diff --git a/.github/logToCs.py b/.github/logToCs.py deleted file mode 100755 index 7befd310a0a76..0000000000000 --- a/.github/logToCs.py +++ /dev/null @@ -1,588 +0,0 @@ -#!/usr/bin/env python3 -# pylint: disable=invalid-name -""" -Convert a log to CheckStyle format. - -Url: https://github.com/mdeweerd/LogToCheckStyle - -The log can then be used for generating annotations in a github action. - -Note: this script is very young and "quick and dirty". - Patterns can be added to "PATTERNS" to match more messages. - -# Examples - -Assumes that logToCs.py is available as .github/logToCs.py. - -## Example 1: - - -```yaml - - run: | - pre-commit run -all-files | tee pre-commit.log - .github/logToCs.py pre-commit.log pre-commit.xml - - uses: staabm/annotate-pull-request-from-checkstyle-action@v1 - with: - files: pre-commit.xml - notices-as-warnings: true # optional -``` - -## Example 2: - - -```yaml - - run: | - pre-commit run --all-files | tee pre-commit.log - - name: Add results to PR - if: ${{ always() }} - run: | - .github/logToCs.py pre-commit.log | cs2pr -``` - -Author(s): - - https://github.com/mdeweerd - -License: MIT License - -""" - -import argparse -import datetime as dt -import json -import os -import re -import sys -import xml.etree.ElementTree as ET # nosec - - -def remove_prefix(string, prefix): - """ - Remove prefix from string - - Provided for backward compatibility. - """ - if prefix and string.startswith(prefix): - return string[len(prefix) :] - return string - - -def convert_notices_to_checkstyle(notices, root_path=None): - """ - Convert annotation list to CheckStyle xml string - """ - root = ET.Element("checkstyle") - for fields in notices: - add_error_entry(root, **fields, root_path=root_path) - return ET.tostring(root, encoding="utf_8").decode("utf_8") - - -def convert_lines_to_notices(lines): - """ - Convert provided message to CheckStyle format. - """ - notices = [] - for line in lines: - fields = parse_message(line) - if fields: - notices.append(fields) - return notices - - -def convert_text_to_notices(text): - """ - Convert provided message to CheckStyle format. - """ - return parse_file(text) - - -# Initial version for Checkrun from: -# https://github.com/tayfun/flake8-your-pr/blob/50a175cde4dd26a656734c5b64ba1e5bb27151cb/src/main.py#L7C1-L123C36 -# MIT Licence -class CheckRun: - """ - Represents the check run - """ - - GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", None) - GITHUB_EVENT_PATH = os.environ.get("GITHUB_EVENT_PATH", None) - - URI = "https://api.github.com" - API_VERSION = "2022-11-28" - ACCEPT_HEADER_VALUE = "application/vnd.github+json" - AUTH_HEADER_VALUE = f"Bearer {GITHUB_TOKEN}" - # This is the max annotations Github API accepts in one go. - MAX_ANNOTATIONS = 50 - - def __init__(self): - """ - Initialise Check Run object with information from checkrun - """ - self.read_event_file() - self.read_meta_data() - - def read_event_file(self): - """ - Read the event file to get the event information later. - """ - if self.GITHUB_EVENT_PATH is None: - raise ValueError("Not running in github workflow") - with open(self.GITHUB_EVENT_PATH, encoding="utf_8") as event_file: - self.event = json.loads(event_file.read()) - - def read_meta_data(self): - """ - Get meta data from event information - """ - self.repo_full_name = self.event["repository"]["full_name"] - pull_request = self.event.get("pull_request") - print("%r", self.event) - if pull_request: - self.head_sha = pull_request["head"]["sha"] - else: - print("%r", self.event) - check_suite = self.event.get("check_suite", None) - if check_suite is not None: - self.head_sha = check_suite["pull_requests"][0]["base"]["sha"] - else: - self.head_sha = None # Can't annotate? - - def submit( # pylint: disable=too-many-arguments - self, - notices, - title=None, - summary=None, - text=None, - conclusion=None, - ): - """ - Submit annotations to github - - See: - https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28 - #update-a-check-run - - :param conclusion: success, failure - """ - # pylint: disable=import-outside-toplevel - import requests # Import here to not impose presence of module - - if self.head_sha is None: - return - - output = { - "annotations": notices[: CheckRun.MAX_ANNOTATIONS], - } - if title is not None: - output["title"] = title - if summary is not None: - output["summary"] = summary - if text is not None: - output["text"] = text - if conclusion is None: - # action_required, cancelled, failure, neutral, success - # skipped, stale, timed_out - if bool(notices): - conclusion = "failure" - else: - conclusion = "success" - - payload = { - "name": "log-to-pr-annotation", - "head_sha": self.head_sha, - "status": "completed", # queued, in_progress, completed - "conclusion": conclusion, - # "started_at": dt.datetime.now(dt.timezone.utc).isoformat(), - "completed_at": dt.datetime.now(dt.timezone.utc).isoformat(), - "output": output, - } - - # Create the check-run - response = requests.post( - f"{self.URI}/repos/{self.repo_full_name}/check-runs", - headers={ - "Accept": self.ACCEPT_HEADER_VALUE, - "Authorization": self.AUTH_HEADER_VALUE, - "X-GitHub-Api-Version": self.API_VERSION, - }, - json=payload, - timeout=30, - ) - print(response.content) - response.raise_for_status() - - -ANY_REGEX = r".*?" -FILE_REGEX = r"\s*(?P\S.*?)\s*?" -FILEGROUP_REGEX = r"\s*(?P\S.*?)\s*?" -EOL_REGEX = r"[\r\n]" -LINE_REGEX = r"\s*(?P\d+?)\s*?" -COLUMN_REGEX = r"\s*(?P\d+?)\s*?" -SEVERITY_REGEX = r"\s*(?Perror|warning|notice|style|info)\s*?" -MSG_REGEX = r"\s*(?P.+?)\s*?" -MULTILINE_MSG_REGEX = r"\s*(?P(?:.|.[\r\n])+)" -# cpplint confidence index -CONFIDENCE_REGEX = r"\s*\[(?P\d+)\]\s*?" - - -# List of message patterns, add more specific patterns earlier in the list -# Creating patterns by using constants makes them easier to define and read. -PATTERNS = [ - # beautysh - # File ftp.sh: error: "esac" before "case" in line 90. - re.compile( - f"^File {FILE_REGEX}:{SEVERITY_REGEX}:" - f" {MSG_REGEX} in line {LINE_REGEX}.$" - ), - # beautysh - # File socks4echo.sh: error: indent/outdent mismatch: -2. - re.compile(f"^File {FILE_REGEX}:{SEVERITY_REGEX}: {MSG_REGEX}$"), - # yamllint - # ##[group].pre-commit-config.yaml - # ##[error]97:14 [trailing-spaces] trailing spaces - # ##[endgroup] - re.compile(rf"^##\[group\]{FILEGROUP_REGEX}$"), # Start file group - re.compile( - rf"^##\[{SEVERITY_REGEX}\]{LINE_REGEX}:{COLUMN_REGEX}{MSG_REGEX}$" - ), # Msg - re.compile(r"^##(?P\[endgroup\])$"), # End file group - # File socks4echo.sh: error: indent/outdent mismatch: -2. - re.compile(f"^File {FILE_REGEX}:{SEVERITY_REGEX}: {MSG_REGEX}$"), - # Emacs style - # path/to/file:845:5: error - Expected 1 space after closing brace - re.compile( - rf"^{FILE_REGEX}:{LINE_REGEX}:{COLUMN_REGEX}:{SEVERITY_REGEX}" - rf"-?\s{MSG_REGEX}$" - ), - # ESLint (JavaScript Linter), RoboCop, shellcheck - # path/to/file.js:10:2: Some linting issue - # path/to/file.rb:10:5: Style/Indentation: Incorrect indentation detected - # path/to/script.sh:10:1: SC2034: Some shell script issue - re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{COLUMN_REGEX}: {MSG_REGEX}$"), - # Cpplint default output: - # '%s:%s: %s [%s] [%d]\n' - # % (filename, linenum, message, category, confidence) - re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{MSG_REGEX}{CONFIDENCE_REGEX}$"), - # MSVC - # file.cpp(10): error C1234: Some error message - re.compile( - f"^{FILE_REGEX}\\({LINE_REGEX}\\):{SEVERITY_REGEX}{MSG_REGEX}$" - ), - # Java compiler - # File.java:10: error: Some error message - re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{SEVERITY_REGEX}:{MSG_REGEX}$"), - # Python - # File ".../logToCs.py", line 90 (note: code line follows) - re.compile(f'^File "{FILE_REGEX}", line {LINE_REGEX}$'), - # Pylint, others - # path/to/file.py:10: [C0111] Missing docstring - # others - re.compile(f"^{FILE_REGEX}:{LINE_REGEX}: {MSG_REGEX}$"), - # Shellcheck: - # In script.sh line 76: - re.compile( - f"^In {FILE_REGEX} line {LINE_REGEX}:{EOL_REGEX}?" - f"({MULTILINE_MSG_REGEX})?{EOL_REGEX}{EOL_REGEX}" - ), - # eslint: - # /path/to/filename - # 14:5 error Unexpected trailing comma comma-dangle - re.compile( - f"^{FILE_REGEX}{EOL_REGEX}" - rf"\s+{LINE_REGEX}:{COLUMN_REGEX}\s+{SEVERITY_REGEX}\s+{MSG_REGEX}$" - ), -] - -# Exceptionnaly some regexes match messages that are not error. -# This pattern matches those exceptions -EXCLUDE_MSG_PATTERN = re.compile( - r"^(" - r"Placeholder pattern" # To remove on first message pattern - r")" -) - -# Exceptionnaly some regexes match messages that are not error. -# This pattern matches those exceptions -EXCLUDE_FILE_PATTERN = re.compile( - r"^(" - # Codespell: (appears as a file name): - r"Used config files\b" - r")" -) - -# Severities available in CodeSniffer report format -SEVERITY_NOTICE = "notice" -SEVERITY_WARNING = "warning" -SEVERITY_ERROR = "error" - - -def strip_ansi(text: str): - """ - Strip ANSI escape sequences from string (colors, etc) - """ - return re.sub(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])", "", text) - - -def parse_file(text): - """ - Parse all messages in a file - - Returns the fields in a dict. - """ - # pylint: disable=too-many-branches,too-many-statements - # regex required to allow same group names - try: - import regex # pylint: disable=import-outside-toplevel - except ImportError as exc: - raise ImportError( - "The 'parsefile' method requires 'python -m pip install regex'" - ) from exc - - patterns = [pattern.pattern for pattern in PATTERNS] - # patterns = [PATTERNS[0].pattern] - - file_group = None # The file name for the group (if any) - full_regex = "(?:(?:" + (")|(?:".join(patterns)) + "))" - results = [] - - for fields in regex.finditer( - full_regex, strip_ansi(text), regex.MULTILINE | regex.IGNORECASE - ): - if not fields: - continue - result = fields.groupdict() - - if len(result) == 0: - continue - - severity = result.get("severity", None) - file_name = result.get("file_name", None) - confidence = result.pop("confidence", None) - new_file_group = result.pop("file_group", None) - file_endgroup = result.pop("file_endgroup", None) - message = result.get("message", None) - - if new_file_group is not None: - # Start of file_group, just store file - file_group = new_file_group - continue - - if file_endgroup is not None: - file_group = None - continue - - if file_name is None: - if file_group is not None: - file_name = file_group - result["file_name"] = file_name - else: - # No filename, skip - continue - else: - if EXCLUDE_FILE_PATTERN.search(file_name): - # This file_name is excluded - continue - - if message is not None: - if EXCLUDE_MSG_PATTERN.search(message): - # This message is excluded - continue - - if confidence is not None: - # Convert confidence level of cpplint - # to warning, etc. - confidence = int(confidence) - - if confidence <= 1: - severity = SEVERITY_NOTICE - elif confidence >= 5: - severity = SEVERITY_ERROR - else: - severity = SEVERITY_WARNING - - if severity is None: - severity = SEVERITY_ERROR - else: - severity = severity.lower() - - if severity in ["info", "style"]: - severity = SEVERITY_NOTICE - - result["severity"] = severity - - results.append(result) - - return results - - -def parse_message(message): - """ - Parse message until it matches a pattern. - - Returns the fields in a dict. - """ - for pattern in PATTERNS: - fields = pattern.match(message, re.IGNORECASE) - if not fields: - continue - result = fields.groupdict() - if len(result) == 0: - continue - - if "confidence" in result: - # Convert confidence level of cpplint - # to warning, etc. - confidence = int(result["confidence"]) - del result["confidence"] - - if confidence <= 1: - severity = SEVERITY_NOTICE - elif confidence >= 5: - severity = SEVERITY_ERROR - else: - severity = SEVERITY_WARNING - result["severity"] = severity - - if "severity" not in result: - result["severity"] = SEVERITY_ERROR - else: - result["severity"] = result["severity"].lower() - - if result["severity"] in ["info", "style"]: - result["severity"] = SEVERITY_NOTICE - - return result - - # Nothing matched - return None - - -def add_error_entry( # pylint: disable=too-many-arguments - root, - severity, - file_name, - line=None, - column=None, - message=None, - source=None, - root_path=None, -): - """ - Add error information to the CheckStyle output being created. - """ - file_element = find_or_create_file_element( - root, file_name, root_path=root_path - ) - error_element = ET.SubElement(file_element, "error") - error_element.set("severity", severity) - if line: - error_element.set("line", line) - if column: - error_element.set("column", column) - if message: - error_element.set("message", message) - if source: - # To verify if this is a valid attribute - error_element.set("source", source) - - -def find_or_create_file_element(root, file_name: str, root_path=None): - """ - Find/create file element in XML document tree. - """ - - if root_path is not None: - file_name = remove_prefix(file_name, root_path) - for file_element in root.findall("file"): - if file_element.get("name") == file_name: - return file_element - file_element = ET.SubElement(root, "file") - file_element.set("name", file_name) - return file_element - - -def main(): - """ - Parse the script arguments and get the conversion done. - """ - parser = argparse.ArgumentParser( - description="Convert messages to Checkstyle XML format." - ) - parser.add_argument( - "input", help="Input file. Use '-' for stdin.", nargs="?", default="-" - ) - parser.add_argument( - "output", - help="Output file. Use '-' for stdout.", - nargs="?", - default="-", - ) - parser.add_argument( - "-i", - "--in", - dest="input_named", - help="Input filename. Overrides positional input.", - ) - parser.add_argument( - "-o", - "--out", - dest="output_named", - help="Output filename. Overrides positional output.", - ) - parser.add_argument( - "--root", - metavar="ROOT_PATH", - help="Root directory to remove from file paths." - " Defaults to working directory.", - default=os.getcwd(), - ) - parser.add_argument( - "--github-annotate", - action=argparse.BooleanOptionalAction, - help="Annotate when in Github workflow.", - # Currently disabled, - # Future: (os.environ.get("GITHUB_EVENT_PATH", None) is not None), - default=False, - ) - - args = parser.parse_args() - - if args.input == "-" and args.input_named: - with open( - args.input_named, encoding="utf_8", errors="surrogateescape" - ) as input_file: - text = input_file.read() - elif args.input != "-": - with open( - args.input, encoding="utf_8", errors="surrogateescape" - ) as input_file: - text = input_file.read() - else: - text = sys.stdin.read() - - root_path = os.path.join(args.root, "") - - try: - notices = convert_text_to_notices(text) - except ImportError: - notices = convert_lines_to_notices(re.split(r"[\r\n]+", text)) - - checkstyle_xml = convert_notices_to_checkstyle( - notices, root_path=root_path - ) - - if args.output == "-" and args.output_named: - with open(args.output_named, "w", encoding="utf_8") as output_file: - output_file.write(checkstyle_xml) - elif args.output != "-": - with open(args.output, "w", encoding="utf_8") as output_file: - output_file.write(checkstyle_xml) - else: - print(checkstyle_xml) - - if args.github_annotate: - checkrun = CheckRun() - checkrun.submit(notices) - - -if __name__ == "__main__": - main() diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index d0cdcb90ef38a..1ae4d3387f8fe 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -7,7 +7,6 @@ jobs: pre-commit: runs-on: ubuntu-latest env: - LOG_TO_CS: .github/logToCs.py RAW_LOG: pre-commit.log CS_XML: pre-commit.xml steps: @@ -37,7 +36,7 @@ jobs: with: cache: pip python-version: "3.11" - - run: python -m pip install pre-commit regex + - run: python -m pip install pre-commit # Restore previous cache of precommit - uses: actions/cache/restore@v4 with: @@ -102,19 +101,12 @@ jobs: pre-commit run --hook-stage manual -a php-cs-with-cache | tee -a ${RAW_LOG} ls -l ~/.cache/pre-commit/ - # If error, we convert log in the checkstyle format - - name: Convert Raw Log to CheckStyle format - if: ${{ failure() }} - run: | - python ${LOG_TO_CS} ${RAW_LOG} ${CS_XML} - # Annotate the git sources with the log messages - - name: Annotate Source Code with Messages - uses: staabm/annotate-pull-request-from-checkstyle-action@v1 + - name: Convert Raw Log to Annotations + uses: mdeweerd/logToCheckStyle@v2024.2.9 if: ${{ failure() }} with: - files: ${{ env.CS_XML }} - notices-as-warnings: true # optional - prepend-filename: true # optional + in: ${{ env.RAW_LOG }} + # Save the precommit cache - uses: actions/cache/save@v4 if: ${{ ! cancelled() }} diff --git a/ChangeLog b/ChangeLog index f6333556481d0..a222f2206ba9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,139 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 18.0.6 compared to 18.0.5 ***** +FIX: 16.0 - parent company gets emptied when updating a third party from the card in edit mode (#28269) +FIX: 16.0 - the e-mail templates configured in the notification module are not used if the recipient is a fixed e-mail address (#29407) +FIX: 17.0: $num doesn't take trigger-modified newref into account, leading to inconsistencies if BILL_SUPPLIER_VALIDATE changes the invoice's ref (#28684) +FIX: 17.0: fatal when updating recurring supplier invoice line with php8 ($remise_percent is '' instead of 0) (#31713) +FIX: 17.0: supplier invoice template card: buyer and seller swapped in VAT-related function calls (probably a copy-paste from customer invoice templates) (#31446) +FIX: #24265 regression cannot see all product on takepos (#28753) +FIX: #25853 Thirdparty Massaction (#25868) +FIX: #28205 +FIX: #28251 Fixing subpermission name on api_multicurrencies.class.php (#28252) +FIX: #28369 +FIX: #28518 (#28520) +FIX: #28978 FIX: #28976 +FIX: #29029 Impossible to delete an order line +FIX: #29114 Missing contact term in intervention +FIX: #29114 Translate contact term in intervention +FIX: #29439 incomplete API return (#29796) +FIX: #29496 filtering a record should not hide its child not filtered +FIX: #30010 Use conf TICKET_MESSAGE_MAIL_INTRO instead of translation key (#30081) +FIX: #30274 Add the include before executing dolibarr_set_const (#30320) +FIX: #30467 +FIX: #30768 allocate the correct invoice_line_id to the element timespent (#30769) +FIX: Accountancy export with file or not +FIX: Accountancy - Generate entries of expense report with localtax (#30411) +FIX: Accountancy - Not trunc id_import +FIX: accounting FEC import (Issue #28306) (#29414) +FIX: Add new hidden conf "DISABLE_QTY_OVERWRITTEN" (#28523) +FIX: Add same security test when uploading files from API than from GUI (#31114) +FIX: Amount of localtaxes in foreign currency was wrong on screen and PDF +FIX: an error in a complex else condition +FIX: ASSET: annual depreciation starting year (Again ;-)) #26084 (#30040) +FIX: avoid error "Column 'entity' in where clause is ambiguous" (#28270) +FIX: avoid from re-initializing array result on nested hook getEntity (#30626) +FIX: avoid php warnings (#29247) +FIX: avoid to delete "lock" and "unlock" files +FIX: avoid Unknown column 'pfp.ref_fourn' (#28145) +FIX: background color for enabled modules (#29378) +FIX: Backport fix fatal error on price with some truncating setup +FIX: Backport page inventory.php from v18 to fix pagination bugs causing data loss (#29688) +FIX: back to page on error in contact card (#29627) +FIX: Bad calculation of $nbtotalofrecord (#30183) +FIX: box_actions.php still uses fk_user_done which no longer exists (#31190) +FIX: can validate shipment without stock movement (#31780) +FIX: Condition on newDateLimReglement +FIX: Conflict with autoload (#30399) +FIX: const WORKFLOW_RECEPTION_CLASSIFY_NEWD_INVOICE (#31601) +FIX: contact/address title is always "New Contact/Address" even if the contact/address already exists (#29581) +FIX: Display the date according to user language on substitutions (#29510) +FIX: Display the real_PMP on inventory when its value is equal to 0 (#22291) +FIX: Don't display column when it's out of date (#28271) +FIX: email templates for expense report not visible +FIX: Error mesg show untranslated extrafield name (#30227) +FIX: Error message overwrote when a error occurs during update of product multilangs (#30841) +FIX: Error When cloning fourn price no default value for tva_tx (#28368) +FIX: executeHooks $object default value (#29647) +FIX: expedition PDF models using units labels (#30358) +FIX: Extrafield following between rec invoice and classic invoice (#31445) +FIX: fatal error on loading pictures in attached documents of an event (#30553) +FIX: fatal error Unsupported operand types when recording load payment +FIX: Fix bug select columns and access to the public ticket list from the public ticket card (case when we have connected to another client before, the track id stocked in session overwrite the new track id from the public ticket card) (#31000) +FIX: Fix create shipping with product who have negative stocks on warehouse but the negative stock transfer is allowed (#26217) +FIX: Fix save directory for invoice ODT and multientities +FIX: group by qty in product margin tab (#29853) +FIX: Hierarchy Employee view do not filter on employee = 1 (#29496) +FIX: if you call fetchLines several times, your $object->lines contains duplicates (#31167) +FIX: If you have no stock of your product, an error is displayed when you delete the reception. (#31504) +FIX: incorrect page numbering in PDF #29458 (#29476) +FIX: inventoryDeletePermission id define twice +FIX: issue on action set condition in particular when you set a deposi… (#31518) +FIX: issue to get the right files exported in Quadratrus export.php (#30004) +FIX: lang output for sales representative on PDF (#30469) +FIX: late order search option (#30692) and propal (#30687) +FIX: lettering (auto) for invoice deposit with company discount (#29633) +FIX: made invalid code shape error more user friendly (#29498) +FIX: Merge of thirdparties must also move uploaded files +FIX: missing entity parameter for ajax_constantonoff +FIX: missing hide "new" button where "product" or "service" module are disable +FIX: mo cloning (#29686) +FIX: modification date from label in accounting bookkeeping list (#30038) +FIX: Move the trigger for delete order line before the SQL request +FIX: multiple problems with multicompany +FIX: mysql error during dump for enable sandbox M999999 (#31116) +FIX: notification: error 500 in fixed emails due to a bad copy/paste (#29580) +FIX: notification module: for supplier orders (any of the 3 triggers), user can choose an e-mail template in conf, but the conf is not used when sending the notification (#28216) +FIX: Not qualified lines for reception (#29473) +FIX: not redirect when error occurs on updating card (#29388) +FIX: Not trancate the multicurrency rate shown on cards (even if the global MAIN_MAX_DECIMALS_SHOWN is set to 0) (#28211) +FIX: on change ref for bank account attachment are lost (#30529) +FIX: Option MAIN_DOC_USE_TIMING can be a string with date format +FIX: orders to bill menu (#30179) +FIX: Payment on customer invoice - Remove accountid in url if empty for apply default value (#28156) +FIX: PDF Fatal error : Backport fix from #23972 +FIX: PDF Translations Extrafields +FIX: permission on payment file of a tax +FIX: php8: Fatal when empty $tmpvat is an empty string (no silent conversion to '0' when used in arithmetic operations) (#29451) +FIX: PHP 8 warning on output of successful cronjob (#29922) +FIX: PHP exception on getSpecialCode (#29646) +FIX: php warning global conf (#29478) +FIX: pos: invoice date incorrectly set because of timezome mismatches (reverts #36e91da) (#30184) +FIX: public project form return an error if SOCIETE_EMAIL_UNIQUE (#29942) +FIX: purge files cron: php warnings when rest module enabled (#30919) +FIX: PUT /thirdparties/{id} and PUT /contacts/{id} should throw exception if update returns < 0 (#29596) +FIX: Regression #29340 +FIX: Repair the replenishment list (#29336) +FIX: REPLENISH MANY FOURN WHEN ORDER ALREADY CREATE (#29710) +FIX: round capital societe (#29211) +FIX: search and add extrafields to tasks when conf disabled (#29542) +FIX: show preview pdf list expensereport (#31694) +FIX: sometimes a string type instead integer is return, why ? +FIX: Special code is now transmitted by args only in order supplier (#28546) (#28619) +FIX: SQL syntax error in DDLUpdateField +FIX: subscription must be editable when accounting isn't reconciled (#28469) +FIX: substitutions THIRDPARTY_XXX are not available for actioncomm reminders (#31385) +FIX: Supplier Order search on date valid (#30448) +FIX: supplier price duplicate entry on update supplier product ref (#29290) +FIX: syntax error +FIX: TakePOS | Add product / Delete line of existing invoice +FIX: Ticket new message notification sent twice +FIX: transfer in accountancy for expense reports. +FIX: Unsigned propal having signing date (#29825) +FIX: Update asset.class.php +FIX: update date_echeance of supplier invoices when we update invoice date in the past (#29886) +FIX: use $conf->browser->os instead +FIX: use price() to display qty on a product's stats tab to avoid showing too many decimals when rounding errors are possible (#31165) +FIX: User List - Function is show in wrong column when module HRM enabled (#30186) +fix: when invoice is created by WORKFLOW_ORDER_AUTOCREATE_INVOICE on ORDER_NEW, the invoice must have the default bank account of the thirdparty is it's empty on order (#29462) +FIX: when qty is not an integer, apply price() (#31138) +FIX: Wrong currency shown in TakePOS payment page +FIX: wrong shortcut key for macintosh +FIX: wrong sql request with product category filter +FIX: wrong stock permission number + + ***** ChangeLog for 18.0.5 compared to 18.0.4 ***** FIX: 17.0: deprecated field should only be a fallback FIX: 17.0 - php8 warnings: test for $field existence before checking if it is null or empty @@ -14,7 +147,7 @@ FIX: Accountancy - Level 3 of binding not working on supplier side (#27462) FIX: Accounting files export - Use th instead of td on all title columns (#28003) FIX: add action update_extras to don card FIX: Adding hooks init -FIX: Adding the $encode parrameter to recursive _replaceHtmlWithOdtTag() utilisation +FIX: Adding the $encode parameter to recursive _replaceHtmlWithOdtTag() utilisation FIX: add new hook context for mo production card (#28037) FIX: avoid from re-initializing result on nested hook getEntity (#27799) FIX: avoid sql error (issue #26342) @@ -273,7 +406,7 @@ NEW: Accountancy - Manage intra-community VAT on supplier invoices - FPC22 NEW: Accountancy - iSuiteExpert export model NEW: Accountancy - Quadratus export with attachments in accountancy export NEW: Accountancy - Can filter on a custom group of accounts. Perf or ledger list. -NEW: Can upload a file with drag and drop on purchase invoice, vats, salaries and social contributions +NEW: Can upload a file with drag and drop on purchase invoice, vats, salaries and social contributions NEW: Authentication: #22740 add OpenID Connect impl NEW: Authentication: add experimental support for Google OAuth2 connexion NEW: Authentication: can now edit service name for OAuth token @@ -366,7 +499,7 @@ NEW: No overwrite of optionals during put() contact NEW: Notifications: add Customer Order delivered (ORDER_NEW) in module Notification NEW: Notifications: for Sign or Refused Propal from Online Page NEW: Now we can edit amount on VAT and salaries clone action -NEW: only get openned contact from liste_contact function, to not have acces to closed contact as mail receiver +NEW: only get open contact from liste_contact function, to not have access to closed contact as mail receiver NEW: Option to manage deposit slips for more payment modes (not only NEW: Option to show column for field and line selection on the left NEW: Orders: add sub total in order list det @@ -462,13 +595,13 @@ WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * Minimal PHP version is now PHP 7.1 instead of PHP 7.0 -* Sensitive datas like keys in setup pages, that need encyption (for example the API keys of users, the CRON security key, the keys into the Stripe module, or +* Sensitive datas like keys in setup pages, that need encyption (for example the API keys of users, the CRON security key, the keys into the Stripe module, or external modules setup pages that store sensitive keys or password), are using the $dolibarr_main_instance_unique_id as part of the key for encryption. So, -if you restore or duplicate the data from another instance dump, you must also update this parameter in ther conf.php file to allow decryption in the new instance, or +if you restore or duplicate the data from another instance dump, you must also update this parameter in ther conf.php file to allow decryption in the new instance, or better, you must reenter the sensitive data into the setup pages of the new instance to resave them correctly. -Note that to find all the parameters that are encrypted into the setup database, you can do a "SELECT * FROM llx_const WHERE value LIKE '%dolcrypt%';" +Note that to find all the parameters that are encrypted into the setup database, you can do a "SELECT * FROM llx_const WHERE value LIKE '%dolcrypt%';" * The deprecated method "escapeunderscore()" of database handlers has been removed. You must use "escapeforlike()" instead. -* The method "nb_expedition()" has been renamed into "countNbOfShipments()" +* The method "nb_expedition()" has been renamed into "countNbOfShipments()" * Revert default type of hooks. Default is now 'addreplace' hooks (and exception become 'output' hooks, that become deprecated). * Deprecated property libelle removed from entrepot class. * The type 'text' in ->fields property does not accept html content anymore. Use the type 'html' for that. @@ -477,6 +610,117 @@ Note that to find all the parameters that are encrypted into the setup database, * The method getCheckOption() and deleteCPUser() of class Holiday has been removed (it was not used) +***** ChangeLog for 17.0.4 compared to 17.0.3 ***** +FIX: $this->newref already exists and could have been modified by trigger but we still use a local variable for the filesystem-based renaming +FIX: 16.0 only, backport fix for SQL error on global search product +FIX: 17.0: deprecated field should only be a fallback +FIX: 17.0 PHP8: supplier invoice class: +FIX: 17.0 - php8 warnings: test for $field existence before checking is_null +FIX: #25399 (#26694) +FIX: #25458 intervention localizations (backport v17) (#26757) +FIX: #25580 install/step1.php - wrong command line argument used for $main_dir (#25581) +FIX: #25919 +FIX: #25934 #25929 +FIX: #26100 - Ticket - On edit, list of closed project must be excluded (#26223) +FIX: #26195 - Various payment - List of project excluded those assigned to third parties (#26222) +FIX: #26735 FIX: #26994 +FIX: #27262 Recurrent invoice - user to string conversion +FIX: Accountancy - Possibility to write in bookkeeping expense report operation with some line not bound (#26545) +FIX: Accountancy - Update Quadra export format +FIX: add action update_extras to don card +FIX: add_customer_ref_on_linked_shipment (#26349) +FIX: add display of an error when attempting to delete a committed transaction (#26573) +FIX: Adding the $encode parameter to recursive _replaceHtmlWithOdtTag() utilisation +FIX: add warning in the changelog +FIX: avoid php8 warnings (#25596) +FIX: avoid warning : Cannot use a scalar value as an array (#26437) +FIX: Backport memory fix for fatal error when +100000 products +FIX: backport SQL error on global search product +FIX: bad accountancy code autoselection for supplier ventilation +FIX: Bad calculation of localtax when price_base_type not defined. +FIX: bad check return for sendfile +FIX: bad from and to +FIX: Bad value of accounting account shown in list. Edit fails. +FIX: Barcode header cell not well displayed +FIX: Bar code verification should be done by entity because generation does (#28087) +FIX: # Bug Estimated Stock at date value in V14 (#26479) +FIX: Can't access to rec supplier invoice card +FIX: Can't delete a fourn commande row if a commande ligne is linked +FIX: check tva_tx before comparing price_min_ttc (#25220) +FIX: commande context (#26497) +FIX: compare the result of the send mail file function +FIX: could not delete a fourn commande row if a commande ligne is linked +FIX: count cronjob list differs of lines shown nb +FIX: crabe PDF is generating in conf->entity instead of object->entity +FIX: creation of invoice from contract with discount lines +FIX: CVE-2024-23817 (#28089) +FIX: dir output path for ODT models on reception card +FIX: disable pointer events on jQuery-UI tooltips to prevent a glitch (fast-blinking tooltip) +FIX: Error handling for computed values on import (#24897) +FIX: escape HTML tags in return value of getFullName() (#26735) +FIX: export FEC +FIX: Fatal error converting object of class User to string (php8) +FIX: fatal error with bad definition of dictionaries +FIX: filter by entity on contact is missing +FIX: Fix supplier invoice security check +FIX: HTML in ODT templates (#26181) +FIX: include +FIX: label +FIX: line special_code never saved (#28051) +FIX: link to create purchase order from sale order +FIX: menu auguria +FIX: message order in ticket public view is not coherent with tickets events tab +FIX: Missing begin transaction when updating supplier recurring invoice +FIX: missing contact_id for the trigger +FIX: Missing error message on CommandeFourn creation +FIX: missing fk_account situation invoice +FIX: missing project entity filter (Issue #26243) (#26247) +FIX: modification of complementary attributes in commercial proposals +FIX: modification of complementary attributes in invoices (#26180) +FIX: more correctly parse the select part to be replaced in sql queries +FIX: not create/update extrafields for visibility 0,2 and 5 +FIX: notification information on intervention validated confirmation message (v17+) +FIX: payment card: misleading message when delete button disabled +FIX: payment : language is not propagated to following pages +FIX: pdf cornas page head multicell width (backport v17) +FIX: possible inconsistency between llx_ecm_files and file system when BILL_SUPPLIER_VALIDATES changes ref +FIX: Prices visible on TakePOS KO with multiprices support +FIX: product list accounting length +FIX: propal list : warning if product module is not enabled (#25583) +FIX: Propal's negative quantities +FIX: Quick search Intervention redirect to wrong page +FIX: reception odt dir output path +FIX: regression on rounding stocks fields on product list +FIX_reload_linked_objects_on_propal_closeas +FIX: Return right content type +FIX: right access on salary card and tabs +FIX: rights paymentsc paiementcharge +FIX: same broken feature as v18 (Multicompany) +FIX: Save user modif id when changing a contact status +FIX: search by ref & rowid in don list +FIX: search by thirdparty in don list +FIX: special_code update line keep old value. (#26819) +FIX: SQL concatenation error +FIX: SQL request parenthesis +FIX: substitute project variables in invoice documents (#26445) +FIX: Suppliers addlines never have VAT if buyprice for this supplier +FIX: [TAKEPOS] display prices with or without taxes depending on setup (TAKEPOS_CHANGE_PRICE_HT) +FIX: TakePOS receipt preview in admin #25648 +FIX: template invoice list extrafield filters (backport v17) (#26227) +FIX: thirdparty object in proposal card is not loaded +FIX: too long output +FIX: translation button +FIX: use event.key instead event.which to avoid keyboard difference +FIX: Use of line->insert instead of line->create +FIX: user creation when LDAP is configured (#26332) +FIX: Use the wrong logo size on PDF +FIX: v17: Param $notrigger in $societe->create() causes method to return true regardless of actual result of database functions (#26499) +FIX: warning param $lineID getSpecialCode is negatif (#26826) +FIX: warning php8.2 undefined_array_key (#26830) +FIX: warning when Workboard Responses display non numeric strings +FIX: Wrong backtopage given for the stocktransfer button from the stocktransfer list (#26271) +FIX: wrong place of trigger delete + ***** ChangeLog for 17.0.3 compared to 17.0.2 ***** FIX: #20304 propaldates update FIX: #24508 Label not reported when creating a supplier invoice template (#25340) @@ -870,7 +1114,7 @@ WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * Minimal PHP version is now PHP 7.0 instead of PHP 5.6 * Core has introduced a Universal Filter Syntax for seach criteria. Example: ((((field1:=:value1) OR (field2:in:1,2,3)) AND ...). In rare case, some filters - could be provided by URL parameters. For such cases (societe/ajax/company.php), use of Universal Filter Syntax become mandatory. + could be provided by URL parameters. For such cases (societe/ajax/company.php), use of Universal Filter Syntax become mandatory. * The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product->getNomUrl() * Trigger ORDER_SUPPLIER_DISPATCH is removed, use ORDER_SUPPLIER_RECEIVE and/or LINEORDER_SUPPLIER_DISPATCH instead. * All functions fetch_all() have been set to deprecated for naming consitency, use fetchAll() instead. @@ -948,7 +1192,7 @@ FIX: #23019 Impossible to add task times to an existing draft invoice FIX: #23072 FIX: #23075 FIX: #23087 -FIX: #23115 +FIX: #23115 FIX: #23116 FIX: #23117 FIX: #23281 @@ -2500,7 +2744,7 @@ NEW: add quick dropdown menu in top right menu (experimental with MAIN_USE_TOP_M NEW: add region in export companies and contacts NEW: add rights on margin info on invoice list NEW: add search param for close date on order list -NEW: add show preview for mail attachement on form mail +NEW: add show preview for mail attachment on form mail NEW: add State/Province origin for products NEW: add the workflow interaction close intervention on closing ticket NEW: add tracking number in list and search_all items @@ -3885,7 +4129,7 @@ FIX: access to public interface when origin email has an alias. FIX: Alias name is not into the email recipient label. FIX: allow standalone credit note even if no invoice FIX: an admin can not access his own permissions after enabling advanced permissions -FIX: Attachement of linked files on ticket when sending a message +FIX: Attachment of linked files on ticket when sending a message FIX: avoid non numeric warning FIX: Bad currency var used in stripe for connect FIX: Bad list of ticket on public interface for ticket emailcollector @@ -4681,7 +4925,7 @@ NEW: hidden option to define an invoice template for each invoice type NEW: Highlight lines on lists when they are checked NEW: Notification module support expense report+holiday validation and approval NEW: On customer/supplier card, add simple tooltip to amount boxes -NEW: Page to check if the operations/items created between two dates have attached item(s) and possibility to download all attachements +NEW: Page to check if the operations/items created between two dates have attached item(s) and possibility to download all attachments NEW: possibility to add all rights of all modules in one time NEW: redirect if only one result on global search on card NEW: Permission to ignore price min @@ -6125,7 +6369,7 @@ NEW: No external check of version without explicit click in about page. NEW: ODT docs for USER USERGROUP CONTRACT and PRODUCT class NEW: odt usergroup NEW: On invoices generated by template, we save if invoice come from a source template. -NEW: option to copy into attachement files of events, files send by mail (with auto event creation) +NEW: option to copy into attachment files of events, files send by mail (with auto event creation) NEW: PDF with numbertoword NEW: Permit multiple file upload in linked documents NEW: PHP 7.1 compatibility diff --git a/dev/examples/zapier/package.json b/dev/examples/zapier/package.json index 8852928771f13..ef70b2af8fdc6 100644 --- a/dev/examples/zapier/package.json +++ b/dev/examples/zapier/package.json @@ -15,7 +15,7 @@ "npm": ">=5.6.0" }, "dependencies": { - "zapier-platform-core": "11.3.1" + "zapier-platform-core": "15.0.1" }, "devDependencies": { "mocha": "^5.2.0", diff --git a/dev/setup/codesniffer/ruleset.xml b/dev/setup/codesniffer/ruleset.xml index 5b7dade0a981e..ce59db1866585 100644 --- a/dev/setup/codesniffer/ruleset.xml +++ b/dev/setup/codesniffer/ruleset.xml @@ -5,20 +5,20 @@ - build/html - build/aps - dev/tools/test/namespacemig - - documents - htdocs/core/class/lessc.class.php - htdocs/custom - htdocs/includes - htdocs/install/doctemplates/websites - htdocs/conf.php - */nltechno* - source - .git - .cache + + + /build/(html|aps)/ + /dev/tools/test/namespacemig/ + + /documents/ + /htdocs/core/class/lessc\.class\.php + /htdocs/(custom|includes)/ + /htdocs/install/doctemplates/websites + /htdocs/([^/]+/)?conf\.php + */nltechno* + /source/ + /\.git/ + /\.cache/ diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index 30020319813c6..580e1797d88c4 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -538,7 +538,7 @@ // Show first line of a break print ''; - print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; + print ''.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').''; print ''; $displayed_account = $root_account_number; diff --git a/htdocs/accountancy/bookkeeping/export.php b/htdocs/accountancy/bookkeeping/export.php index 7f95698caa5ed..e7c97b475b9d6 100644 --- a/htdocs/accountancy/bookkeeping/export.php +++ b/htdocs/accountancy/bookkeeping/export.php @@ -1190,7 +1190,6 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $objectstatic = new Facture($db); $objectstatic->fetch($line->fk_doc); - //$modulepart = 'facture'; $filename = dol_sanitizeFileName($line->doc_ref); $filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); @@ -1202,11 +1201,10 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $objectstatic = new FactureFournisseur($db); $objectstatic->fetch($line->fk_doc); - //$modulepart = 'invoice_supplier'; $filename = dol_sanitizeFileName($line->doc_ref); - $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($line->fk_doc, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); - $subdir = get_exdir($objectstatic->id, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); + $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($line->fk_doc, 2, 0, 0, $objectstatic, $objectstatic->element).dol_sanitizeFileName($line->doc_ref); + $subdir = get_exdir($objectstatic->id, 2, 0, 0, $objectstatic, $objectstatic->element).dol_sanitizeFileName($line->doc_ref); $documentlink = $formfile->getDocumentsLink($objectstatic->element, $subdir, $filedir); } elseif ($line->doc_type == 'expense_report') { $langs->loadLangs(array('trips')); @@ -1214,7 +1212,6 @@ require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; $objectstatic = new ExpenseReport($db); $objectstatic->fetch($line->fk_doc); - //$modulepart = 'expensereport'; $filename = dol_sanitizeFileName($line->doc_ref); $filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index a8956a5e9a9bd..4583e58fd070e 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1,8 +1,8 @@ * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2013-2023 Alexandre Spangaro - * Copyright (C) 2022 Lionel Vessiller + * Copyright (C) 2013-2024 Alexandre Spangaro + * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2016-2017 Laurent Destailleur * Copyright (C) 2018-2021 Frédéric France * Copyright (C) 2022 Progiseize @@ -479,7 +479,7 @@ setEventMessages($object->error, $object->errors, 'errors'); $error++; break; - } elseif (isset($object->date_validation) || $object->date_validation != '') { + } elseif (isset($object->date_validation) && $object->date_validation != '') { setEventMessages($langs->trans("ValidatedRecordWhereFound"), null, 'errors'); $error++; break; @@ -932,7 +932,7 @@ print $form->selectDate($search_date_modification_start, 'search_date_modification_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); print ''; print '
'; - print $form->selectDate($search_date_modification_end, 'search_date_modification_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print $form->selectDate($search_date_modification_end, 'search_date_modification_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); print '
'; print ''; } @@ -1293,7 +1293,7 @@ } if (!empty($arrayfields['t.import_key']['checked'])) { - print ''.$obj->import_key."\n"; + print ''.$obj->import_key."\n"; if (!$i) { $totalarray['nbfield']++; } diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 9aa6c74e744ed..abdf358ccfc1c 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -2,7 +2,7 @@ /* Copyright (C) 2016 Neil Orley * Copyright (C) 2013-2016 Olivier Geffroy * Copyright (C) 2013-2020 Florian Henry - * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2013-2024 Alexandre Spangaro * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -446,7 +446,7 @@ setEventMessages($object->error, $object->errors, 'errors'); $error++; break; - } elseif (isset($object->date_validation) || $object->date_validation != '') { + } elseif (isset($object->date_validation) && $object->date_validation != '') { setEventMessages($langs->trans("ValidatedRecordWhereFound"), null, 'errors'); $error++; break; @@ -1207,7 +1207,7 @@ } if (!empty($arrayfields['t.import_key']['checked'])) { - print ''.$line->import_key."\n"; + print ''.$line->import_key."\n"; if (!$i) { $totalarray['nbfield']++; } diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index c515b7230b22f..d986e5c0d56f8 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -5,7 +5,7 @@ * Copyright (C) 2015 Florian Henry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Pierre-Henry Favre - * Copyright (C) 2016-2023 Alexandre Spangaro + * Copyright (C) 2016-2024 Alexandre Spangaro * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2013-2017 Olivier Geffroy * Copyright (C) 2017 Elarifr. Ari Elbaz @@ -385,11 +385,12 @@ public function export(&$TData, $formatexportset, $withAttachment = 0, $download // directory already created when module is enabled $outputDir .= '/export'; $outputDir .= '/'.dol_sanitizePathName($formatexportset); - if (!dol_is_dir($outputDir)) { - if (dol_mkdir($outputDir) < 0) { - $this->errors[] = $langs->trans('ErrorCanNotCreateDir', $outputDir); - return -1; - } + } + + if (!dol_is_dir($outputDir)) { + if (dol_mkdir($outputDir) < 0) { + $this->errors[] = $langs->trans('ErrorCanNotCreateDir', $outputDir); + return -1; } } diff --git a/htdocs/accountancy/class/accountancyimport.class.php b/htdocs/accountancy/class/accountancyimport.class.php index 5f4d76bc4c55f..ef22ceafa52db 100644 --- a/htdocs/accountancy/class/accountancyimport.class.php +++ b/htdocs/accountancy/class/accountancyimport.class.php @@ -93,10 +93,9 @@ public function cleanValue(&$arrayrecord, $listfields, $record_key) public function computeAmount(&$arrayrecord, $listfields, $record_key) { // get fields indexes - $field_index_list = array_flip($listfields); - if (isset($field_index_list['debit']) && isset($field_index_list['credit'])) { - $debit_index = $field_index_list['debit']; - $credit_index = $field_index_list['credit']; + if (isset($listfields['b.debit']) && isset($listfields['b.credit'])) { + $debit_index = $listfields['b.debit']; + $credit_index = $listfields['b.credit']; $debit = floatval($arrayrecord[$debit_index]['val']); $credit = floatval($arrayrecord[$credit_index]['val']); @@ -123,9 +122,8 @@ public function computeAmount(&$arrayrecord, $listfields, $record_key) */ public function computeDirection(&$arrayrecord, $listfields, $record_key) { - $field_index_list = array_flip($listfields); - if (isset($field_index_list['debit'])) { - $debit_index = $field_index_list['debit']; + if (isset($listfields['b.debit'])) { + $debit_index = $listfields['b.debit']; $debit = floatval($arrayrecord[$debit_index]['val']); if (!empty($debit)) { diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index 67eee9022b51d..0c22e2041a032 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -51,6 +51,10 @@ class Lettering extends BookKeeping 'table' => 'societe_remise_except', 'fk_doc' => 'fk_facture_source', 'fk_link' => 'fk_facture', + 'fk_line_link' => 'fk_facture_line', + 'table_link_line' => 'facturedet', + 'fk_table_link_line' => 'rowid', + 'fk_table_link_line_parent' => 'fk_facture', 'prefix' => 'a', 'is_fk_link_is_also_fk_doc' => true, ), @@ -73,6 +77,10 @@ class Lettering extends BookKeeping 'table' => 'societe_remise_except', 'fk_doc' => 'fk_invoice_supplier_source', 'fk_link' => 'fk_invoice_supplier', + 'fk_line_link' => 'fk_invoice_supplier_line', + 'table_link_line' => 'facture_fourn_det', + 'fk_table_link_line' => 'rowid', + 'fk_table_link_line_parent' => 'fk_facture_fourn', 'prefix' => 'a', 'is_fk_link_is_also_fk_doc' => true, ), @@ -765,10 +773,26 @@ public function getLinkedDocumentByGroup($document_ids, $doc_type) $link_by_element = array(); $element_by_link = array(); foreach ($doc_type_info['linked_info'] as $linked_info) { - $sql = "SELECT DISTINCT tl2." . $linked_info['fk_link'] . " AS fk_link, tl2." . $linked_info['fk_doc'] . " AS fk_doc"; - $sql .= " FROM " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl2 ON tl2." . $linked_info['fk_link'] . " = tl." . $linked_info['fk_link']; - $sql .= " WHERE tl." . $linked_info['fk_doc'] . " IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; + if (empty($linked_info['fk_line_link'])) { + $sql = "SELECT DISTINCT tl2.".$linked_info['fk_link']." AS fk_link, tl2.".$linked_info['fk_doc']." AS fk_doc"; + $sql .= " FROM ".MAIN_DB_PREFIX.$linked_info['table']." AS tl"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$linked_info['table']." AS tl2 ON tl2.".$linked_info['fk_link']." = tl.".$linked_info['fk_link']; + $sql .= " WHERE tl.".$linked_info['fk_doc']." IN (".$this->db->sanitize(implode(',', $document_ids)).")"; + } else { + $sql = "SELECT DISTINCT tl2.fk_link, tl2.fk_doc"; + $sql .= " FROM ("; + $sql .= " SELECT DISTINCT " . $this->db->ifsql("tll." . $linked_info['fk_table_link_line_parent'], "tll." . $linked_info['fk_table_link_line_parent'], "tl." . $linked_info['fk_link']) . " AS fk_link, tl." . $linked_info['fk_doc'] . " AS fk_doc"; + $sql .= " FROM " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $linked_info['table_link_line'] . " AS tll ON tll." . $linked_info['fk_table_link_line'] . " = tl." . $linked_info['fk_line_link']; + $sql .= ") AS tl"; + $sql .= " LEFT JOIN ("; + $sql .= " SELECT DISTINCT " . $this->db->ifsql("tll." . $linked_info['fk_table_link_line_parent'], "tll." . $linked_info['fk_table_link_line_parent'], "tl." . $linked_info['fk_link']) . " AS fk_link, tl." . $linked_info['fk_doc'] . " AS fk_doc"; + $sql .= " FROM " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $linked_info['table_link_line'] . " AS tll ON tll." . $linked_info['fk_table_link_line'] . " = tl." . $linked_info['fk_line_link']; + $sql .= ") AS tl2 ON tl2.fk_link = tl.fk_link"; + $sql .= " WHERE tl.fk_doc IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; + $sql .= " AND tl2.fk_doc IS NOT NULL"; + } dol_syslog(__METHOD__ . " - Get document lines", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 6b091db2cb85c..126100d71e3a8 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -212,10 +212,11 @@ $tabtype = array(); $tabmoreinfo = array(); - // Loop on each line into llx_bank table. For each line, we should get: + // Loop on each line into the llx_bank table. For each line, we should get: // one line tabpay = line into bank // one line for bank record = tabbq // one line for thirdparty record = tabtp + // Note: tabcompany is used to store the subledger account $i = 0; while ($i < $num) { $obj = $db->fetch_object($result); @@ -263,7 +264,8 @@ ); // Set accountancy code for user - // $obj->accountancy_code is the accountancy_code of table u=user but it is defined only if a link with type 'user' exists) + // $obj->accountancy_code is the accountancy_code of table u=user (but it is defined only if + // a link with type 'user' exists and user as a subledger account) $compta_user = (!empty($obj->accountancy_code) ? $obj->accountancy_code : ''); $tabuser[$obj->rowid] = array( @@ -307,15 +309,25 @@ // get_url may return -1 which is not traversable if (is_array($links) && count($links) > 0) { $is_sc = false; + $is_expensereport = false; foreach ($links as $v) { if ($v['type'] == 'sc') { $is_sc = true; break; } + if ($v['type'] == 'payment_expensereport') { + $is_expensereport = true; + break; + } } + // Now loop on each link of record in bank (code similar to bankentries_list.php) foreach ($links as $key => $val) { - if ($links[$key]['type'] == 'user' && !$is_sc) continue; + if ($links[$key]['type'] == 'user' && !$is_sc && !$is_expensereport) { + // We must avoid as much as possible this "continue". If we want to jump to next loop, it means we don't want to process + // the case the link is user (often because managed by hard coded code into another link), and we must avoid this. + continue; + } if (in_array($links[$key]['type'], array('sc', 'payment_sc', 'payment', 'payment_supplier', 'payment_vat', 'payment_expensereport', 'banktransfert', 'payment_donation', 'member', 'payment_loan', 'payment_salary', 'payment_various'))) { // So we excluded 'company' and 'user' here. We want only payment lines @@ -364,13 +376,25 @@ $userstatic->lastname = $tabuser[$obj->rowid]['lastname']; $userstatic->statut = $tabuser[$obj->rowid]['status']; $userstatic->accountancy_code = $tabuser[$obj->rowid]['accountancy_code']; + // For a payment of social contribution, we have a link sc + user. + // but we already fill the $tabpay[$obj->rowid]["soclib"] in the line 'sc'. + // If we fill it here to, we must concat if ($userstatic->id > 0) { - $tabpay[$obj->rowid]["soclib"] = $userstatic->getNomUrl(1, 'accountancy', 0); + if ($is_sc) { + $tabpay[$obj->rowid]["soclib"] .= ' '.$userstatic->getNomUrl(1, 'accountancy', 0); + } else { + $tabpay[$obj->rowid]["soclib"] = $userstatic->getNomUrl(1, 'accountancy', 0); + } } else { $tabpay[$obj->rowid]["soclib"] = '???'; // Should not happen, but happens with old data when id of user was not saved on expense report payment. } + if ($compta_user) { - $tabtp[$obj->rowid][$compta_user] += $amounttouse; + if ($is_sc) { + //$tabcompany[$obj->rowid][$compta_user] += $amounttouse; + } else { + $tabtp[$obj->rowid][$compta_user] += $amounttouse; + } } } elseif ($links[$key]['type'] == 'sc') { $chargestatic->id = $links[$key]['url_id']; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 20bc41e7752e2..9b69c83711351 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -1,13 +1,13 @@ - * Copyright (C) 2007-2010 Jean Heimburger - * Copyright (C) 2011 Juanjo Menent - * Copyright (C) 2012 Regis Houssin - * Copyright (C) 2013-2023 Alexandre Spangaro - * Copyright (C) 2013-2016 Olivier Geffroy - * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2018 Frédéric France - * Copyright (C) 2018 Eric Seigne +/* Copyright (C) 2007-2010 Laurent Destailleur + * Copyright (C) 2007-2010 Jean Heimburger + * Copyright (C) 2011 Juanjo Menent + * Copyright (C) 2012 Regis Houssin + * Copyright (C) 2013-2024 Alexandre Spangaro + * Copyright (C) 2013-2016 Olivier Geffroy + * Copyright (C) 2013-2016 Florian Henry + * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018 Eric Seigne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -155,8 +155,8 @@ $vatdata = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0); $compta_tva = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat); - $compta_localtax1 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva); - $compta_localtax2 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva); + $compta_localtax1 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat); + $compta_localtax2 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat); // Define array to display all VAT rates that use this accounting account $compta_tva if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) { diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 56ef0ef03171d..9c47ef5054713 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -408,7 +408,7 @@ } // Warranty - if (!$errorforline) { + if (!$errorforline && getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) { foreach ($tabwarranty[$key] as $k => $mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; @@ -649,52 +649,54 @@ // Revenue stamp if (!$errorforline) { - foreach ($tabrevenuestamp[$key] as $k => $mt) { - if ($mt) { - $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label - $label_account = $accountingaccount->label; + if (isset($tabrevenuestamp[$key])) { + foreach ($tabrevenuestamp[$key] as $k => $mt) { + if ($mt) { + $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label + $label_account = $accountingaccount->label; - $bookkeeping = new BookKeeping($db); - $bookkeeping->doc_date = $val["date"]; - $bookkeeping->date_lim_reglement = $val["datereg"]; - $bookkeeping->doc_ref = $val["ref"]; - $bookkeeping->date_creation = $now; - $bookkeeping->doc_type = 'customer_invoice'; - $bookkeeping->fk_doc = $key; - $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add - $bookkeeping->thirdparty_code = $companystatic->code_client; + $bookkeeping = new BookKeeping($db); + $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; + $bookkeeping->doc_ref = $val["ref"]; + $bookkeeping->date_creation = $now; + $bookkeeping->doc_type = 'customer_invoice'; + $bookkeeping->fk_doc = $key; + $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add + $bookkeeping->thirdparty_code = $companystatic->code_client; - $bookkeeping->subledger_account = ''; - $bookkeeping->subledger_label = ''; + $bookkeeping->subledger_account = ''; + $bookkeeping->subledger_label = ''; - $bookkeeping->numero_compte = $k; - $bookkeeping->label_compte = $label_account; + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $label_account; - $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp"); - $bookkeeping->montant = $mt; - $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; - $bookkeeping->debit = ($mt < 0) ? -$mt : 0; - $bookkeeping->credit = ($mt >= 0) ? $mt : 0; - $bookkeeping->code_journal = $journal; - $bookkeeping->journal_label = $langs->transnoentities($journal_label); - $bookkeeping->fk_user_author = $user->id; - $bookkeeping->entity = $conf->entity; + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp"); + $bookkeeping->montant = $mt; + $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; + $bookkeeping->debit = ($mt < 0) ? -$mt : 0; + $bookkeeping->credit = ($mt >= 0) ? $mt : 0; + $bookkeeping->code_journal = $journal; + $bookkeeping->journal_label = $langs->transnoentities($journal_label); + $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; - $totaldebit += $bookkeeping->debit; - $totalcredit += $bookkeeping->credit; + $totaldebit += $bookkeeping->debit; + $totalcredit += $bookkeeping->credit; - $result = $bookkeeping->create($user); - if ($result < 0) { - if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists - $error++; - $errorforline++; - $errorforinvoice[$key] = 'alreadyjournalized'; - //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings'); - } else { - $error++; - $errorforline++; - $errorforinvoice[$key] = 'other'; - setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); + $result = $bookkeeping->create($user); + if ($result < 0) { + if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists + $error++; + $errorforline++; + $errorforinvoice[$key] = 'alreadyjournalized'; + //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings'); + } else { + $error++; + $errorforline++; + $errorforinvoice[$key] = 'other'; + setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); + } } } } @@ -799,22 +801,24 @@ } // Warranty - foreach ($tabwarranty[$key] as $k => $mt) { - //if ($mt) { - print '"'.$key.'"'.$sep; - print '"'.$date.'"'.$sep; - print '"'.$val["ref"].'"'.$sep; - print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep; - print '"'.length_accounta(html_entity_decode($k)).'"'.$sep; - print '"'.length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')).'"'.$sep; - print '"'.length_accounta(html_entity_decode($k)).'"'.$sep; - print '"'.$langs->trans("Thirdparty").'"'.$sep; - print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").'"'.$sep; - print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep; - print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep; - print '"'.$journal.'"'; - print "\n"; - //} + if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) { + foreach ($tabwarranty[$key] as $k => $mt) { + //if ($mt) { + print '"' . $key . '"' . $sep; + print '"' . $date . '"' . $sep; + print '"' . $val["ref"] . '"' . $sep; + print '"' . utf8_decode(dol_trunc($companystatic->name, 32)) . '"' . $sep; + print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep; + print '"' . length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')) . '"' . $sep; + print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep; + print '"' . $langs->trans("Thirdparty") . '"' . $sep; + print '"' . utf8_decode(dol_trunc($companystatic->name, 16)) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Retainedwarranty") . '"' . $sep; + print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep; + print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep; + print '"' . $journal . '"'; + print "\n"; + //} + } } // Third party @@ -888,22 +892,24 @@ } // Revenue stamp - foreach ($tabrevenuestamp[$key] as $k => $mt) { - //if ($mt) { - print '"'.$key.'"'.$sep; - print '"'.$date.'"'.$sep; - print '"'.$val["ref"].'"'.$sep; - print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep; - print '"'.length_accountg(html_entity_decode($k)).'"'.$sep; - print '"'.length_accountg(html_entity_decode($k)).'"'.$sep; - print '""'.$sep; - print '"'.$langs->trans("RevenueStamp").'"'.$sep; - print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").'"'.$sep; - print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep; - print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep; - print '"'.$journal.'"'; - print "\n"; - //} + if (isset($tabrevenuestamp[$key])) { + foreach ($tabrevenuestamp[$key] as $k => $mt) { + //if ($mt) { + print '"' . $key . '"' . $sep; + print '"' . $date . '"' . $sep; + print '"' . $val["ref"] . '"' . $sep; + print '"' . utf8_decode(dol_trunc($companystatic->name, 32)) . '"' . $sep; + print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep; + print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep; + print '""' . $sep; + print '"' . $langs->trans("RevenueStamp") . '"' . $sep; + print '"' . utf8_decode(dol_trunc($companystatic->name, 16)) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp") . '"' . $sep; + print '"' . ($mt < 0 ? price(-$mt) : '') . '"' . $sep; + print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep; + print '"' . $journal . '"'; + print "\n"; + //} + } } } } @@ -1066,33 +1072,35 @@ function writebookkeeping() { } // Warranty - foreach ($tabwarranty[$key] as $k => $mt) { - print ''; - print ""; - print "".$date.""; - print "".$invoicestatic->getNomUrl(1).""; - // Account - print ""; - $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')); - if (($accountoshow == "") || $accountoshow == 'NotDefined') { - print ''.$langs->trans("MainAccountForRetainedWarrantyNotDefined").''; - } else { - print $accountoshow; - } - print ''; - // Subledger account - print ""; - $accountoshow = length_accounta($k); - if (($accountoshow == "") || $accountoshow == 'NotDefined') { - print ''.$langs->trans("ThirdpartyAccountNotDefined").''; - } else { - print $accountoshow; + if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && isset($tabwarranty[$key])) { + foreach ($tabwarranty[$key] as $k => $mt) { + print ''; + print ""; + print "" . $date . ""; + print "" . $invoicestatic->getNomUrl(1) . ""; + // Account + print ""; + $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print '' . $langs->trans("MainAccountForRetainedWarrantyNotDefined") . ''; + } else { + print $accountoshow; + } + print ''; + // Subledger account + print ""; + $accountoshow = length_accounta($k); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print '' . $langs->trans("ThirdpartyAccountNotDefined") . ''; + } else { + print $accountoshow; + } + print ''; + print "" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("Retainedwarranty") . ""; + print '' . ($mt >= 0 ? price($mt) : '') . ""; + print '' . ($mt < 0 ? price(-$mt) : '') . ""; + print ""; } - print ''; - print "".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").""; - print ''.($mt >= 0 ? price($mt) : '').""; - print ''.($mt < 0 ? price(-$mt) : '').""; - print ""; } // Third party @@ -1212,27 +1220,29 @@ function writebookkeeping() { } // Warranty - foreach ($tabrevenuestamp[$key] as $k => $mt) { - print ''; - print ""; - print "".$date.""; - print "".$invoicestatic->getNomUrl(1).""; - // Account - print ""; - $accountoshow = length_accountg($k); - if (($accountoshow == "") || $accountoshow == 'NotDefined') { - print ''.$langs->trans("MainAccountForRevenueStampSaleNotDefined").''; - } else { - print $accountoshow; + if (isset($tabrevenuestamp[$key])) { + foreach ($tabrevenuestamp[$key] as $k => $mt) { + print ''; + print ""; + print "" . $date . ""; + print "" . $invoicestatic->getNomUrl(1) . ""; + // Account + print ""; + $accountoshow = length_accountg($k); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print '' . $langs->trans("MainAccountForRevenueStampSaleNotDefined") . ''; + } else { + print $accountoshow; + } + print ''; + // Subledger account + print ""; + print ''; + print "" . $companystatic->getNomUrl(0, 'customer', 16) . ' - ' . $invoicestatic->ref . ' - ' . $langs->trans("RevenueStamp") . ""; + print '' . ($mt < 0 ? price(-$mt) : '') . ""; + print '' . ($mt >= 0 ? price($mt) : '') . ""; + print ""; } - print ''; - // Subledger account - print ""; - print ''; - print "".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").""; - print ''.($mt < 0 ? price(-$mt) : '').""; - print ''.($mt >= 0 ? price($mt) : '').""; - print ""; } } diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 0bc4aeed29ca3..7d9b73d444b0d 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1016,7 +1016,7 @@ function initfieldrequired() { $listetype = $adht->liste_array(1); print img_picto('', $adht->picto, 'class="pictofixedwidth"'); if (count($listetype)) { - print $form->selectarray("typeid", $listetype, (GETPOST('typeid', 'int') ? GETPOST('typeid', 'int') : $typeid), (count($listetype) > 1 ? 1 : 0), 0, 0, '', 0, 0, 0, '', '', 1); + print $form->selectarray("typeid", $listetype, (GETPOST('typeid', 'int') ? GETPOST('typeid', 'int') : $typeid), (count($listetype) > 1 ? 1 : 0), 0, 0, '', 0, 0, 0, '', 'minwidth150', 1); } else { print ''.$langs->trans("NoTypeDefinedGoToSetup").''; } diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 8717ecd010a91..25fa2b6a257ca 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3102,6 +3102,7 @@ public function sendReminderForExpiredSubscription($daysbeforeendlist = '10') $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent'; $sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only; + $sql .= " AND statut = 1"; $sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'"; //$sql .= " LIMIT 10000"; diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php index a9446083faf86..c258485760b87 100644 --- a/htdocs/adherents/subscription/card.php +++ b/htdocs/adherents/subscription/card.php @@ -358,7 +358,7 @@ print '
'; if ($user->hasRight('adherent', 'cotisation', 'creer')) { - if (!empty($bankline->rappro) || empty($bankline)) { + if (empty($bankline->rappro) || empty($bankline)) { print '"; } else { print '"; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 19a34b5ad4fc9..ad8fa3b545a12 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -121,6 +121,13 @@ @ini_set("max_execution_time", $max_execution_time_for_deploy); // This work only if safe mode is off. also web servers has timeout of 300 } +$dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT); +$allowonlineinstall = true; +$allowfromweb = 1; +if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) { + $allowonlineinstall = false; +} + /* * Actions @@ -141,7 +148,7 @@ $search_version = ''; } -if ($action == 'install') { +if ($action == 'install' && $allowonlineinstall) { $error = 0; // $original_file should match format module_modulename-x.y[.z].zip @@ -262,6 +269,8 @@ if (!$error) { setEventMessages($langs->trans("SetupIsReadyForUse", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentitiesnoconv("Home").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules")), null, 'warnings'); } +} elseif ($action == 'install' && !$allowonlineinstall) { + httponly_accessforbidden("You try to bypass the protection to disallow deployment of an external module. Hack attempt ?"); } if ($action == 'set' && $user->admin) { @@ -1175,13 +1184,6 @@ print $deschelp; - $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT); - $allowonlineinstall = true; - $allowfromweb = 1; - if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) { - $allowonlineinstall = false; - } - $fullurl = ''.$urldolibarrmodules.''; $message = ''; if ($allowonlineinstall) { diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index 413b57c969467..76c56e252071d 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -156,253 +156,255 @@ $oauthstateanticsrf = bin2hex(random_bytes(128/8)); // $list is defined into oauth.lib.php to the list of supporter OAuth providers. - foreach ($listinsetup as $key) { - $supported = 0; - $keyforsupportedoauth2array = $key[0]; // May be OAUTH_GOOGLE_NAME or OAUTH_GOOGLE_xxx_NAME - $keyforsupportedoauth2array = preg_replace('/^OAUTH_/', '', $keyforsupportedoauth2array); - $keyforsupportedoauth2array = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array); - if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { - $keybeforeprovider = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); - $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array); - } else { - $keybeforeprovider = $keyforsupportedoauth2array; - $keyforprovider = ''; - } - $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); - $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME'; + if (!empty($listinsetup)) { + foreach ($listinsetup as $key) { + $supported = 0; + $keyforsupportedoauth2array = $key[0]; // May be OAUTH_GOOGLE_NAME or OAUTH_GOOGLE_xxx_NAME + $keyforsupportedoauth2array = preg_replace('/^OAUTH_/', '', $keyforsupportedoauth2array); + $keyforsupportedoauth2array = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array); + if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { + $keybeforeprovider = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); + $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array); + } else { + $keybeforeprovider = $keyforsupportedoauth2array; + $keyforprovider = ''; + } + $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); + $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME'; - $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); + $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); - $shortscope = ''; - if (getDolGlobalString($key[4])) { - $shortscope = getDolGlobalString($key[4]); - } - $state = $shortscope; // TODO USe a better state - - // Define $urltorenew, $urltodelete, $urltocheckperms - if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') { - // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). - // We pass this param list in to 'state' because we need it before and after the redirect. - - // Note: github does not accept csrf key inside the state parameter (only known values) - $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($shortscope).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltocheckperms = 'https://github.com/settings/applications/'; - } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') { - // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). - // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes - // We pass this key list into the param 'state' because we need it before and after the redirect. - $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltocheckperms = 'https://security.google.com/settings/security/permissions'; - } elseif (!empty($supportedoauth2array[$keyforsupportedoauth2array]['returnurl'])) { - $urltorenew = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltodelete = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); - $urltocheckperms = ''; - } else { - $urltorenew = ''; - $urltodelete = ''; - $urltocheckperms = ''; - } + $shortscope = ''; + if (getDolGlobalString($key[4])) { + $shortscope = getDolGlobalString($key[4]); + } + $state = $shortscope; // TODO USe a better state + + // Define $urltorenew, $urltodelete, $urltocheckperms + if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') { + // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). + // We pass this param list in to 'state' because we need it before and after the redirect. + + // Note: github does not accept csrf key inside the state parameter (only known values) + $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($shortscope).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltocheckperms = 'https://github.com/settings/applications/'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') { + // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). + // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes + // We pass this key list into the param 'state' because we need it before and after the redirect. + $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltocheckperms = 'https://security.google.com/settings/security/permissions'; + } elseif (!empty($supportedoauth2array[$keyforsupportedoauth2array]['returnurl'])) { + $urltorenew = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete = $urlwithroot.$supportedoauth2array[$keyforsupportedoauth2array]['returnurl'].'?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltocheckperms = ''; + } else { + $urltorenew = ''; + $urltodelete = ''; + $urltocheckperms = ''; + } - if ($urltorenew) { - $urltorenew .= '&keyforprovider='.urlencode($keyforprovider); - } - if ($urltodelete) { - $urltodelete .= '&keyforprovider='.urlencode($keyforprovider); - } + if ($urltorenew) { + $urltorenew .= '&keyforprovider='.urlencode($keyforprovider); + } + if ($urltodelete) { + $urltodelete .= '&keyforprovider='.urlencode($keyforprovider); + } - // Show value of token - $tokenobj = null; - // Token - require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; - // Dolibarr storage - $storage = new DoliStorage($db, $conf, $keyforprovider); - try { - // $OAUTH_SERVICENAME is for example 'Google-keyforprovider' - print ''."\n"; - $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); - //print $storage->token.'
'; - //print $tokenobj->getExtraParams()['id_token'].'
'; - //print $tokenobj->getAccessToken().'
'; - } catch (Exception $e) { - // Return an error if token not found - //print $e->getMessage(); - } + // Show value of token + $tokenobj = null; + // Token + require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; + // Dolibarr storage + $storage = new DoliStorage($db, $conf, $keyforprovider); + try { + // $OAUTH_SERVICENAME is for example 'Google-keyforprovider' + print ''."\n"; + $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); + //print $storage->token.'
'; + //print $tokenobj->getExtraParams()['id_token'].'
'; + //print $tokenobj->getAccessToken().'
'; + } catch (Exception $e) { + // Return an error if token not found + //print $e->getMessage(); + } - // Set other properties - $refreshtoken = false; - $expiredat = ''; + // Set other properties + $refreshtoken = false; + $expiredat = ''; - $expire = false; - // Is token expired or will token expire in the next 30 seconds - if (is_object($tokenobj)) { - $expire = ($tokenobj->getEndOfLife() !== $tokenobj::EOL_NEVER_EXPIRES && $tokenobj->getEndOfLife() !== $tokenobj::EOL_UNKNOWN && time() > ($tokenobj->getEndOfLife() - 30)); - } - if ($key[1] != '' && $key[2] != '') { + $expire = false; + // Is token expired or will token expire in the next 30 seconds if (is_object($tokenobj)) { - $refreshtoken = $tokenobj->getRefreshToken(); - - $endoflife = $tokenobj->getEndOfLife(); - if ($endoflife == $tokenobj::EOL_NEVER_EXPIRES) { - $expiredat = $langs->trans("Never"); - } elseif ($endoflife == $tokenobj::EOL_UNKNOWN) { - $expiredat = $langs->trans("Unknown"); - } else { - $expiredat = dol_print_date($endoflife, "dayhour", 'tzuserrel'); + $expire = ($tokenobj->getEndOfLife() !== $tokenobj::EOL_NEVER_EXPIRES && $tokenobj->getEndOfLife() !== $tokenobj::EOL_UNKNOWN && time() > ($tokenobj->getEndOfLife() - 30)); + } + if ($key[1] != '' && $key[2] != '') { + if (is_object($tokenobj)) { + $refreshtoken = $tokenobj->getRefreshToken(); + + $endoflife = $tokenobj->getEndOfLife(); + if ($endoflife == $tokenobj::EOL_NEVER_EXPIRES) { + $expiredat = $langs->trans("Never"); + } elseif ($endoflife == $tokenobj::EOL_UNKNOWN) { + $expiredat = $langs->trans("Unknown"); + } else { + $expiredat = dol_print_date($endoflife, "dayhour", 'tzuserrel'); + } } } - } - - $submit_enabled = 0; - - print '
'; - print ''; - print ''; - print '
'; - print ''."\n"; + $submit_enabled = 0; - // Api Name - $label = $langs->trans($keyforsupportedoauth2array); - print ''; - print ''; - print ''; - print ''; - print "\n"; + print ''; + print ''; + print ''; - print ''; - print ''; - //var_dump($key); - print $langs->trans("OAuthIDSecret").''; - print ''; - print ''; - print ''."\n"; - - // Scopes - print ''; - print ''; - print ''; + print '
'; + print '
'; - print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); - if ($label == $keyforsupportedoauth2array) { - print $supportedoauth2array[$keyforsupportedoauth2array]['name']; - } else { - print $label; - } - if ($keyforprovider) { - print ' ('.$keyforprovider.')'; - } else { - print ' ('.$langs->trans("NoName").')'; - } - print '
'; - print ''.$langs->trans("SeePreviousTab").''; - print ''; - print '
'.$langs->trans("Scopes").''; - $currentscopes = getDolGlobalString($key[4]); - print $currentscopes; - print '
'."\n"; - print ''; - print ''; - //var_dump($key); - print $langs->trans("IsTokenGenerated"); - print ''; - print ''; - print ''; + print ''; - - print ''; - print ''; - //var_dump($key); - print $langs->trans("Token").''; - print ''; - print ''."\n"; + if ($keyforprovider) { + print ' ('.$keyforprovider.')'; + } else { + print ' ('.$langs->trans("NoName").')'; + } + print ''; + print ''; + print ''; + print "\n"; - if (is_object($tokenobj)) { - // Token refresh print ''; print ''; //var_dump($key); - print $langs->trans("TOKEN_REFRESH"); + print $langs->trans("OAuthIDSecret").''; + print ''; - print ''; - print ''; + print ''."\n"; + + // Scopes + print ''; + print ''; + print ''; - // Token expired print ''; print ''; //var_dump($key); - print $langs->trans("TOKEN_EXPIRED"); + print $langs->trans("IsTokenGenerated"); print ''; - print ''; + print ''; print ''; - // Token expired at print ''; print ''; //var_dump($key); - print $langs->trans("TOKEN_EXPIRE_AT"); - print ''; + print $langs->trans("Token").''; print ''; - print ''; - } + print ''."\n"; + + if (is_object($tokenobj)) { + // Token refresh + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_REFRESH"); + print ''; + print ''; + print ''; + + // Token expired + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_EXPIRED"); + print ''; + print ''; + print ''; + + // Token expired at + print ''; + print ''; + //var_dump($key); + print $langs->trans("TOKEN_EXPIRE_AT"); + print ''; + print ''; + print ''; + } - print '
'; - if (is_object($tokenobj)) { - print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '.dol_print_date($storage->date_modification, 'dayhour').' state='.dol_escape_htmltag($storage->state)); - } else { - print ''.$langs->trans("NoAccessToken").''; - } - print ''; - // Links to delete/checks token - if (is_object($tokenobj)) { - //test on $storage->hasAccessToken($OAUTH_SERVICENAME) ? - if ($urltodelete) { - print ''.$langs->trans('DeleteAccess').'
'; + // Api Name + $label = $langs->trans($keyforsupportedoauth2array); + print '
'; + print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); + if ($label == $keyforsupportedoauth2array) { + print $supportedoauth2array[$keyforsupportedoauth2array]['name']; } else { - print ''.$langs->trans('GoOnTokenProviderToDeleteToken').'
'; + print $label; } - } - // Request remote token - if ($urltorenew) { - print ''.$langs->trans('GetAccess').''; - print $form->textwithpicto('', $langs->trans('RequestAccess')); - print '
'; - } - // Check remote access - if ($urltocheckperms) { - print '
'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': '.$urltocheckperms.''; - } - print ''; - print '
'; - - if (is_object($tokenobj)) { - $tokentoshow = $tokenobj->getAccessToken(); - print ''.showValueWithClipboardCPButton($tokentoshow, 1, dol_trunc($tokentoshow, 32)).'
'; - //print 'Refresh: '.$tokenobj->getRefreshToken().'
'; - //print 'EndOfLife: '.$tokenobj->getEndOfLife().'
'; - //var_dump($tokenobj->getExtraParams()); - /*print '
Extra:
';*/ - } - print '
'; + print ''.$langs->trans("SeePreviousTab").''; print ''; - print ''.showValueWithClipboardCPButton($refreshtoken, 1, dol_trunc($refreshtoken, 32)).''; + print ''; print '
'.$langs->trans("Scopes").''; + $currentscopes = getDolGlobalString($key[4]); + print $currentscopes; + print '
'; - print yn($expire); + print ''; + if (is_object($tokenobj)) { + print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '.dol_print_date($storage->date_modification, 'dayhour').' state='.dol_escape_htmltag($storage->state)); + } else { + print ''.$langs->trans("NoAccessToken").''; + } + print ''; + // Links to delete/checks token + if (is_object($tokenobj)) { + //test on $storage->hasAccessToken($OAUTH_SERVICENAME) ? + if ($urltodelete) { + print ''.$langs->trans('DeleteAccess').'
'; + } else { + print ''.$langs->trans('GoOnTokenProviderToDeleteToken').'
'; + } + } + // Request remote token + if ($urltorenew) { + print ''.$langs->trans('GetAccess').''; + print $form->textwithpicto('', $langs->trans('RequestAccess')); + print '
'; + } + // Check remote access + if ($urltocheckperms) { + print '
'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': '.$urltocheckperms.''; + } print '
'; - print $expiredat; + + if (is_object($tokenobj)) { + $tokentoshow = $tokenobj->getAccessToken(); + print ''.showValueWithClipboardCPButton($tokentoshow, 1, dol_trunc($tokentoshow, 32)).'
'; + //print 'Refresh: '.$tokenobj->getRefreshToken().'
'; + //print 'EndOfLife: '.$tokenobj->getEndOfLife().'
'; + //var_dump($tokenobj->getExtraParams()); + /*print '
Extra:
';*/ + } print '
'; + print ''.showValueWithClipboardCPButton($refreshtoken, 1, dol_trunc($refreshtoken, 32)).''; + print '
'; + print yn($expire); + print '
'; + print $expiredat; + print '
'; - print '
'; + print ''; + print '
'; - if (!empty($driver)) { - if ($submit_enabled) { - print $form->buttonsSaveCancel("Modify", ''); + if (!empty($driver)) { + if ($submit_enabled) { + print $form->buttonsSaveCancel("Modify", ''); + } } - } - print ''; - print '
'; + print ''; + print '
'; + } } } diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 28d347bcabec2..0ddb7cf67aa0c 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -161,7 +161,7 @@ ), // Automatic classification reception - 'WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE'=>array( + 'WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE'=>array( 'family'=>'classify_reception', 'position'=>95, 'enabled'=>(isModEnabled("reception") && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index 915768e0ea697..b8320b35df3c0 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -580,8 +580,10 @@ public function getDocumentsListByElement($modulepart, $id = 0, $ref = '', $sort } elseif (is_array($ecmfile->lines) && count($ecmfile->lines) > 0) { $count = count($filearray); for ($i = 0 ; $i < $count ; $i++) { - if ($filearray[$i]['name'] == $ecmfile->lines[$i]->filename) { - $filearray[$i] = array_merge($filearray[$i], (array) $ecmfile->lines[0]); + foreach ($ecmfile->lines as $line) { + if ($filearray[$i]['name'] == $line->filename) { + $filearray[$i] = array_merge($filearray[$i], (array) $line); + } } } } @@ -888,7 +890,7 @@ public function post($filename, $modulepart, $ref = '', $subdir = '', $fileconte // Move the temporary file at its final emplacement $result = dol_move($destfiletmp, $dest_file, 0, $overwriteifexists, 1, 1, $moreinfo); if (!$result) { - throw new RestException(500, "Failed to move file into '".$destfile."'"); + throw new RestException(500, "Failed to move file into '".$dest_file."'"); } return dol_basename($destfile); diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index e2d93806ca352..a9763e4fcd6f6 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -863,7 +863,7 @@ public function calculationDepreciation() // Get fiscal period require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; - $dates = getDefaultDatesForTransfer(); + $dates = getCurrentPeriodOfFiscalYear($this->db, $conf, $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition); $init_fiscal_period_start = $dates['date_start']; $init_fiscal_period_end = $dates['date_end']; if (empty($init_fiscal_period_start) || empty($init_fiscal_period_end)) { diff --git a/htdocs/barcode/codeinit.php b/htdocs/barcode/codeinit.php index 9c45d29cf795a..4aff659344850 100644 --- a/htdocs/barcode/codeinit.php +++ b/htdocs/barcode/codeinit.php @@ -108,6 +108,7 @@ $nbok = 0; if (!empty($eraseallthirdpartybarcode)) { $sql = "UPDATE ".MAIN_DB_PREFIX."societe"; + $sql .= " AND entity IN (".getEntity('societe').")"; $sql .= " SET barcode = NULL"; $resql = $db->query($sql); if ($resql) { @@ -120,6 +121,7 @@ $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."societe"; $sql .= " WHERE barcode IS NULL or barcode = ''"; + $sql .= " AND entity IN (".getEntity('societe').")"; $sql .= $db->order("datec", "ASC"); $sql .= $db->plimit($maxperinit); @@ -211,6 +213,7 @@ if (!empty($eraseallproductbarcode)) { $sql = "UPDATE ".MAIN_DB_PREFIX."product"; $sql .= " SET barcode = NULL"; + $sql .= " WHERE entity IN (".getEntity('product').")"; $resql = $db->query($sql); if ($resql) { setEventMessages($langs->trans("AllBarcodeReset"), null, 'mesgs'); @@ -222,6 +225,7 @@ $sql = "SELECT rowid, ref, fk_product_type"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE barcode IS NULL or barcode = ''"; + $sql .= " AND entity IN (".getEntity('product').")"; $sql .= $db->order("datec", "ASC"); $sql .= $db->plimit($maxperinit); @@ -322,6 +326,7 @@ function confirm_erase() { } $sql = "SELECT count(rowid) as nb FROM ".MAIN_DB_PREFIX."societe"; + $sql .= " WHERE entity IN (".getEntity('societe').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); @@ -376,6 +381,7 @@ function confirm_erase() { $sql = "SELECT count(rowid) as nb, fk_product_type, datec"; $sql .= " FROM ".MAIN_DB_PREFIX."product"; $sql .= " WHERE barcode IS NULL OR barcode = ''"; + $sql .= " AND entity IN (".getEntity('product').")"; $sql .= " GROUP BY fk_product_type, datec"; $sql .= " ORDER BY datec"; $resql = $db->query($sql); @@ -394,6 +400,7 @@ function confirm_erase() { } $sql = "SELECT count(rowid) as nb FROM ".MAIN_DB_PREFIX."product"; + $sql .= " WHERE entity IN (".getEntity('product').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index 486e65544aacb..3711518795b8e 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -255,10 +255,18 @@ if (!$mesg) { $outputlangs = $langs; + $previousConf = getDolGlobalInt('TCPDF_THROW_ERRORS_INSTEAD_OF_DIE'); + $conf->global->TCPDF_THROW_ERRORS_INSTEAD_OF_DIE = 1; + // This generates and send PDF to output // TODO Move - $result = doc_label_pdf_create($db, $arrayofrecords, $modellabel, $outputlangs, $diroutput, $template, dol_sanitizeFileName($outfile)); + try { + $result = doc_label_pdf_create($db, $arrayofrecords, $modellabel, $outputlangs, $diroutput, $template, dol_sanitizeFileName($outfile)); + } catch (Exception $e) { + $mesg = $langs->trans('ErrorGeneratingBarcode'); + } + $conf->global->TCPDF_THROW_ERRORS_INSTEAD_OF_DIE = $previousConf; } } @@ -313,7 +321,7 @@ $arrayoflabels[$codecards] = $labeltoshow; } asort($arrayoflabels); -print $form->selectarray('modellabel', $arrayoflabels, (GETPOST('modellabel') ?GETPOST('modellabel') : $conf->global->ADHERENT_ETIQUETTE_TYPE), 1, 0, 0, '', 0, 0, 0, '', '', 1); +print $form->selectarray('modellabel', $arrayoflabels, (GETPOST('modellabel') ? GETPOST('modellabel') : getDolGlobalString('ADHERENT_ETIQUETTE_TYPE')), 1, 0, 0, '', 0, 0, 0, '', '', 1); print ''; // Number of stickers to print diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 5b82bcd6d2c22..8b20fdec7d9f6 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -267,8 +267,8 @@ public function delete($id) throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if (!$this->category->delete(DolibarrApiAccess::$user)) { - throw new RestException(401, 'error when delete category'); + if ($this->category->delete(DolibarrApiAccess::$user) <= 0) { + throw new RestException(500, 'Error when delete category : ' . $this->category->error); } return array( diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 9791cdeb5be44..09c61378c7848 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -131,7 +131,7 @@ foreach ($object->multilangs as $key => $value) { // recording of new values in the object $libelle = GETPOST('libelle-'.$key, 'alpha'); - $desc = GETPOST('desc-'.$key); + $desc = GETPOST('desc-'.$key, 'restricthtml'); if (empty($libelle)) { $error++; diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 304aa33537a8c..0f8b9a32a3537 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1000,7 +1000,7 @@ $newdate = GETPOST('newdate', 'alpha'); if (empty($newdate) || strpos($newdate, 'dayevent_') != 0) { - header("Location: ".$backtopage); + header("Location: ".$backtopage, true, 307); exit; } @@ -1085,7 +1085,7 @@ } } if (!empty($backtopage)) { - header("Location: ".$backtopage); + header("Location: ".$backtopage, true, 307); exit; } else { $action = ''; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index df388d7b5fa05..43fb40704a165 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -841,9 +841,6 @@ public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '', $loadres $this->type_color = $obj->type_color; $this->type_picto = $obj->type_picto; $this->type = $obj->type_type; - /*$transcode = $langs->trans("Action".$obj->type_code); - $this->type = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label); */ - $transcode = $langs->trans("Action".$obj->type_code.'Short'); $this->code = $obj->code; $this->label = $obj->label; @@ -2520,6 +2517,7 @@ public function sendEmailsReminder() // Load event $res = $this->fetch($actionCommReminder->fk_actioncomm); + if ($res > 0) $res = $this->fetch_thirdparty(); if ($res > 0) { // PREPARE EMAIL $errormesg = ''; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 3e201e1f683c5..63dd1ae743655 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -146,7 +146,6 @@ if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } - if (empty($reshook)) { $backurlforlist = DOL_URL_ROOT.'/comm/propal/list.php'; @@ -1614,7 +1613,20 @@ $result = $object->set_demand_reason($user, GETPOST('demand_reason_id', 'int')); } elseif ($action == 'setconditions' && $usercancreate) { // Terms of payment - $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha')); + $sql = "SELECT code "; + $sql .= "FROM " . $db->prefix() . "c_payment_term"; + $sql .= " WHERE rowid = " . ((int) GETPOST('cond_reglement_id', 'int')); + $result = $db->query($sql); + if ($result) { + $obj = $db->fetch_object($result); + if ($obj->code == 'DEP30PCTDEL') { + $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), GETPOST('cond_reglement_id_deposit_percent', 'alpha')); + } else { + $object->deposit_percent = 0; + $object->update($user); + $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'), $object->deposit_percent); + } + } } elseif ($action == 'setremisepercent' && $usercancreate) { $result = $object->set_remise_percent($user, price2num(GETPOST('remise_percent'), '', 2)); } elseif ($action == 'setremiseabsolue' && $usercancreate) { @@ -2857,7 +2869,9 @@ print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; @@ -2866,7 +2880,9 @@ print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; print '' . price($object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; } diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 2d59bb1ac6537..a2ff96ec37d8b 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -278,7 +278,7 @@ public function post($request_data = null) throw new RestException(500, "Error creating order", array_merge(array($this->propal->error), $this->propal->errors)); } - return $this->propal->id; + return ((int) $this->propal->id); } /** diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index ec2fa41b99157..c2825ff18300b 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -272,6 +272,8 @@ class Propal extends CommonObject public $multicurrency_total_ht; public $multicurrency_total_tva; public $multicurrency_total_ttc; + public $multicurrency_total_localtax1; // not in database + public $multicurrency_total_localtax2; // not in database /** @@ -1413,7 +1415,9 @@ public function createFromClone(User $user, $socid = 0, $forceentity = null, $up } // reset ref_client - $object->ref_client = ''; + if (!getDolGlobalString('MAIN_KEEP_REF_CUSTOMER_ON_CLONING')) { + $object->ref_client = ''; + } // TODO Change product price if multi-prices } else { @@ -2695,7 +2699,10 @@ public function closeProposal($user, $status, $note = '', $notrigger = 0) } $sql = "UPDATE ".MAIN_DB_PREFIX."propal"; - $sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($date_signature)."', fk_user_signature=".$fk_user_signature; + $sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."'"; + if ($status == self::STATUS_SIGNED) { + $sql .= ", date_signature='".$this->db->idate($now)."', fk_user_signature = ".($fk_user_signature); + } $sql .= " WHERE rowid = ".((int) $this->id); $resql = $this->db->query($sql); @@ -3510,7 +3517,7 @@ public function load_board($user, $mode) $response->label = $label; $response->labelShort = $labelShort; $response->url = DOL_URL_ROOT.'/comm/propal/list.php?search_status='.$status.'&mainmenu=commercial&leftmenu=propals'; - $response->url_late = DOL_URL_ROOT.'/comm/propal/list.php?search_status='.$status.'&mainmenu=commercial&leftmenu=propals&sortfield=p.datep&sortorder=asc'; + $response->url_late = DOL_URL_ROOT.'/comm/propal/list.php?search_option=late&mainmenu=commercial&leftmenu=propals&sortfield=p.datep&sortorder=asc'; $response->img = img_object('', "propal"); // This assignment in condition is not a bug. It allows walking the results. diff --git a/htdocs/comm/propal/contact.php b/htdocs/comm/propal/contact.php index 26bb7c5818e2c..dbe7790c21de0 100644 --- a/htdocs/comm/propal/contact.php +++ b/htdocs/comm/propal/contact.php @@ -67,11 +67,11 @@ if (!empty($user->socid)) { $socid = $user->socid; } +$hookmanager->initHooks(array('proposalcontactcard', 'globalcard')); restrictedArea($user, 'propal', $object->id); $usercancreate = $user->hasRight("propal", "creer"); - /* * Add a new contact */ diff --git a/htdocs/comm/propal/document.php b/htdocs/comm/propal/document.php index 0a7584248c0aa..45349be628688 100644 --- a/htdocs/comm/propal/document.php +++ b/htdocs/comm/propal/document.php @@ -81,6 +81,7 @@ if (!empty($user->socid)) { $socid = $user->socid; } +$hookmanager->initHooks(array('propaldocument', 'globalcard')); restrictedArea($user, 'propal', $object->id); $usercancreate = $user->hasRight("propal", "creer"); diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 93a2db8007238..4b1def204bce5 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -17,6 +17,7 @@ * Copyright (C) 2021 Anthony Berton * Copyright (C) 2021 Frédéric France * Copyright (C) 2022 Josep Lluís Amador + * Copyright (C) 2024 William Mead * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -146,6 +147,12 @@ $optioncss = GETPOST('optioncss', 'alpha'); $object_statut = GETPOST('search_statut', 'alpha'); +$search_option = GETPOST('search_option', 'alpha'); +if ($search_option == 'late') { + $search_status = '1'; + $object_statut = '1'; +} + $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $mesg = (GETPOST("msg") ? GETPOST("msg") : GETPOST("mesg")); @@ -389,6 +396,7 @@ $search_date_signature_endyear = ''; $search_date_signature_start = ''; $search_date_signature_end = ''; + $search_option = ''; } if ($object_statut != '') { $search_status = $object_statut; @@ -764,6 +772,9 @@ if ($search_date_signature_end) { $sql .= " AND p.date_signature <= '".$db->idate($search_date_signature_end)."'"; } +if ($search_option == 'late') { + $sql .= " AND p.fin_validite < '".$db->idate(dol_now() - $conf->propal->cloture->warning_delay)."'"; +} // Search for tag/category ($searchCategoryProductList is an array of ID) $searchCategoryProductOperator = -1; $searchCategoryProductList = array($search_product_category); @@ -1042,6 +1053,9 @@ if ($search_date_signature_endyear) { $param .= '&search_date_signature_endyear='.urlencode($search_date_signature_endyear); } + if ($search_option) { + $param .= "&search_option=".urlencode($search_option); + } // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -1166,6 +1180,7 @@ $moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', $tmptitle, 0, 0, $tmptitle); $moreforfilter .= ''; } + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 71aefc2e7084f..7128688a7cc83 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -866,8 +866,8 @@ } } - $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx)); - $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx)); + $tmpvat = (float) price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx)); + $tmpprodvat = (float) price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx)); // Set unit price to use if (!empty($price_ht) || $price_ht === '0') { @@ -2770,7 +2770,9 @@ print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; @@ -2780,7 +2782,9 @@ print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; print '' . price($object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($object->total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($object->multicurrency_total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; } diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index 66e8c2ee9576e..5498f22a3c81d 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -297,7 +297,7 @@ public function post($request_data = null) throw new RestException(500, "Error creating order", array_merge(array($this->commande->error), $this->commande->errors)); } - return $this->commande->id; + return ((int) $this->commande->id); } /** diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 6b6037d62d556..dce7ec132b042 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -13,6 +13,7 @@ * Copyright (C) 2016-2022 Ferran Marcet * Copyright (C) 2021-2023 Frédéric France * Copyright (C) 2022 Gauthier VERDOL + * Copyright (C) 2024 William Mead * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -275,6 +276,8 @@ class Commande extends CommonOrder public $multicurrency_total_ht; public $multicurrency_total_tva; public $multicurrency_total_ttc; + public $multicurrency_total_localtax1; // not in database + public $multicurrency_total_localtax2; // not in database //! key of module source when order generated from a dedicated module ('cashdesk', 'takepos', ...) public $module_source; @@ -3612,6 +3615,7 @@ public function load_board($user) $response->label = $langs->trans("OrdersToProcess"); $response->labelShort = $langs->trans("Opened"); $response->url = DOL_URL_ROOT.'/commande/list.php?search_status=-3&mainmenu=commercial&leftmenu=orders'; + $response->url_late = DOL_URL_ROOT.'/commande/list.php?search_option=late&mainmenu=commercial&leftmenu=orders'; $response->img = img_object('', "order"); $generic_commande = new Commande($this->db); @@ -4374,6 +4378,8 @@ public function fetch($rowid) $this->multicurrency_total_tva = $objp->multicurrency_total_tva; $this->multicurrency_total_ttc = $objp->multicurrency_total_ttc; + $this->fetch_optionals(); + $this->db->free($result); return 1; @@ -4396,20 +4402,20 @@ public function delete(User $user, $notrigger = 0) $error = 0; - if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility + if (empty($this->id) && !empty($this->rowid)) { // For backward compatibility $this->id = $this->rowid; } // check if order line is not in a shipment line before deleting - $sqlCheckShipmentLine = "SELECT"; + $sqlCheckShipmentLine = "SELECT"; $sqlCheckShipmentLine .= " ed.rowid"; - $sqlCheckShipmentLine .= " FROM ".MAIN_DB_PREFIX."expeditiondet ed"; - $sqlCheckShipmentLine .= " WHERE ed.fk_origin_line = ".((int) $this->id); + $sqlCheckShipmentLine .= " FROM " . MAIN_DB_PREFIX . "expeditiondet ed"; + $sqlCheckShipmentLine .= " WHERE ed.fk_origin_line = " . ((int) $this->id); $resqlCheckShipmentLine = $this->db->query($sqlCheckShipmentLine); if (!$resqlCheckShipmentLine) { $error++; - $this->error = $this->db->lasterror(); + $this->error = $this->db->lasterror(); $this->errors[] = $this->error; } else { $langs->load('errors'); @@ -4417,56 +4423,58 @@ public function delete(User $user, $notrigger = 0) if ($num > 0) { $error++; $objCheckShipmentLine = $this->db->fetch_object($resqlCheckShipmentLine); - $this->error = $langs->trans('ErrorRecordAlreadyExists').' : '.$langs->trans('ShipmentLine').' '.$objCheckShipmentLine->rowid; + $this->error = $langs->trans('ErrorRecordAlreadyExists') . ' : ' . $langs->trans('ShipmentLine') . ' ' . $objCheckShipmentLine->rowid; $this->errors[] = $this->error; } $this->db->free($resqlCheckShipmentLine); } if ($error) { - dol_syslog(__METHOD__.'Error ; '.$this->error, LOG_ERR); + dol_syslog(__METHOD__ . 'Error ; ' . $this->error, LOG_ERR); return -1; } $this->db->begin(); - $sql = 'DELETE FROM '.MAIN_DB_PREFIX."commandedet WHERE rowid = ".((int) $this->id); - - dol_syslog("OrderLine::delete", LOG_DEBUG); - $resql = $this->db->query($sql); - if ($resql) { - if (!$error && !$notrigger) { - // Call trigger - $result = $this->call_trigger('LINEORDER_DELETE', $user); - if ($result < 0) { - $error++; - } - // End call triggers + if (!$notrigger) { + // Call trigger + $result = $this->call_trigger('LINEORDER_DELETE', $user); + if ($result < 0) { + $error++; } + // End call triggers + } - // Remove extrafields - if (!$error) { - $result = $this->deleteExtraFields(); - if ($result < 0) { - $error++; - dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR); - } - } + if (!$error) { + $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . "commandedet WHERE rowid = " . ((int) $this->id); - if (!$error) { - $this->db->commit(); - return 1; + dol_syslog("OrderLine::delete", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->error = $this->db->lasterror(); + $error++; } + } - foreach ($this->errors as $errmsg) { - dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); - $this->error .= ($this->error ? ', '.$errmsg : $errmsg); + // Remove extrafields + if (!$error) { + $result = $this->deleteExtraFields(); + if ($result < 0) { + $error++; + dol_syslog(get_class($this) . "::delete error -4 " . $this->error, LOG_ERR); } - $this->db->rollback(); - return -1 * $error; - } else { - $this->error = $this->db->lasterror(); - return -1; } + + if (!$error) { + $this->db->commit(); + return 1; + } + + foreach ($this->errors as $errmsg) { + dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR); + $this->error .= ($this->error ? ', ' . $errmsg : $errmsg); + } + $this->db->rollback(); + return -1 * $error; } /** diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index a71212a517cb7..ab99e305871d7 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -12,6 +12,7 @@ * Copyright (C) 2016-2023 Ferran Marcet * Copyright (C) 2018 Charlene Benke * Copyright (C) 2021 Anthony Berton + * Copyright (C) 2024 William Mead * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -118,6 +119,10 @@ $search_fk_shipping_method = GETPOST('search_fk_shipping_method', 'int'); $search_fk_mode_reglement = GETPOST('search_fk_mode_reglement', 'int'); $search_fk_input_reason = GETPOST('search_fk_input_reason', 'int'); +$search_option = GETPOST('search_option', 'alpha'); +if ($search_option == 'late') { + $search_status = '-2'; +} $diroutputmassaction = $conf->commande->multidir_output[$conf->entity].'/temp/massgeneration/'.$user->id; @@ -293,6 +298,7 @@ $search_fk_shipping_method = ''; $search_fk_mode_reglement = ''; $search_fk_input_reason = ''; + $search_option = ''; } if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { @@ -601,6 +607,9 @@ if ($search_status != '') { $param .= '&search_status='.urlencode($search_status); } + if ($search_option) { + $param .= "&search_option=".urlencode($search_option); + } if ($search_orderday) { $param .= '&search_orderday='.urlencode($search_orderday); } @@ -915,7 +924,9 @@ $sql .= ' AND (c.fk_statut IN (1,2))'; // validated, in process } } - +if ($search_option == 'late') { + $sql .= " AND c.date_commande < '".$db->idate(dol_now() - $conf->commande->client->warning_delay)."'"; +} if ($search_datecloture_start) { $sql .= " AND c.date_cloture >= '".$db->idate($search_datecloture_start)."'"; } @@ -1169,6 +1180,9 @@ if ($search_status != '') { $param .= '&search_status='.urlencode($search_status); } +if ($search_option) { + $param .= "&search_option=".urlencode($search_option); +} if ($search_datecloture_start) { $param .= '&search_datecloture_startday='.dol_print_date($search_datecloture_start, '%d').'&search_datecloture_startmonth='.dol_print_date($search_datecloture_start, '%m').'&search_datecloture_startyear='.dol_print_date($search_datecloture_start, '%Y'); } @@ -1466,6 +1480,7 @@ $moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', 1, 0, 0, $tmptitle, 0, 0, array(), 'maxwidth250 widthcentpercentminusx'); $moreforfilter .= ''; } + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { @@ -2620,7 +2635,7 @@ $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; } else { $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel']; - $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; + $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel']; } if ($reliquat > $generic_product->stock_reel) { diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 9fc9e4059a77b..86a30b9cfc954 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -2016,7 +2016,7 @@ $productstat_cachevirtual[$obj->fk_product]['stock_reel'] = $generic_product->stock_theorique; } else { $generic_product->stock_reel = $productstat_cache[$obj->fk_product]['stock_reel']; - $generic_product->stock_theorique = $productstat_cachevirtual[$obj->fk_product]['stock_reel'] = $generic_product->stock_theorique; + $generic_product->stock_theorique = $productstat_cachevirtual[$obj->fk_product]['stock_reel']; } if ($reliquat > $generic_product->stock_reel) { diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index da275c4044bce..7a322ab3939df 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -82,7 +82,6 @@ $result = restrictedArea($user, 'banque', $id, 'bank_account&bank_account', '', '', $fieldid); - /* * Actions */ @@ -236,6 +235,7 @@ $object = new Account($db); $object->fetch(GETPOST("id", 'int')); + $object->oldref = $object->ref; $object->ref = dol_string_nospecial(trim(GETPOST('ref', 'alpha'))); $object->label = trim(GETPOST("label", 'alphanohtml')); $object->courant = GETPOST("type"); diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index ca54201736059..26ce53400f99e 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -277,6 +277,11 @@ class Account extends CommonObject */ public $ics_transfer; + /** + * @var string The previous ref in case of rename on update to rename attachment folders + */ + public $oldref; + /** @@ -920,6 +925,28 @@ public function update(User $user, $notrigger = 0) } } + if (!$error && !empty($this->oldref) && $this->oldref !== $this->ref) { + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'bank/".$this->db->escape($this->ref)."'"; + $sql .= " WHERE filepath = 'bank/".$this->db->escape($this->oldref)."' and src_object_type='bank_account' and entity = ".((int) $conf->entity); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->error = $this->db->lasterror(); + } + + // We rename directory in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->oldref); + $newref = dol_sanitizeFileName($this->ref); + $dirsource = $conf->bank->dir_output.'/'.$oldref; + $dirdest = $conf->bank->dir_output.'/'.$newref; + if (file_exists($dirsource)) { + dol_syslog(get_class($this)."::update rename dir ".$dirsource." into ".$dirdest, LOG_DEBUG); + if (@rename($dirsource, $dirdest)) { + dol_syslog("Rename ok", LOG_DEBUG); + } + } + } + if (!$error && !$notrigger) { // Call trigger $result = $this->call_trigger('BANKACCOUNT_MODIFY', $user); @@ -2570,12 +2597,15 @@ public function info($id) */ public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip = 0) { - global $langs; + global $conf, $langs; $result = ''; $label = img_picto('', $this->picto).' '.$langs->trans("BankTransactionLine").':
'; $label .= ''.$langs->trans("Ref").': '.$this->ref; + if ($this->amount) { + $label .= '
'.$langs->trans("Amount").': '.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency); + } $linkstart = ''; $linkend = ''; @@ -2587,6 +2617,7 @@ public function getNomUrl($withpicto = 0, $maxlen = 0, $option = '', $notooltip if ($withpicto != 2) { $result .= ($this->ref ? $this->ref : $this->id); } + $result .= $linkend; if ($option == 'showall' || $option == 'showconciliated' || $option == 'showconciliatedandaccounted') { diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index 38a8fb1013b88..d20666c224e1c 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -125,6 +125,7 @@ $sql = "SELECT b.num_releve as num"; $sql .= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql .= " WHERE b.num_releve < '".$db->escape($numref)."'"; +$sql .= " AND b.num_releve <> ''"; $sql .= " AND b.fk_account = ".((int) $object->id); $sql .= " ORDER BY b.num_releve DESC"; $sql .= $db->plimit(1); @@ -380,6 +381,7 @@ $sql = "SELECT sum(b.amount) as amount"; $sql .= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql .= " WHERE b.num_releve < '".$db->escape($objp->numr)."'"; + $sql .= " AND b.num_releve <> ''"; $sql .= " AND b.fk_account = ".((int) $object->id); $resql = $db->query($sql); if ($resql) { @@ -464,6 +466,7 @@ $sql = "SELECT sum(b.amount) as amount"; $sql .= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql .= " WHERE b.num_releve < '".$db->escape($numref)."'"; + $sql .= " AND b.num_releve <> ''"; $sql .= " AND b.fk_account = ".((int) $object->id); $resql = $db->query($sql); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index a65358b7d5836..90555b00b0cc3 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -12,7 +12,7 @@ * Copyright (C) 2013 Jean-Francois FERRY * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013 Cédric Salvador - * Copyright (C) 2014-2019 Ferran Marcet + * Copyright (C) 2014-2024 Ferran Marcet * Copyright (C) 2015-2016 Marcos García * Copyright (C) 2018-2023 Frédéric France * Copyright (C) 2022 Gauthier VERDOL @@ -321,7 +321,7 @@ $object->date = dol_now(); } - if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) { + if (!empty($conf->global->INVOICE_CHECK_POSTERIOR_DATE)) { $last_of_type = $object->willBeLastOfSameType(true); if (empty($object->date_validation) && !$last_of_type[0]) { setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref, dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors'); @@ -456,7 +456,7 @@ $object->date = $newdate; $new_date_lim_reglement = $object->calculate_date_lim_reglement(); - if ($new_date_lim_reglement > $old_date_lim_reglement) { + if ($new_date_lim_reglement) { $object->date_lim_reglement = $new_date_lim_reglement; } if ($object->date_lim_reglement < $object->date) { @@ -496,7 +496,7 @@ if (!$error) { $old_date_lim_reglement = $object->date_lim_reglement; $new_date_lim_reglement = $object->calculate_date_lim_reglement(); - if ($new_date_lim_reglement > $old_date_lim_reglement) { + if ($new_date_lim_reglement) { $object->date_lim_reglement = $new_date_lim_reglement; } if ($object->date_lim_reglement < $object->date) { @@ -1604,7 +1604,7 @@ null, 0, '', - 1 + (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)?0:1) ); } @@ -4487,6 +4487,9 @@ function setRadioForTypeOfIncoice() { $morehtmlref .= ''; $object->totalpaid = $totalpaid; // To give a chance to dol_banner_tab to use already paid amount to show correct status + $object->totalcreditnotes = $totalcreditnotes; + $object->totaldeposits = $totaldeposits; + $object->remaintopay = price2num($object->total_ttc - $object->totalpaid - $object->totalcreditnotes - $object->totaldeposits, 'MT'); dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, '', 0, '', ''); @@ -4904,7 +4907,9 @@ function setRadioForTypeOfIncoice() { print '' . $langs->transcountry("AmountLT1", $mysoc->country_code) . ''; print '' . price($sign * $object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($sign * $object->total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT'); + + print '' . price($sign * $object->multicurrency_total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; @@ -4913,7 +4918,9 @@ function setRadioForTypeOfIncoice() { print '' . $langs->transcountry("AmountLT2", $mysoc->country_code) . ''; print '' . price($sign * $object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . ''; if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) { - print '' . price($sign * $object->total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; + $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT'); + + print '' . price($sign * $object->multicurrency_total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . ''; } print ''; } @@ -5035,7 +5042,9 @@ function js_recalculate_revenuestamp(){ $current_situation_counter = array(); foreach ($object->tab_previous_situation_invoice as $prev_invoice) { - $tmptotalpaidforthisinvoice = $prev_invoice->getSommePaiement(); + $tmptotalallpayments = $prev_invoice->getSommePaiement(0); + $tmptotalallpayments += $prev_invoice->getSumDepositsUsed(0); + $tmptotalallpayments += $prev_invoice->getSumCreditNotesUsed(0); $total_prev_ht += $prev_invoice->total_ht; $total_prev_ttc += $prev_invoice->total_ttc; $current_situation_counter[] = (($prev_invoice->type == Facture::TYPE_CREDIT_NOTE) ?-1 : 1) * $prev_invoice->situation_counter; @@ -5048,11 +5057,14 @@ function js_recalculate_revenuestamp(){ } print ''.price($prev_invoice->total_ht).''; print ''.price($prev_invoice->total_ttc).''; - print ''.$prev_invoice->getLibStatut(3, $tmptotalpaidforthisinvoice).''; + print ''.$prev_invoice->getLibStatut(3, $tmptotalallpayments).''; print ''; } } + $totalallpayments = $object->getSommePaiement(0); + $totalallpayments += $object->getSumCreditNotesUsed(0); + $totalallpayments += $object->getSumDepositsUsed(0); $total_global_ht += $total_prev_ht; $total_global_ttc += $total_prev_ttc; @@ -5068,7 +5080,7 @@ function js_recalculate_revenuestamp(){ } print ''.price($object->total_ht).''; print ''.price($object->total_ttc).''; - print ''.$object->getLibStatut(3, $object->getSommePaiement()).''; + print ''.$object->getLibStatut(3, $totalallpayments).''; print ''; @@ -5110,7 +5122,9 @@ function js_recalculate_revenuestamp(){ $total_next_ht = $total_next_ttc = 0; foreach ($object->tab_next_situation_invoice as $next_invoice) { - $totalpaid = $next_invoice->getSommePaiement(); + $totalpaid = $next_invoice->getSommePaiement(0); + $totalcreditnotes = $next_invoice->getSumCreditNotesUsed(0); + $totaldeposits = $next_invoice->getSumDepositsUsed(0); $total_next_ht += $next_invoice->total_ht; $total_next_ttc += $next_invoice->total_ttc; @@ -5123,7 +5137,7 @@ function js_recalculate_revenuestamp(){ } print ''.price($next_invoice->total_ht).''; print ''.price($next_invoice->total_ttc).''; - print ''.$next_invoice->getLibStatut(3, $totalpaid).''; + print ''.$next_invoice->getLibStatut(3, $totalpaid + $totalcreditnotes + $totaldeposits).''; print ''; } @@ -5696,7 +5710,7 @@ function js_recalculate_revenuestamp(){ // Sometimes we can receive more, so we accept to enter more and will offer a button to convert into discount (but it is not a credit note, just a prepayment done) //print ''.$langs->trans('DoPayment').''; $params['attr']['title'] = ''; - print dolGetButtonAction($langs->trans('DoPayment'), '', 'default', DOL_URL_ROOT.'/compta/paiement.php?facid='.$object->id.'&action=create&accountid='.$object->fk_account, '', true, $params); + print dolGetButtonAction($langs->trans('DoPayment'), '', 'default', DOL_URL_ROOT.'/compta/paiement.php?facid='.$object->id.'&action=create'.($object->fk_account > 0 ? '&accountid='.$object->fk_account : ''), '', true, $params); } } } diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index d48740ea68d62..72c392816ebf0 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -318,7 +318,7 @@ public function post($request_data = null) if ($this->invoice->create(DolibarrApiAccess::$user, 0, (empty($request_data["date_lim_reglement"]) ? 0 : $request_data["date_lim_reglement"])) < 0) { throw new RestException(500, "Error creating invoice", array_merge(array($this->invoice->error), $this->invoice->errors)); } - return $this->invoice->id; + return ((int) $this->invoice->id); } /** diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 4b641b6566880..4f7ad339fe9de 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -1340,6 +1340,14 @@ public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidat $facture->multicurrency_tx = $facturerec->multicurrency_tx; } + if (isset($facture->array_options) && isset($facturerec->array_options)) { + foreach ($facturerec->array_options as $key => $value) { + if (isset($facture->array_options[$key])) { + $facture->array_options[$key] = $value; + } + } + } + $invoiceidgenerated = $facture->create($user); if ($invoiceidgenerated <= 0) { $this->errors = $facture->errors; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index cf84bbd1b44d3..1c02a897a1436 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -262,6 +262,8 @@ class Facture extends CommonInvoice public $multicurrency_total_ht; public $multicurrency_total_tva; public $multicurrency_total_ttc; + public $multicurrency_total_localtax1; // not in database + public $multicurrency_total_localtax2; // not in database /** * @var int Situation cycle reference number @@ -501,8 +503,8 @@ public function create(User $user, $notrigger = 0, $forceduedate = 0) $this->ref_client = trim($this->ref_client); $this->note = (isset($this->note) ? trim($this->note) : trim($this->note_private)); // deprecated - $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note_private)); - $this->note_public = trim($this->note_public); + $this->note_private = (isset($this->note_private) ? trim($this->note_private) : ''); + $this->note_public = (isset($this->note_public) ? trim($this->note_public) : ''); if (!$this->cond_reglement_id) { $this->cond_reglement_id = 0; } @@ -5842,9 +5844,9 @@ public function sendEmailsRemindersOnInvoiceDueDate($nbdays = 0, $paymentmode = $joinFileName = []; $joinFileMime = []; if ($arraymessage->joinfiles == 1 && !empty($tmpinvoice->last_main_doc)) { - $joinFile[] = DOL_DATA_ROOT.$tmpinvoice->last_main_doc; + $joinFile[] = DOL_DATA_ROOT.'/'.$tmpinvoice->last_main_doc; $joinFileName[] = basename($tmpinvoice->last_main_doc); - $joinFileMime[] = dol_mimetype(DOL_DATA_ROOT.$tmpinvoice->last_main_doc); + $joinFileMime[] = dol_mimetype(DOL_DATA_ROOT.'/'.$tmpinvoice->last_main_doc); } // Mail Creation diff --git a/htdocs/compta/facture/contact.php b/htdocs/compta/facture/contact.php index 38d51f7b8b854..5c577ff0df634 100644 --- a/htdocs/compta/facture/contact.php +++ b/htdocs/compta/facture/contact.php @@ -55,12 +55,11 @@ if ($id > 0 || !empty($ref)) { $ret = $object->fetch($id, $ref, '', '', (!empty($conf->global->INVOICE_USE_SITUATION) ? $conf->global->INVOICE_USE_SITUATION : 0)); } - +$hookmanager->initHooks(array('invoicecontactcard', 'globalcard')); $result = restrictedArea($user, 'facture', $object->id); $usercancreate = $user->hasRight("facture", "creer"); - /* * Add a new contact */ diff --git a/htdocs/compta/facture/document.php b/htdocs/compta/facture/document.php index af633e14f908c..ed0498c67538d 100644 --- a/htdocs/compta/facture/document.php +++ b/htdocs/compta/facture/document.php @@ -79,6 +79,7 @@ if ($user->socid) { $socid = $user->socid; } +$hookmanager->initHooks(array('invoicedocument', 'globalcard')); $result = restrictedArea($user, 'facture', $object->id, ''); $usercancreate = $user->hasRight("facture", "creer"); diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 6a089f7a87dc6..d3469f3f74db0 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -422,8 +422,8 @@ $paiementAmount = $facture->getSommePaiement(); $totalcreditnotes = $facture->getSumCreditNotesUsed(); $totaldeposits = $facture->getSumDepositsUsed(); - $totalpay = $paiementAmount + $totalcreditnotes + $totaldeposits; - $remaintopay = price2num($facture->total_ttc - $totalpay); + $totalallpayments = $paiementAmount + $totalcreditnotes + $totaldeposits; + $remaintopay = price2num($facture->total_ttc - $totalallpayments); if ($remaintopay != 0) { $resultBank = $facture->setBankAccount($bankid); if ($resultBank < 0) { @@ -1821,6 +1821,9 @@ $totalarray['val']['f.total_tva'] = 0; $totalarray['val']['f.total_ht'] = 0; $totalarray['val']['f.total_ttc'] = 0; + $totalarray['val']['dynamount_payed'] = 0; + $totalarray['val']['rtp'] = 0; + $with_margin_info = false; if (isModEnabled('margin') && ( @@ -1907,8 +1910,8 @@ $multicurrency_totalcreditnotes = $facturestatic->getSumCreditNotesUsed(1); $multicurrency_totaldeposits = $facturestatic->getSumDepositsUsed(1); - $totalpay = $paiement + $totalcreditnotes + $totaldeposits; - $remaintopay = price2num($facturestatic->total_ttc - $totalpay); + $totalallpayments = $paiement + $totalcreditnotes + $totaldeposits; + $remaintopay = $obj->total_ttc - $totalallpayments; $multicurrency_totalpay = $multicurrency_paiement + $multicurrency_totalcreditnotes + $multicurrency_totaldeposits; $multicurrency_remaintopay = price2num($facturestatic->multicurrency_total_ttc - $multicurrency_totalpay); @@ -1920,13 +1923,16 @@ if ($facturestatic->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1) { // If credit note closed, we take into account the amount not yet consumed $remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id); $remaintopay = -$remaincreditnote; - $totalpay = price2num($facturestatic->total_ttc - $remaintopay); + $totalallpayments = price2num($facturestatic->total_ttc - $remaintopay); $multicurrency_remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id, 0, 0, 1); $multicurrency_remaintopay = -$multicurrency_remaincreditnote; $multicurrency_totalpay = price2num($facturestatic->multicurrency_total_ttc - $multicurrency_remaintopay); } $facturestatic->alreadypaid = $paiement; + $facturestatic->totalpaid = $paiement; + $facturestatic->totalcreditnotes = $totalcreditnotes; + $facturestatic->totaldeposits = $totaldeposits; $marginInfo = array(); if ($with_margin_info === true) { @@ -2379,14 +2385,14 @@ } if (!empty($arrayfields['dynamount_payed']['checked'])) { - print ''.(!empty($totalpay) ? price($totalpay, 0, $langs) : ' ').''; // TODO Use a denormalized field + print ''.(!empty($totalallpayments) ? price($totalallpayments, 0, $langs) : ' ').''; // TODO Use a denormalized field if (!$i) { $totalarray['nbfield']++; } if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalam'; + $totalarray['pos'][$totalarray['nbfield']] = 'dynamount_payed'; } - $totalarray['val']['totalam'] += $totalpay; + $totalarray['val']['dynamount_payed'] += $totalallpayments; } // Pending amount @@ -2577,7 +2583,7 @@ // Status if (!empty($arrayfields['f.fk_statut']['checked'])) { print ''; - print $facturestatic->getLibStatut(5, $paiement); + print $facturestatic->getLibStatut(5, $totalallpayments); print ""; if (!$i) { $totalarray['nbfield']++; diff --git a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php index 04d7f97baef17..c002e5a7e5fe1 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php @@ -86,11 +86,24 @@ print ''; print ''; + $totalallpayments = 0; + $totalcalculated = false; if (method_exists($objectlink, 'getSommePaiement')) { print $objectlink->getLibStatut(3, $objectlink->getSommePaiement()); + $totalcalculated = true; + $totalallpayments += $objectlink->getSommePaiement(); } else { print $objectlink->getLibStatut(3); } + if (method_exists($objectlink, 'getSumDepositsUsed')) { + $totalcalculated = true; + $totalallpayments += $objectlink->getSumDepositsUsed(); + } + if (method_exists($objectlink, 'getSumCreditNotesUsed')) { + $totalcalculated = true; + $totalallpayments += $objectlink->getSumCreditNotesUsed(); + } + print $objectlink->getLibStatut(3, ($totalcalculated ? $totalallpayments : -1)); print ''; print ''.img_picto($langs->transnoentitiesnoconv("RemoveLink"), 'unlink').''; print "\n"; diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index a340d7ef7c372..e7df99729bb65 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -215,6 +215,9 @@ $thirdpartystatic->code_compta = $obj->code_compta; //$thirdpartystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; + $totalallpayments = $tmpinvoice->getSommePaiement(0); + $totalallpayments += $tmpinvoice->getSumCreditNotesUsed(0); + $totalallpayments += $tmpinvoice->getSumDepositsUsed(0); print ''; print ''; @@ -247,7 +250,7 @@ print 'jdate($obj->tms), 'dayhour', 'tzuserrel')).'">'.dol_print_date($db->jdate($obj->tms), 'day', 'tzuserrel').''; - print ''.$tmpinvoice->getLibStatut(3, $obj->am).''; + print ''.$tmpinvoice->getLibStatut(3, $totalallpayments).''; print ''; @@ -377,6 +380,8 @@ print ''.price($obj->total_ttc).''; print 'jdate($obj->tms), 'dayhour', 'tzuserrel')).'">'.dol_print_date($db->jdate($obj->tms), 'day', 'tzuserrel').''; $alreadypaid = $facstatic->getSommePaiement(); + $alreadypaid += $facstatic->getSumCreditNotesUsed(); + $alreadypaid += $facstatic->getSumDepositsUsed(); print ''.$facstatic->getLibStatut(3, $alreadypaid).''; print ''; $total_ht += $obj->total_ht; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index ea36236689b55..cb8eaf0f8bf32 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -888,10 +888,10 @@ function callForResult(imgId) print '
'; if (!empty($totalpayment)) { - $text = $langs->trans('ConfirmCustomerPayment', $totalpayment, $langs->trans("Currency".$conf->currency)); + $text = $langs->trans('ConfirmCustomerPayment', $totalpayment, $langs->transnoentitiesnoconv("Currency".$conf->currency)); } if (!empty($multicurrency_totalpayment)) { - $text .= '
'.$langs->trans('ConfirmCustomerPayment', $multicurrency_totalpayment, $langs->trans("paymentInInvoiceCurrency")); + $text .= '
'.$langs->trans('ConfirmCustomerPayment', $multicurrency_totalpayment, $langs->transnoentitiesnoconv("paymentInInvoiceCurrency")); } if (GETPOST('closepaidinvoices')) { $text .= '
'.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed"); diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 94e2d570fcfa6..307d5a41f2766 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -1269,7 +1269,7 @@ public function getNomUrl($withpicto = 0, $option = '', $mode = 'withlistofinvoi $facturestatic = new Facture($this->db); foreach ($arraybill as $billid) { $facturestatic->fetch($billid); - $label .= '
'.$facturestatic->getNomUrl(1, '', 0, 0, '', 1).' '.$facturestatic->getLibStatut(2, 1); + $label .= '
'.$facturestatic->getNomUrl(1, '', 0, 0, '', 1).' '.$facturestatic->getLibStatut(2, -1); } } } diff --git a/htdocs/compta/paiement/list.php b/htdocs/compta/paiement/list.php index 7ac0669a28a6f..85c57d3538559 100644 --- a/htdocs/compta/paiement/list.php +++ b/htdocs/compta/paiement/list.php @@ -183,6 +183,8 @@ $sql = "SELECT p.rowid, p.ref, p.datep, p.amount, p.statut, p.num_paiement"; $sql .= ", c.code as paiement_code"; + $sqlfields = $sql; // $sql fields to remove for count total + // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook @@ -197,10 +199,13 @@ $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; } else { - $sql = "SELECT p.rowid, p.ref, p.datep, p.fk_bank, p.amount, p.statut, p.num_paiement"; + $sql = "SELECT p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount"; $sql .= ", c.code as paiement_code"; $sql .= ", ba.rowid as bid, ba.ref as bref, ba.label as blabel, ba.number, ba.account_number as account_number, ba.fk_accountancy_journal as accountancy_journal"; $sql .= ", s.rowid as socid, s.nom as name, s.email"; + // We need an aggregate because we added a left join to get the thirdparty. In real world, it should be the same thirdparty if payment is same (but not in database structure) + // so SUM(pf.amount) should be equal to p.amount but if we filter on $socid, it may differ + $sql .= ", SUM(pf.amount) as totalamount, COUNT(f.rowid) as nbinvoices"; // Add fields from hooks $parameters = array(); @@ -213,18 +218,21 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON p.fk_paiement = c.id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank as b ON p.fk_bank = b.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON b.fk_account = ba.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON p.rowid = pf.fk_paiement"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON pf.fk_facture = f.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql .= " WHERE p.entity IN (".getEntity('invoice').")"; if ($socid > 0) { - $sql .= " AND f.fk_soc = ".((int) $socid); + $sql .= " AND EXISTS (SELECT f.fk_soc FROM ".MAIN_DB_PREFIX."facture as f, ".MAIN_DB_PREFIX."paiement_facture as pf"; + $sql .= " WHERE p.rowid = pf.fk_paiement AND pf.fk_facture = f.rowid AND f.fk_soc = ".((int) $socid).")"; } if ($userid) { if ($userid == -1) { - $sql .= " AND f.fk_user_author IS NULL"; + $sql .= " AND p.fk_user_creat IS NULL"; } else { - $sql .= " AND f.fk_user_author = ".((int) $userid); + $sql .= " AND p.fk_user_creat = ".((int) $userid); } } @@ -248,7 +256,10 @@ $sql .= natural_search('p.num_paiement', $search_payment_num); } if ($search_amount) { - $sql .= natural_search('p.amount', $search_amount, 1); + $sql .= " AND (".natural_search('p.amount', $search_amount, 1, 1); + $sql .= " OR "; + $sql .= natural_search('pf.amount', $search_amount, 1, 1); + $sql .= ")"; } if ($search_company) { $sql .= natural_search('s.nom', $search_company); @@ -270,13 +281,18 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; + + $sql .= " GROUP BY p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount"; + $sql .= ", c.code"; + $sql .= ", ba.rowid, ba.ref, ba.label, ba.number, ba.account_number, ba.fk_accountancy_journal"; + $sql .= ", s.rowid, s.nom, s.email"; } // Count total nb of records $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { /* The fast and low memory method to get and count full list converts the sql into a sql count */ - $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(DISTINCT p.rowid) as nbtotalofrecords', $sql); $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); $resql = $db->query($sqlforcount); if ($resql) { @@ -298,6 +314,7 @@ if ($limit) { $sql .= $db->plimit($limit + 1, $offset); } +//print $sql; $resql = $db->query($sql); if (!$resql) { @@ -532,6 +549,8 @@ $object->id = $objp->rowid; $object->ref = ($objp->ref ? $objp->ref : $objp->rowid); + $object->date = $db->jdate($objp->datep); + $object->amount = $objp->amount; $companystatic->id = $objp->socid; $companystatic->name = $objp->name; @@ -629,7 +648,12 @@ // Amount if (!empty($arrayfields['p.amount']['checked'])) { - print ''.price($objp->amount).''; + print ''; + if ($objp->nbinvoices > 1 || ($objp->totalamount && $objp->amount != $objp->totalamount)) { + print $form->textwithpicto('', $langs->trans("PaymentMadeForSeveralInvoices")); + } + print ''.price($objp->amount).''; + print ''; if (!$i) { $totalarray['nbfield']++; } diff --git a/htdocs/compta/prelevement/index.php b/htdocs/compta/prelevement/index.php index 71677f0051c2e..dbe814569f09b 100644 --- a/htdocs/compta/prelevement/index.php +++ b/htdocs/compta/prelevement/index.php @@ -101,7 +101,7 @@ /* * Invoices waiting for withdraw */ -$sql = "SELECT f.ref, f.rowid, f.total_ttc, f.fk_statut, f.paye, f.type,"; +$sql = "SELECT f.ref, f.rowid, f.total_ttc, f.fk_statut as status, f.paye, f.type,"; $sql .= " pfd.date_demande, pfd.amount,"; $sql .= " s.nom as name, s.email, s.rowid as socid, s.tva_intra, s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4, s.idprof5, s.idprof6"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,"; @@ -141,10 +141,13 @@ $invoicestatic->id = $obj->rowid; $invoicestatic->ref = $obj->ref; - $invoicestatic->statut = $obj->fk_statut; + $invoicestatic->statut = $obj->status; + $invoicestatic->status = $obj->status; $invoicestatic->paye = $obj->paye; $invoicestatic->type = $obj->type; - $alreadypayed = $invoicestatic->getSommePaiement(); + $totalallpayments = $invoicestatic->getSommePaiement(0); + $totalallpayments += $invoicestatic->getSumCreditNotesUsed(0); + $totalallpayments += $invoicestatic->getSumDepositsUsed(0); $thirdpartystatic->id = $obj->socid; $thirdpartystatic->name = $obj->name; @@ -177,7 +180,7 @@ print ''; print ''; - print $invoicestatic->getLibStatut(3, $alreadypayed); + print $invoicestatic->getLibStatut(3, $totalallpayments); print ''; print ''; $i++; diff --git a/htdocs/compta/recap-compta.php b/htdocs/compta/recap-compta.php index 0808e5a7aab20..73ed206943813 100644 --- a/htdocs/compta/recap-compta.php +++ b/htdocs/compta/recap-compta.php @@ -159,7 +159,9 @@ print $fac->error."
"; continue; } - $totalpaid = $fac->getSommePaiement(); + $alreadypaid = $fac->getSommePaiement(); + $alreadypaid += $fac->getSumDepositsUsed(); + $alreadypaid += $fac->getSumCreditNotesUsed(); $userstatic->id = $objf->userid; $userstatic->login = $objf->login; @@ -169,7 +171,7 @@ 'date' => $fac->date, 'datefieldforsort' => $fac->date.'-'.$fac->ref, 'link' => $fac->getNomUrl(1), - 'status' => $fac->getLibStatut(2, $totalpaid), + 'status' => $fac->getLibStatut(2, $alreadypaid), 'amount' => $fac->total_ttc, 'author' => $userstatic->getLoginUrl(1) ); diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 8fb4310692e80..0634c8bdac232 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -259,7 +259,7 @@ print ''.$langs->trans("PreviousPeriod").''; print ''.$langs->trans("SelectedPeriod").''; foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { + if (($k + 1) >= $date_startmonth && $k < $date_endmonth) { print ''.$langs->trans('MonthShort'.sprintf("%02s", ($k + 1))).''; } } @@ -392,7 +392,7 @@ // Detail by month foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { + if (($k + 1) >= $date_startmonth && $k < $date_endmonth) { foreach ($sommes as $code => $det) { $vars[$code] = empty($det['M'][$k]) ? 0 : $det['M'][$k]; } @@ -591,7 +591,7 @@ // Each month foreach ($totCat['M'] as $k => $v) { - if (($k + 1) >= $date_startmonth) { + if (($k + 1) >= $date_startmonth && $k < $date_endmonth) { print ''.price($v).''; } } @@ -632,7 +632,7 @@ // Make one call for each month foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { + if (($k + 1) >= $date_startmonth && $k < $date_endmonth) { if (isset($cpt['account_number'])) { $resultM = $totPerAccount[$cpt['account_number']]['M'][$k]; } else { diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 69a6989153639..48e8b51087700 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -102,7 +102,7 @@ 'cs.fk_type' =>array('label'=>"Type", 'checked'=>1, 'position'=>30), 'cs.date_ech' =>array('label'=>"Date", 'checked'=>1, 'position'=>40), 'cs.periode' =>array('label'=>"PeriodEndDate", 'checked'=>1, 'position'=>50), - 'p.ref' =>array('label'=>"ProjectRef", 'checked'=>1, 'position'=>60, 'enable'=>(isModEnabled('project'))), + 'p.ref' =>array('label'=>"ProjectRef", 'checked'=>1, 'position'=>60, 'enabled'=>(isModEnabled('project'))), 'cs.fk_user' =>array('label'=>"Employee", 'checked'=>1, 'position'=>70), 'cs.fk_mode_reglement' =>array('checked'=>-1, 'position'=>80, 'label'=>"DefaultPaymentMode"), 'cs.amount' =>array('label'=>"Amount", 'checked'=>1, 'position'=>100), diff --git a/htdocs/compta/stats/cabyprodserv.php b/htdocs/compta/stats/cabyprodserv.php index 27b5a5b2723b4..4a31057b74a91 100644 --- a/htdocs/compta/stats/cabyprodserv.php +++ b/htdocs/compta/stats/cabyprodserv.php @@ -503,7 +503,7 @@ // Quantity print ''; - print $qty[$key]; + print price($qty[$key], 1, $langs, 0, 0); print ''; // Percent; diff --git a/htdocs/compta/tva/list.php b/htdocs/compta/tva/list.php index 9e5a28b6905a9..ec2ee333490f2 100644 --- a/htdocs/compta/tva/list.php +++ b/htdocs/compta/tva/list.php @@ -719,7 +719,8 @@ } if (!empty($arrayfields['t.status']['checked'])) { - print '' . $tva_static->getLibStatut(5, $obj->alreadypayed) . ''; + $totalallpayments = $obj->alreadypayed; + print '' . $tva_static->getLibStatut(5, $totalallpayments) . ''; if (!$i) { $totalarray['nbfield']++; } diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 66760c4586f5e..257eef6cb2a18 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -454,15 +454,13 @@ $no_email = GETPOST('no_email', 'int'); $result = $object->setNoEmail($no_email); if ($result < 0) { + $error++; setEventMessages($object->error, $object->errors, 'errors'); - $action = 'edit'; } } - - $action = 'view'; } else { + $error++; setEventMessages($object->error, $object->errors, 'errors'); - $action = 'edit'; } } } @@ -472,6 +470,9 @@ header("Location: ".$backtopage); exit; } + $action = 'view'; + } else { + $action = 'edit'; } } @@ -568,7 +569,9 @@ $title = $object->lastname; } $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; -$title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("NewContact") : $langs->trans("NewContactAddress")); +if (empty($object->id)) { + $title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("NewContact") : $langs->trans("NewContactAddress")); +} llxHeader('', $title, $help_url); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 0ed49cc8aa67b..4366be5b60467 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -802,6 +802,8 @@ $result = $objectline->update($user); if ($result < 0) { $error++; + $action = 'editline'; + $_GET['rowid'] = GETPOST('elrowid'); setEventMessages($objectline->error, $objectline->errors, 'errors'); } } @@ -1711,7 +1713,7 @@ $line = new ContratLigne($db); $line->id = $objp->rowid; $line->fetch_optionals(); - print $line->showOptionals($extrafields, 'view', array('class'=>'oddeven', 'style'=>$moreparam, 'colspan'=>$colspan), '', '', 1); + print $line->showOptionals($extrafields, 'view', array('class'=>'oddeven', 'style'=>$moreparam, 'colspan'=>$colspan, 'tdclass' => 'notitlefieldcreate'), '', '', 1); } } else { // Line in mode update @@ -1815,7 +1817,7 @@ $line = new ContratLigne($db); $line->id = $objp->rowid; $line->fetch_optionals(); - print $line->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan), '', '', 1); + print $line->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan, 'tdclass' => 'notitlefieldcreate'), '', '', 1); } } diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 65e5249bf82b9..3718c2740e029 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1621,7 +1621,8 @@ public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $contractline->id = $contractlineid; $result = $contractline->insertExtraFields(); if ($result < 0) { - $this->error[] = $contractline->error; + $this->errors = array_merge($this->errors, $contractline->errors); + $this->error = $contractline->error; $error++; } } diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 62cb1b62c69b5..a85f0d4714c36 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -482,10 +482,10 @@ $title = $langs->trans("ListOfRunningServices"); } if ($search_status == "4&filter=notexpired") { - $title = $langs->trans("ListOfNotExpiredRunningServices"); + $title = $langs->trans("ListOfNotExpiredServices"); } if ($search_status == "4&filter=expired") { - $title = $langs->trans("ListOfExpiredRunningServices"); + $title = $langs->trans("ListOfExpiredServices"); } if ($search_status == "5") { $title = $langs->trans("ListOfClosedServices"); diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 086b37aa501cd..25458a612e50d 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -95,7 +95,9 @@ } elseif ($object->fields[$key]['type'] == 'datetime') { $value = dol_mktime(GETPOST($key.'hour', 'int'), GETPOST($key.'min', 'int'), GETPOST($key.'sec', 'int'), GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int'), 'tzuserrel'); } elseif ($object->fields[$key]['type'] == 'duration') { - $value = 60 * 60 * GETPOST($key.'hour', 'int') + 60 * GETPOST($key.'min', 'int'); + $hour = intval(GETPOST($key.'hour', 'int')); + $min = intval(GETPOST($key.'min', 'int')); + $value = 60 * 60 * $hour + 60 * $min; } elseif (preg_match('/^(integer|price|real|double)/', $object->fields[$key]['type'])) { $value = price2num(GETPOST($key, 'alphanohtml')); // To fix decimal separator according to lang setup } elseif ($object->fields[$key]['type'] == 'boolean') { diff --git a/htdocs/core/ajax/objectonoff.php b/htdocs/core/ajax/objectonoff.php index 0818dc823a459..2d71b29cdbd60 100644 --- a/htdocs/core/ajax/objectonoff.php +++ b/htdocs/core/ajax/objectonoff.php @@ -77,7 +77,7 @@ // We check permission. // Check is done on $user->rights->element->create or $user->rights->element->subelement->create (because $action = 'set') -if (preg_match('/status$/', $field) || ($field == 'evenunsubscribe' && $object->table_element == 'mailing')) { +if (preg_match('/statu[st]$/', $field) || ($field == 'evenunsubscribe' && $object->table_element == 'mailing')) { restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission); } elseif ($element == 'product' && in_array($field, array('tosell', 'tobuy', 'tobatch'))) { // Special case for products restrictedArea($user, 'produit|service', $object, 'product&product', '', '', 'rowid'); diff --git a/htdocs/core/ajax/selectobject.php b/htdocs/core/ajax/selectobject.php index 14372a405b4ab..d94e9c65caa77 100644 --- a/htdocs/core/ajax/selectobject.php +++ b/htdocs/core/ajax/selectobject.php @@ -79,7 +79,11 @@ $searchkey = (($id && GETPOST($id, 'alpha')) ? GETPOST($id, 'alpha') : (($htmlname && GETPOST($htmlname, 'alpha')) ? GETPOST($htmlname, 'alpha') : '')); // Add a security test to avoid to get content of all tables -restrictedArea($user, $objecttmp->element, $id); +if (!empty($objecttmp->module)) { + restrictedArea($user, $objecttmp->module, $id, $objecttmp->table_element, $objecttmp->element); +} else { + restrictedArea($user, $objecttmp->element, $id); +} /* diff --git a/htdocs/core/ajax/selectsearchbox.php b/htdocs/core/ajax/selectsearchbox.php index 05f8c8d215e2d..987701edf425b 100644 --- a/htdocs/core/ajax/selectsearchbox.php +++ b/htdocs/core/ajax/selectsearchbox.php @@ -95,7 +95,7 @@ if (isModEnabled('project') && empty($conf->global->MAIN_SEARCHFORM_PROJECT_DISABLED) && $user->hasRight('projet', 'lire')) { $arrayresult['searchintoprojects'] = array('position'=>40, 'shortcut'=>'Q', 'img'=>'object_project', 'label'=>$langs->trans("SearchIntoProjects", $search_boxvalue), 'text'=>img_picto('', 'object_project', 'class="pictofixedwidth"').' '.$langs->trans("SearchIntoProjects", $search_boxvalue), 'url'=>DOL_URL_ROOT.'/projet/list.php'.($search_boxvalue ? '?search_all='.urlencode($search_boxvalue) : '')); } -if (isModEnabled('project') && empty($conf->global->MAIN_SEARCHFORM_TASK_DISABLED) && $user->hasRight('projet', 'lire')) { +if (isModEnabled('project') && empty($conf->global->MAIN_SEARCHFORM_TASK_DISABLED) && empty($conf->global->PROJECT_HIDE_TASKS) && $user->hasRight('projet', 'lire')) { $arrayresult['searchintotasks'] = array('position'=>45, 'img'=>'object_projecttask', 'label'=>$langs->trans("SearchIntoTasks", $search_boxvalue), 'text'=>img_picto('', 'object_projecttask', 'class="pictofixedwidth"').' '.$langs->trans("SearchIntoTasks", $search_boxvalue), 'url'=>DOL_URL_ROOT.'/projet/tasks/list.php'.($search_boxvalue ? '?search_all='.urlencode($search_boxvalue) : '')); } diff --git a/htdocs/core/boxes/box_actions.php b/htdocs/core/boxes/box_actions.php index 840d6c06ffc6d..fc7b46f4be887 100644 --- a/htdocs/core/boxes/box_actions.php +++ b/htdocs/core/boxes/box_actions.php @@ -106,7 +106,7 @@ public function loadBox($max = 5) $sql .= " AND s.rowid = ".((int) $user->socid); } if (!$user->hasRight('agenda', 'allactions', 'read')) { - $sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id)." OR a.fk_user_done = ".((int) $user->id).")"; + $sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id).")"; } $sql .= " ORDER BY a.datep ASC"; $sql .= $this->db->plimit($max, 0); diff --git a/htdocs/core/boxes/box_external_rss.php b/htdocs/core/boxes/box_external_rss.php index 8bc4943e50b63..70786334fa654 100644 --- a/htdocs/core/boxes/box_external_rss.php +++ b/htdocs/core/boxes/box_external_rss.php @@ -167,7 +167,6 @@ public function loadBox($max = 5, $cachedelay = 3600) $title = preg_replace("/([[:alnum:]])\?([[:alnum:]])/", "\\1'\\2", $title); // Gere probleme des apostrophes mal codee/decodee par utf8 $title = preg_replace("/^\s+/", "", $title); // Supprime espaces de debut - $this->info_box_contents["$href"] = "$title"; $tooltip = $title; $description = !empty($item['description']) ? $item['description'] : ''; diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 48b3690a92f6b..db8b30ed2497a 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -80,19 +80,20 @@ class CMailFile */ public $errors = array(); - public $smtps; // Contains SMTPs object (if this method is used) - public $phpmailer; // Contains PHPMailer object (if this method is used) /** - * @var Swift_SmtpTransport + * @var SMTPS (if this method is used) */ - public $transport; - + public $smtps; /** - * @var Swift_Mailer + * @var Swift_Mailer (if the method is used) */ public $mailer; + /** + * @var Swift_SmtpTransport + */ + public $transport; /** * @var Swift_Plugins_Loggers_ArrayLogger */ @@ -107,9 +108,13 @@ class CMailFile //! Defined background directly in body tag public $bodyCSS; + /** + * @var string Message-ID of the email to send (generated) + */ public $msgid; public $headers; public $message; + /** * @var array fullfilenames list (full path of filename on file system) */ @@ -513,13 +518,15 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array() //$this->message = new Swift_SignedMessage(); // Adding a trackid header to a message $headers = $this->message->getHeaders(); + $headers->addTextHeader('X-Dolibarr-TRACKID', $this->trackid.'@'.$host); $this->msgid = time().'.swiftmailer-dolibarr-'.$this->trackid.'@'.$host; $headerID = $this->msgid; $msgid = $headers->get('Message-ID'); $msgid->setId($headerID); - $headers->addIdHeader('References', $headerID); - // TODO if (!empty($moreinheader)) ... + + // Add 'References:' header + //$headers->addIdHeader('References', $headerID); // Give the message a subject try { @@ -652,7 +659,6 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array() } } - /** * Send mail that was prepared by constructor. * @@ -888,7 +894,7 @@ public function sendfile() } } elseif ($this->sendmode == 'smtps') { if (!is_object($this->smtps)) { - $this->error = "Failed to send mail with smtps lib to HOST=".$server.", PORT=".$conf->global->$keyforsmtpport."
Constructor of object CMailFile was not initialized without errors."; + $this->error = "Failed to send mail with smtps lib to HOST=".ini_get('SMTP').", PORT=".$conf->global->$keyforsmtpport."
Constructor of object CMailFile was not initialized without errors."; dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); return false; } @@ -1184,9 +1190,10 @@ public function sendfile() $res = true; if (!empty($this->error) || !empty($this->errors) || !$result) { if (!empty($failedRecipients)) { - $this->errors[] = 'Transport failed for the following addresses: "' . join('", "', $failedRecipients) . '".'; + $this->error = 'Transport failed for the following addresses: "' . join('", "', $failedRecipients) . '".'; + $this->errors[] = $this->error; } - dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); + dol_syslog("CMailFile::sendfile: mail end error=". join(' ', $this->errors), LOG_ERR); $res = false; if (!empty($conf->global->MAIN_MAIL_DEBUG)) { @@ -1451,7 +1458,7 @@ public function write_smtpheaders() // References is kept in response and Message-ID is returned into In-Reply-To: $this->msgid = time().'.phpmail-dolibarr-'.$trackid.'@'.$host; $out .= 'Message-ID: <'.$this->msgid.">".$this->eol2; // Uppercase seems replaced by phpmail - $out .= 'References: <'.$this->msgid.">".$this->eol2; + //$out .= 'References: <'.$this->msgid.">".$this->eol2; $out .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host.$this->eol2; } else { $this->msgid = time().'.phpmail@'.$host; diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 70f859dd487aa..1d7008aae59ca 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -324,6 +324,7 @@ public function get_substitutionarray_thirdparty($object, $outputlangs, $array_k 'company_juridicalstatus'=>$object->forme_juridique, 'company_outstanding_limit'=>$object->outstanding_limit, 'company_capital'=>$object->capital, + 'company_capital_formated'=> price($object->capital, 0, '', 1, -1), 'company_idprof1'=>$object->idprof1, 'company_idprof2'=>$object->idprof2, 'company_idprof3'=>$object->idprof3, @@ -747,16 +748,20 @@ public function get_substitutionarray_lines($line, $outputlangs, $linenumber = 0 if (isset($line->fk_product) && $line->fk_product > 0) { $tmpproduct = new Product($this->db); $result = $tmpproduct->fetch($line->fk_product); - foreach ($tmpproduct->array_options as $key => $label) { - $resarray["line_product_".$key] = $label; + if (!empty($tmpproduct->array_options) && is_array($tmpproduct->array_options)) { + foreach ($tmpproduct->array_options as $key => $label) { + $resarray["line_product_".$key] = $label; + } } } else { // Set unused placeholders as blank $extrafields->fetch_name_optionals_label("product"); $extralabels = $extrafields->attributes["product"]['label']; - foreach ($extralabels as $key => $label) { - $resarray['line_product_options_'.$key] = ''; + if (!empty($extralabels) && is_array($extralabels)) { + foreach ($extralabels as $key => $label) { + $resarray['line_product_options_'.$key] = ''; + } } } @@ -879,8 +884,11 @@ public function get_substitutionarray_shipment_lines($line, $outputlangs) if (isset($line->fk_product) && $line->fk_product > 0) { $tmpproduct = new Product($this->db); $tmpproduct->fetch($line->fk_product); - foreach ($tmpproduct->array_options as $key=>$label) - $resarray["line_product_".$key] = $label; + if (!empty($tmpproduct->array_options) && is_array($tmpproduct->array_options)) { + foreach ($tmpproduct->array_options as $key=>$label) { + $resarray["line_product_".$key] = $label; + } + } } return $resarray; @@ -910,13 +918,17 @@ public function get_substitutionarray_each_var_object(&$object, $outputlangs, $r $array_other['object_'.$key] = $value; } elseif (is_array($value) && $recursive) { $tmparray = $this->get_substitutionarray_each_var_object($value, $outputlangs, 0); - foreach ($tmparray as $key2 => $value2) { - $array_other['object_'.$key.'_'.preg_replace('/^object_/', '', $key2)] = $value2; + if (!empty($tmparray) && is_array($tmparray)) { + foreach ($tmparray as $key2 => $value2) { + $array_other['object_'.$key.'_'.preg_replace('/^object_/', '', $key2)] = $value2; + } } } elseif (is_object($value) && $recursive) { $tmparray = $this->get_substitutionarray_each_var_object($value, $outputlangs, 0); - foreach ($tmparray as $key2 => $value2) { - $array_other['object_'.$key.'_'.preg_replace('/^object_/', '', $key2)] = $value2; + if (!empty($tmparray) && is_array($tmparray)) { + foreach ($tmparray as $key2 => $value2) { + $array_other['object_'.$key.'_'.preg_replace('/^object_/', '', $key2)] = $value2; + } } } } @@ -1350,7 +1362,9 @@ public function getExtrafieldContent($object, $extrafieldKey, $outputlangs = nul $extrafields = $this->extrafieldsCache; $extrafieldOutputContent = ''; - if (isset($object->array_options[$extrafieldOptionsKey])) $extrafieldOutputContent = $extrafields->showOutputField($extrafieldKey, $object->array_options[$extrafieldOptionsKey], '', $object->table_element); + if (isset($object->array_options[$extrafieldOptionsKey])) { + $extrafieldOutputContent = $extrafields->showOutputField($extrafieldKey, $object->array_options[$extrafieldOptionsKey], '', $object->table_element, $outputlangs); + } // TODO : allow showOutputField to be pdf public friendly, ex: in a link to object, clean getNomUrl to remove link and images... like a getName methode ... if ($extrafields->attributes[$object->table_element]['type'][$extrafieldKey] == 'link') { @@ -1458,6 +1472,9 @@ public function getExtrafieldsInHtml($object, $outputlangs, $params = array()) $field = new stdClass(); $field->rank = intval($extrafields->attributes[$object->table_element]['pos'][$key]); $field->content = $this->getExtrafieldContent($object, $key, $outputlangs); + if (isset($extrafields->attributes[$object->table_element]['langfile'][$key])) { + $outputlangs->load($extrafields->attributes[$object->table_element]['langfile'][$key]); + } $field->label = $outputlangs->transnoentities($label); $field->type = $extrafields->attributes[$object->table_element]['type'][$key]; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0ee2c772ffc2e..8c5a84c9120b8 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -619,6 +619,19 @@ abstract class CommonObject public $user_modification_id; + /** + * @var int ID + * @deprecated Use $user_creation_id + */ + public $fk_user_creat; + + /** + * @var int ID + * @deprecated Use $user_modification_id + */ + public $fk_user_modif; + + public $next_prev_filter; /** @@ -3114,7 +3127,7 @@ public function getChildrenOfLine($id, $includealltree = 0) while ($row = $this->db->fetch_row($resql)) { $rows[] = $row[0]; if (!empty($includealltree)) { - $rows = array_merge($rows, $this->getChildrenOfLine($row[0]), $includealltree); + $rows = array_merge($rows, $this->getChildrenOfLine($row[0], $includealltree)); } } } @@ -4528,7 +4541,7 @@ public function getSpecialCode($lineid) $resql = $this->db->query($sql); if ($resql) { $row = $this->db->fetch_row($resql); - return $row[0]; + return (!empty($row[0]) ? $row[0] : 0); } return 0; @@ -6215,7 +6228,7 @@ public function insertExtraFields($trigger = '', $userused = null) foreach ($new_array_options as $key => $value) { $attributeKey = substr($key, 8); // Remove 'options_' prefix $attributeType = $extrafields->attributes[$this->table_element]['type'][$attributeKey]; - $attributeLabel = $extrafields->attributes[$this->table_element]['label'][$attributeKey]; + $attributeLabel = $langs->transnoentities($extrafields->attributes[$this->table_element]['label'][$attributeKey]); $attributeParam = $extrafields->attributes[$this->table_element]['param'][$attributeKey]; $attributeRequired = $extrafields->attributes[$this->table_element]['required'][$attributeKey]; $attributeUnique = $extrafields->attributes[$this->table_element]['unique'][$attributeKey]; @@ -9058,9 +9071,9 @@ protected function isIndex($info) /** - * Function to prepare a part of the query for insert by returning an array with all properties of object. + * Function to return the array of data key-value from the ->fields and all the ->properties of an object. * - * Note $this->${field} are set by the page that make the createCommon() or the updateCommon(). + * Note: $this->${field} are set by the page that make the createCommon() or the updateCommon(). * $this->${field} should be a clean and string value (so date are formated for SQL insert). * * @return array Array with all values of each properties to update @@ -9263,6 +9276,11 @@ public function createCommon(User $user, $notrigger = false) } if (array_key_exists('fk_user_creat', $fieldvalues) && !($fieldvalues['fk_user_creat'] > 0)) { $fieldvalues['fk_user_creat'] = $user->id; + $this->fk_user_creat = $user->id; + } + if (array_key_exists('user_modification_id', $fieldvalues) && !($fieldvalues['user_modification_id'] > 0)) { + $fieldvalues['user_modification_id'] = $user->id; + $this->user_modification_id = $user->id; } unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into insert. if (array_key_exists('ref', $fieldvalues)) { @@ -9499,6 +9517,7 @@ public function fetchLinesCommon($morewhere = '') if ($resql) { $num_rows = $this->db->num_rows($resql); $i = 0; + $this->lines = array(); while ($i < $num_rows) { $obj = $this->db->fetch_object($resql); if ($obj) { diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 094d1ab3e11d7..7b1188f6f9ada 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -186,9 +186,11 @@ public function __construct() $this->user = new stdClass(); $this->adherent = new stdClass(); $this->bank = new stdClass(); + $this->mailing = new stdClass(); $this->notification = new stdClass(); $this->expensereport = new stdClass(); $this->productbatch = new stdClass(); + $this->api = new stdClass(); } /** diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 288eadc69034e..5c990aa9c941c 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1582,12 +1582,17 @@ public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $ * @param string $value Value to show * @param string $moreparam To add more parameters on html input tag (only checkbox use html input for output rendering) * @param string $extrafieldsobjectkey Required (for example $object->table_element). + * @param Translate $outputlangs Output language * @return string Formated value */ - public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '') + public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '', $outputlangs = null) { global $conf, $langs; + if (is_null($outputlangs) || !is_object($outputlangs)) { + $outputlangs = $langs; + } + if (empty($extrafieldsobjectkey)) { dol_syslog(get_class($this).'::showOutputField extrafieldsobjectkey required', LOG_ERR); return 'BadValueForParamExtraFieldsObjectKey'; @@ -1636,7 +1641,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec //$value=price($value); $sizeparts = explode(",", $size); $number_decimals = array_key_exists(1, $sizeparts) ? $sizeparts[1] : 0; - $value = price($value, 0, $langs, 0, 0, $number_decimals, ''); + $value = price($value, 0, $outputlangs, 0, 0, $number_decimals, ''); } } elseif ($type == 'boolean') { $checked = ''; @@ -1655,7 +1660,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec } elseif ($type == 'price') { //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency); if ($value || $value == '0') { - $value = price($value, 0, $langs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$langs->getCurrencySymbol($conf->currency); + $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$outputlangs->getCurrencySymbol($conf->currency); } } elseif ($type == 'pricecy') { $currency = $conf->currency; @@ -1666,7 +1671,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec $value = $pricetmp[0]; } if ($value || $value == '0') { - $value = price($value, 0, $langs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency); + $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency); } } elseif ($type == 'select') { $valstr = (!empty($param['options'][$value]) ? $param['options'][$value] : ''); @@ -1674,7 +1679,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec $valstr = substr($valstr, 0, $pos); } if ($langfile && $valstr) { - $value = $langs->trans($valstr); + $value = $outputlangs->trans($valstr); } else { $value = $valstr; } @@ -1733,12 +1738,12 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec foreach ($fields_label as $field_toshow) { $translabel = ''; if (!empty($obj->$field_toshow)) { - $translabel = $langs->trans($obj->$field_toshow); + $translabel = $outputlangs->trans($obj->$field_toshow); if ($translabel != $obj->$field_toshow) { - $value .= dol_trunc($translabel, 24).' '; + $value .= dol_trunc($translabel, 24) . ' '; } else { - $value .= $obj->$field_toshow.' '; + $value .= $obj->$field_toshow . ' '; } } } @@ -1747,7 +1752,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec $tmppropname = $InfoFieldList[1]; //$obj->$tmppropname = ''; if (!empty(isset($obj->$tmppropname) ? $obj->$tmppropname : '')) { - $translabel = $langs->trans($obj->$tmppropname); + $translabel = $outputlangs->trans($obj->$tmppropname); } if ($translabel != (isset($obj->$tmppropname) ? $obj->$tmppropname : '')) { $value = dol_trunc($translabel, 18); @@ -1776,10 +1781,10 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec } } elseif ($type == 'radio') { if (!isset($param['options'][$value])) { - $langs->load('errors'); - $value = $langs->trans('ErrorNoValueForRadioType'); + $outputlangs->load('errors'); + $value = $outputlangs->trans('ErrorNoValueForRadioType'); } else { - $value = $langs->trans($param['options'][$value]); + $value = $outputlangs->trans($param['options'][$value]); } } elseif ($type == 'checkbox') { $value_arr = explode(',', $value); @@ -1843,7 +1848,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec foreach ($fields_label as $field_toshow) { $translabel = ''; if (!empty($obj->$field_toshow)) { - $translabel = $langs->trans($obj->$field_toshow); + $translabel = $outputlangs->trans($obj->$field_toshow); } if ($translabel != $field_toshow) { $label .= ' '.dol_trunc($translabel, 18); @@ -1856,7 +1861,7 @@ public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjec } else { $translabel = ''; if (!empty($obj->{$InfoFieldList[1]})) { - $translabel = $langs->trans($obj->{$InfoFieldList[1]}); + $translabel = $outputlangs->trans($obj->{$InfoFieldList[1]}); } if ($translabel != $obj->{$InfoFieldList[1]}) { $toprint[] = '
  • '.dol_trunc($translabel, 18).'
  • '; diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 6c43f5ce7970b..1cb35d40b8548 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -153,7 +153,7 @@ public function initHooks($arraycontext) * All types can also return some values into an array ->results that will be finaly merged into this->resArray for caller. * $this->error or this->errors are also defined by class called by this function if error. */ - public function executeHooks($method, $parameters = array(), &$object = '', &$action = '') + public function executeHooks($method, $parameters = array(), &$object = null, &$action = '') { if (!is_array($this->hooks) || empty($this->hooks)) { return 0; // No hook available, do nothing. @@ -208,6 +208,7 @@ public function executeHooks($method, $parameters = array(), &$object = '', &$ac // Init return properties $localResPrint = ''; + $localResArray = array(); $this->resArray = array(); $this->resNbOfHooks = 0; @@ -263,9 +264,9 @@ public function executeHooks($method, $parameters = array(), &$object = '', &$ac if (isset($actionclassinstance->results) && is_array($actionclassinstance->results)) { if ($resactiontmp > 0) { - $this->resArray = $actionclassinstance->results; + $localResArray = $actionclassinstance->results; } else { - $this->resArray = array_merge($this->resArray, $actionclassinstance->results); + $localResArray = array_merge($localResArray, $actionclassinstance->results); } } if (!empty($actionclassinstance->resprints)) { @@ -291,7 +292,7 @@ public function executeHooks($method, $parameters = array(), &$object = '', &$ac $resaction += $resactiontmp; if (!empty($actionclassinstance->results) && is_array($actionclassinstance->results)) { - $this->resArray = array_merge($this->resArray, $actionclassinstance->results); + $localResArray = array_merge($localResArray, $actionclassinstance->results); } if (!empty($actionclassinstance->resprints)) { $localResPrint .= $actionclassinstance->resprints; @@ -321,6 +322,7 @@ public function executeHooks($method, $parameters = array(), &$object = '', &$ac } $this->resPrint = $localResPrint; + $this->resArray = $localResArray; return ($error ? -1 : $resaction); } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 2d0291e1bd353..67a8dab78453c 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3381,9 +3381,10 @@ public function select_produits_fournisseurs_list($socid, $selected = '', $htmln } $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock, p.tva_tx as tva_tx_sale, p.default_vat_code as default_vat_code_sale,"; - $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,"; - $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name,"; - $sql .= " pfp.supplier_reputation"; + $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice"; + $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice"; + $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name"; + $sql .= ", pfp.supplier_reputation"; // if we use supplier description of the products if (!empty($conf->global->PRODUIT_FOURN_TEXTS)) { $sql .= ", pfp.desc_fourn as description"; @@ -3689,6 +3690,10 @@ public function select_produits_fournisseurs_list($socid, $selected = '', $htmln $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"'; $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"'; $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"'; + if (isModEnabled('multicurrency')) { + $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"'; + $optstart .= ' data-multicurrency-up="' . dol_escape_htmltag($objp->multicurrency_unitprice) . '"'; + } } $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"'; @@ -3710,6 +3715,10 @@ public function select_produits_fournisseurs_list($socid, $selected = '', $htmln 'disabled' => (empty($objp->idprodfournprice) ? true : false), 'description' => $objp->description ); + if (isModEnabled('multicurrency')) { + $outarrayentry['multicurrency_code'] = $objp->multicurrency_code; + $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU'); + } $parameters = array( 'objp' => &$objp, @@ -3725,29 +3734,33 @@ public function select_produits_fournisseurs_list($socid, $selected = '', $htmln // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax // "label" value of json key array is used by jQuery automatically as text for combo box $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "\n"; - array_push( - $outarray, - array('key' => $outkey, - 'value' => $outref, - 'label' => $outvallabel, - 'qty' => $outqty, - 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty - 'price_qty_ht_locale' => price($objp->fprice), - 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price - 'price_unit_ht_locale' => price($objp->unitprice), - 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility) - 'tva_tx_formated' => price($objp->tva_tx), - 'tva_tx' => price2num($objp->tva_tx), - 'default_vat_code' => $objp->default_vat_code, - 'discount' => $outdiscount, - 'type' => $outtype, - 'duration_value' => $outdurationvalue, - 'duration_unit' => $outdurationunit, - 'disabled' => (empty($objp->idprodfournprice) ? true : false), - 'description' => $objp->description - ) + $outarraypush = array( + 'key' => $outkey, + 'value' => $outref, + 'label' => $outvallabel, + 'qty' => $outqty, + 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty + 'price_qty_ht_locale' => price($objp->fprice), + 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price + 'price_unit_ht_locale' => price($objp->unitprice), + 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility) + 'tva_tx_formated' => price($objp->tva_tx), + 'tva_tx' => price2num($objp->tva_tx), + 'default_vat_code' => $objp->default_vat_code, + 'discount' => $outdiscount, + 'type' => $outtype, + 'duration_value' => $outdurationvalue, + 'duration_unit' => $outdurationunit, + 'disabled' => (empty($objp->idprodfournprice) ? true : false), + 'description' => $objp->description ); - // Exemple of var_dump $outarray + if (isModEnabled('multicurrency')) { + $outarraypush['multicurrency_code'] = $objp->multicurrency_code; + $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU'); + } + array_push($outarray, $outarraypush); + + // Example of var_dump $outarray // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp" // ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)" // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false) @@ -5938,9 +5951,9 @@ public function form_multicurrency_rate($page, $rate = '', $htmlname = 'multicur print ''; } else { if (!empty($rate)) { - print price($rate, 1, $langs, 1, 0); + print price($rate, 1, $langs, 0, 0); if ($currency && $rate != 1) { - print '   (' . price($rate, 1, $langs, 1, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')'; + print '   (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')'; } } else { print 1; @@ -6348,7 +6361,7 @@ public function load_cache_vatrates($country_code) if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) { $langs->load("errors"); $new_country_code = $reg[1]; - $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid'); + $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_country', 'code', 'rowid'); $this->error .= '
    '.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : '')); } $this->error .= ''; diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index ac6bbc42e0d69..03b9695b18fc9 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -26,6 +26,9 @@ class FormSetup */ public $db; + /** @var int */ + public $entity; + /** @var FormSetupItem[] */ public $items = array(); @@ -86,7 +89,8 @@ class FormSetup */ public function __construct($db, $outputLangs = false) { - global $langs; + global $conf, $langs; + $this->db = $db; $this->form = new Form($this->db); $this->formAttributes['action'] = $_SERVER["PHP_SELF"]; @@ -94,6 +98,7 @@ public function __construct($db, $outputLangs = false) $this->formHiddenInputs['token'] = newToken(); $this->formHiddenInputs['action'] = 'update'; + $this->entity = (is_null($this->entity) ? $conf->entity : $this->entity); if ($outputLangs) { $this->langs = $outputLangs; @@ -446,6 +451,8 @@ public function newItem($confKey, $targetItemKey = false, $insertAfterTarget = f { $item = new FormSetupItem($confKey); + $item->entity = $this->entity; + // set item rank if not defined as last item if (empty($item->rank)) { $item->rank = $this->getCurentItemMaxRank() + 1; @@ -638,7 +645,7 @@ class FormSetupItem /** * Constructor * - * @param string $confKey the conf key used in database + * @param string $confKey the conf key used in database */ public function __construct($confKey) { @@ -652,7 +659,7 @@ public function __construct($confKey) } $this->langs = $langs; - $this->entity = $conf->entity; + $this->entity = (is_null($this->entity) ? $conf->entity : ((int) $this->entity)); $this->confKey = $confKey; $this->loadValueFromConf(); @@ -1089,7 +1096,7 @@ public function generateOutputField() $out.= $this->generateOutputFieldColor(); } elseif ($this->type == 'yesno') { if (!empty($conf->use_javascript_ajax)) { - $out.= ajax_constantonoff($this->confKey); + $out.= ajax_constantonoff($this->confKey, array(), $this->entity); // TODO possibility to add $input parameter } else { if ($this->fieldValue == 1) { $out.= $langs->trans('yes'); diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 74287b1bd0b19..6f8b8fd687e4c 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -549,6 +549,7 @@ public function send($notifcode, $object, $filename_list = array(), $mimetype_li $link = ''.$newref.''; $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object); $object_type = 'order_supplier'; + $labeltouse = isset($conf->global->ORDER_SUPPLIER_VALIDATE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_VALIDATE_TEMPLATE : ''; $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n"; $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderValidatedBy", $link, $user->getFullName($outputlangs)); $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n"; @@ -557,6 +558,7 @@ public function send($notifcode, $object, $filename_list = array(), $mimetype_li $link = ''.$newref.''; $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object); $object_type = 'order_supplier'; + $labeltouse = isset($conf->global->ORDER_SUPPLIER_APPROVE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_APPROVE_TEMPLATE : ''; $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n"; $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderApprovedBy", $link, $user->getFullName($outputlangs)); $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n"; @@ -565,6 +567,7 @@ public function send($notifcode, $object, $filename_list = array(), $mimetype_li $link = ''.$newref.''; $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object); $object_type = 'order_supplier'; + $labeltouse = isset($conf->global->ORDER_SUPPLIER_REFUSE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_REFUSE_TEMPLATE : ''; $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n"; $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextOrderRefusedBy", $link, $user->getFullName($outputlangs)); $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n"; @@ -899,12 +902,29 @@ public function send($notifcode, $object, $filename_list = array(), $mimetype_li $mimefilename_list[] = $ref.".pdf"; } - $message = ''; - $message .= $langs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n"; - $message .= "\n"; - $message .= $mesg; + // if an e-mail template is configured for this notification code (for instance + // 'SHIPPING_VALIDATE_TEMPLATE'), we fetch this template by its label. Otherwise, a default message + // content will be sent. + $mailTemplateLabel = isset($conf->global->{$notifcode.'_TEMPLATE'}) ? $conf->global->{$notifcode.'_TEMPLATE'} : ''; + $emailTemplate = null; + if (!empty($mailTemplateLabel)) { + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + $formmail = new FormMail($this->db); + $emailTemplate = $formmail->getEMailTemplate($this->db, $object_type.'_send', $user, $langs, 0, 1, $labeltouse); + } + if (!empty($mailTemplateLabel) && is_object($emailTemplate) && $emailTemplate->id > 0) { + $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); + complete_substitutions_array($substitutionarray, $langs, $object); + $subject = make_substitutions($emailTemplate->topic, $substitutionarray, $langs); + $message = make_substitutions($emailTemplate->content, $substitutionarray, $langs); + } else { + $message = ''; + $message .= $langs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n"; + $message .= "\n"; + $message .= $mesg; - $message = nl2br($message); + $message = nl2br($message); + } // Replace keyword __SUPERVISOREMAIL__ if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) { diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index 0ab9bd3ef8d31..cec01ddcac53b 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -654,9 +654,8 @@ public function sendMsg() global $conf; require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; - /** - * Default return value - */ + + // Default return value $_retVal = false; // Connect to Server @@ -1450,10 +1449,10 @@ public function getHeader() $trackid = $this->getTrackId(); if ($trackid) { - // References is kept in response and Message-ID is returned into In-Reply-To: $_header .= 'Message-ID: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n"; - $_header .= 'References: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n"; $_header .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host."\r\n"; + // References and In-Reply-To: will be set by caller + //$_header .= 'References: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n"; } else { $_header .= 'Message-ID: <'.time().'.SMTPs@'.$host.">\r\n"; } @@ -1464,10 +1463,6 @@ public function getHeader() $_header .= $this->getMoreInHeader(); // Value must include the "\r\n"; } - //$_header .= - // 'Read-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n" - // 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n"; - if ($this->getSensitivity()) { $_header .= 'Sensitivity: '.$this->getSensitivity()."\r\n"; } @@ -1492,6 +1487,7 @@ public function getHeader() $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART ? 'MAIN_MAIL_USE_MULTI_PART' : 'No MAIN_MAIL_USE_MULTI_PART')."\r\n"; $_header .= 'Mime-Version: 1.0'."\r\n"; + // TODO Add also $this->references and In-Reply-To return $_header; } diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index 1f6eace6163f6..e78cf55d34449 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -102,23 +102,23 @@ public function purgeFiles($choices = 'tempfilesold+logfiles', $nbsecondsold = 8 } if ($choice == 'allfiles') { - // Delete all files (except install.lock, do not follow symbolic links) + // Delete all files (except .lock and .unlock files, do not follow symbolic links) if ($dolibarr_main_data_root) { - $filesarray = dol_dir_list($dolibarr_main_data_root, "all", 0, '', 'install\.lock$', 'name', SORT_ASC, 0, 0, '', 1); // No need to use recursive, we will delete directory + $filesarray = dol_dir_list($dolibarr_main_data_root, "all", 0, '', '(\.lock|\.unlock)$', 'name', SORT_ASC, 0, 0, '', 1); // No need to use recursive, we will delete directory } } if ($choice == 'allfilesold') { - // Delete all files (except install.lock, do not follow symbolic links) + // Delete all files (except .lock and .unlock files, do not follow symbolic links) if ($dolibarr_main_data_root) { - $filesarray = dol_dir_list($dolibarr_main_data_root, "files", 1, '', 'install\.lock$', 'name', SORT_ASC, 0, 0, '', 1, $nbsecondsold); // No need to use recursive, we will delete directory + $filesarray = dol_dir_list($dolibarr_main_data_root, "files", 1, '', '(\.lock|\.unlock)$', 'name', SORT_ASC, 0, 0, '', 1, $nbsecondsold); // No need to use recursive, we will delete directory } } if ($choice == 'logfile' || $choice == 'logfiles') { // Define files log if ($dolibarr_main_data_root) { - $filesarray = dol_dir_list($dolibarr_main_data_root, "files", 0, '.*\.log[\.0-9]*(\.gz)?$', 'install\.lock$', 'name', SORT_ASC, 0, 0, '', 1); + $filesarray = dol_dir_list($dolibarr_main_data_root, "files", 0, '.*\.log[\.0-9]*(\.gz)?$', '(\.lock|\.unlock)$', 'name', SORT_ASC, 0, 0, '', 1); } if (isModEnabled('syslog')) { @@ -146,7 +146,13 @@ public function purgeFiles($choices = 'tempfilesold+logfiles', $nbsecondsold = 8 $result = dol_delete_dir_recursive($filesarray[$key]['fullname'], $startcount, 1, 0, $tmpcountdeleted); - if (!in_array($filesarray[$key]['fullname'], array($conf->api->dir_temp, $conf->user->dir_temp))) { // The 2 directories $conf->api->dir_temp and $conf->user->dir_temp are recreated at end, so we do not count them + $recreatedDirs = array($conf->user->dir_temp); + + if (isModEnabled('api')) { + $recreatedDirs[] = $conf->api->dir_temp; + } + + if (!in_array($filesarray[$key]['fullname'], $recreatedDirs)) { // The 2 directories $conf->api->dir_temp and $conf->user->dir_temp are recreated at end, so we do not count them $count += $result; $countdeleted += $tmpcountdeleted; } @@ -526,13 +532,13 @@ public function dumpDatabase($compression = 'none', $type = 'auto', $usedefault } elseif ($compression == 'zstd') { fclose($handle); } - if ($ok && preg_match('/^-- (MySql|MariaDB)/i', $errormsg)) { // No error + if ($ok && preg_match('/^-- (MySql|MariaDB)/i', $errormsg) || preg_match('/^\/\*M?!999999/', $errormsg)) { // Start of file is ok, NOT an error $errormsg = ''; } else { - // Renommer fichier sortie en fichier erreur + // Rename file out into a file error //print "$outputfile -> $outputerror"; @dol_delete_file($outputerror, 1, 0, 0, null, false, 0); - @rename($outputfile, $outputerror); + @dol_move($outputfile, $outputerror, '0', 1, 0, 0); // Si safe_mode on et command hors du parametre exec, on a un fichier out vide donc errormsg vide if (!$errormsg) { $langs->load("errors"); diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index f04dd7a991ee6..e7d6a7b5b6345 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -94,7 +94,7 @@ // Objects available by default $arrayoftype = array( 'thirdparty' => array('langs'=>'companies', 'label' => 'ThirdParties', 'picto'=>'company', 'ObjectClassName' => 'Societe', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/societe/class/societe.class.php"), - 'contact' => array('label' => 'Contacts', 'picto'=>'contact', 'ObjectClassName' => 'Contact', 'enabled' => isModEnabled('societ'), 'ClassPath' => "/contact/class/contact.class.php"), + 'contact' => array('label' => 'Contacts', 'picto'=>'contact', 'ObjectClassName' => 'Contact', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/contact/class/contact.class.php"), 'proposal' => array('label' => 'Proposals', 'picto'=>'proposal', 'ObjectClassName' => 'Propal', 'enabled' => isModEnabled('propal'), 'ClassPath' => "/comm/propal/class/propal.class.php"), 'order' => array('label' => 'Orders', 'picto'=>'order', 'ObjectClassName' => 'Commande', 'enabled' => isModEnabled('commande'), 'ClassPath' => "/commande/class/commande.class.php"), 'invoice' => array('langs'=>'facture', 'label' => 'Invoices', 'picto'=>'bill', 'ObjectClassName' => 'Facture', 'enabled' => isModEnabled('facture'), 'ClassPath' => "/compta/facture/class/facture.class.php"), diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 2923992e34578..a5d226804b329 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -1273,9 +1273,9 @@ public function DDLUpdateField($table, $field_name, $field_desc) if (isset($field_desc['default']) && $field_desc['default'] != '') { if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sql .= " DEFAULT ".$this->escape($field_desc['default']); + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT ".((float) $field_desc['default']); } elseif ($field_desc['type'] != 'text') { - $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields } } diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 34ca110dd1eb2..67f64a766617c 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -163,6 +163,14 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen price_ttc: item.price_ttc, price_unit_ht: item.price_unit_ht, price_unit_ht_locale: item.price_unit_ht_locale, + '; + if (isModEnabled('multicurrency')) { + $script .= ' + multicurrency_code: item.multicurrency_code, + multicurrency_unitprice: item.multicurrency_unitprice, + '; + } + $script .= ' description : item.description, ref_customer: item.ref_customer, tva_tx: item.tva_tx, @@ -194,7 +202,14 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen $("#'.$htmlnamejquery.'").attr("data-tvatx", ui.item.tva_tx); $("#'.$htmlnamejquery.'").attr("data-default-vat-code", ui.item.default_vat_code); '; - if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { + if (isModEnabled('multicurrency')) { + $script .= ' + // For multi-currency values + $("#'.$htmlnamejquery.'").attr("data-multicurrency-code", ui.item.multicurrency_code); + $("#'.$htmlnamejquery.'").attr("data-multicurrency-unitprice", ui.item.multicurrency_unitprice); + '; + } + if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { $script .= ' // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on console.log("PRODUIT_CUSTOMER_PRICES_BY_QTY is on, propagate also prices by quantity into data-pbqxxx properties"); diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index fd231091af1a1..82e42792144a8 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -71,7 +71,7 @@ function societe_prepare_head(Societe $object) $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql .= " WHERE p.fk_soc = ".((int) $object->id); - $sql .= " AND entity IN (".getEntity($object->element).")"; + $sql .= " AND p.entity IN (".getEntity($object->element).")"; // Add where from hooks $parameters = array('contacttab' => true); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index 479417cc32fe4..fb57502d6fe43 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -34,31 +34,32 @@ function get_tz_array() { $tzarray = array( - -11=>"Pacific/Midway", - -10=>"Pacific/Fakaofo", - -9=>"America/Anchorage", - -8=>"America/Los_Angeles", - -7=>"America/Dawson_Creek", - -6=>"America/Chicago", - -5=>"America/Bogota", - -4=>"America/Anguilla", - -3=>"America/Araguaina", - -2=>"America/Noronha", - -1=>"Atlantic/Azores", - 0=>"Africa/Abidjan", - 1=>"Europe/Paris", - 2=>"Europe/Helsinki", - 3=>"Europe/Moscow", - 4=>"Asia/Dubai", - 5=>"Asia/Karachi", - 6=>"Indian/Chagos", - 7=>"Asia/Jakarta", - 8=>"Asia/Hong_Kong", - 9=>"Asia/Tokyo", - 10=>"Australia/Sydney", - 11=>"Pacific/Noumea", - 12=>"Pacific/Auckland", - 13=>"Pacific/Enderbury" + -11 => "Pacific/Pago_Pago", + -10 => "Pacific/Honolulu", + -9 => "America/Anchorage", + -8 => "America/Los_Angeles", + -7 => "America/Dawson_Creek", + -6 => "America/Chicago", + -5 => "America/Bogota", + -4 => "America/Asuncion", + -3 => "America/Araguaina", + -2 => "America/Noronha", + -1 => "Atlantic/Azores", + 0 => "Europe/London", + 1 => "Europe/Paris", + 2 => "Europe/Helsinki", + 3 => "Europe/Moscow", + 4 => "Asia/Dubai", + 5 => "Asia/Karachi", + 6 => "Indian/Chagos", + 7 => "Asia/Jakarta", + 8 => "Asia/Hong_Kong", + 9 => "Asia/Tokyo", + 10 => "Australia/Sydney", + 11 => "Pacific/Noumea", + 12 => "Pacific/Auckland", + 13 => "Pacific/Fakaofo", + 14 => "Pacific/Kiritimati" ); return $tzarray; } diff --git a/htdocs/core/lib/expensereport.lib.php b/htdocs/core/lib/expensereport.lib.php index fd72aa16135f3..10f9d243031b4 100644 --- a/htdocs/core/lib/expensereport.lib.php +++ b/htdocs/core/lib/expensereport.lib.php @@ -81,7 +81,7 @@ function expensereport_prepare_head($object) $head[$h][2] = 'info'; $h++; - complete_head_from_modules($conf, $langs, $object, $head, $h, 'donation', 'add', 'external'); + complete_head_from_modules($conf, $langs, $object, $head, $h, 'expensereport', 'add', 'external'); complete_head_from_modules($conf, $langs, $object, $head, $h, 'expensereport', 'remove'); diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 7c03180136990..2ed990205ad69 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2605,7 +2605,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, // Find the subdirectory name as the reference. For example original_file='10/myfile.pdf' -> refname='10' if (empty($refname)) { $refname = basename(dirname($original_file)."/"); - if ($refname == 'thumbs') { + if ($refname == 'thumbs' || $refname == 'temp') { // If we get the thumbs directory, we must go one step higher. For example original_file='10/thumbs/myfile_small.jpg' -> refname='10' $refname = basename(dirname(dirname($original_file))."/"); } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index cf8bb9b324e83..c3bab3ce70c05 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -971,6 +971,9 @@ function sanitizeVal($out = '', $check = 'alphanohtml', $filter = null, $options } break; case 'intcomma': + if (is_array($out)) { + $out = implode(',', $out); + } if (preg_match('/[^0-9,-]+/i', $out)) { $out = ''; } @@ -2448,7 +2451,16 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi } else { $morehtmlstatus .= ''.$object->getLibStatut(6, 1).''; } - } elseif (in_array($object->element, array('facture', 'invoice', 'invoice_supplier', 'chargesociales', 'loan', 'tva', 'salary'))) { + } elseif (in_array($object->element, array('facture', 'invoice', 'invoice_supplier'))) { + $totalallpayments = $object->getSommePaiement(0); + $totalallpayments += $object->getSumCreditNotesUsed(0); + $totalallpayments += $object->getSumDepositsUsed(0); + $tmptxt = $object->getLibStatut(6, $totalallpayments); + if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { + $tmptxt = $object->getLibStatut(5, $totalallpayments); + } + $morehtmlstatus .= $tmptxt; + } elseif (in_array($object->element, array('chargesociales', 'loan', 'tva'))) { $tmptxt = $object->getLibStatut(6, $object->totalpaid); if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { $tmptxt = $object->getLibStatut(5, $object->totalpaid); @@ -2968,6 +2980,10 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = */ function dol_getdate($timestamp, $fast = false, $forcetimezone = '') { + if ($timestamp === '') { + return array(); + } + $datetimeobj = new DateTime(); $datetimeobj->setTimestamp($timestamp); // Use local PHP server timezone if ($forcetimezone) { @@ -5928,9 +5944,10 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ $nbdecimal = dol_strlen($decpart); } // Si on depasse max - if ($trunc && $nbdecimal > $conf->global->MAIN_MAX_DECIMALS_SHOWN) { - $nbdecimal = $conf->global->MAIN_MAX_DECIMALS_SHOWN; - if (preg_match('/\.\.\./i', $conf->global->MAIN_MAX_DECIMALS_SHOWN)) { + $max_nbdecimal = (int) str_replace('...', '', getDolGlobalString('MAIN_MAX_DECIMALS_SHOWN')); + if ($trunc && $nbdecimal > $max_nbdecimal) { + $nbdecimal = $max_nbdecimal; + if (preg_match('/\.\.\./i', getDolGlobalString('MAIN_MAX_DECIMALS_SHOWN'))) { // Si un affichage est tronque, on montre des ... $end = '...'; } @@ -8027,12 +8044,12 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__MEMBER_PHONEPRO__'] = (isset($object->phone_perso) ? dol_print_phone($object->phone_perso) : ''); $substitutionarray['__MEMBER_PHONEMOBILE__'] = (isset($object->phone_mobile) ? dol_print_phone($object->phone_mobile) : ''); $substitutionarray['__MEMBER_TYPE__'] = (isset($object->type) ? $object->type : ''); - $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'dayrfc'); - $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = (isset($object->first_subscription_date_start) ? dol_print_date($object->first_subscription_date_start, 'dayrfc') : ''); - $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = (isset($object->first_subscription_date_end) ? dol_print_date($object->first_subscription_date_end, 'dayrfc') : ''); - $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE__'] = dol_print_date($object->last_subscription_date, 'dayrfc'); - $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->last_subscription_date_start, 'dayrfc'); - $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->last_subscription_date_end, 'dayrfc'); + $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'day'); + $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = (isset($object->first_subscription_date_start) ? dol_print_date($object->first_subscription_date_start, 'day') : ''); + $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = (isset($object->first_subscription_date_end) ? dol_print_date($object->first_subscription_date_end, 'day') : ''); + $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE__'] = dol_print_date($object->last_subscription_date, 'day'); + $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->last_subscription_date_start, 'day'); + $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->last_subscription_date_end, 'day'); } if (is_object($object) && $object->element == 'societe') { @@ -8129,9 +8146,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $datenextexpiration = $line->date_end; } } - $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = dol_print_date($dateplannedstart, 'dayrfc'); + $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = dol_print_date($dateplannedstart, 'day'); $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = dol_print_date($dateplannedstart, 'standard'); - $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = dol_print_date($datenextexpiration, 'dayrfc'); + $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = dol_print_date($datenextexpiration, 'day'); $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = dol_print_date($datenextexpiration, 'standard'); } // add substition variable for ticket @@ -9289,22 +9306,28 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' // We block use of php exec or php file functions $forbiddenphpstrings = array('$$'); - $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST')); + $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST', 'ReflectionFunction')); $forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen"); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("dol_eval", "executeCLI", "verifCond")); // native dolibarr functions - $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode")); // decode string functions + $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode", "str_rot13", "hex2bin")); // decode string functions used to obfuscated function name $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask")); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("get_defined_functions", "get_defined_vars", "get_defined_constants", "get_declared_classes")); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func")); + $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("require", "include", "require_once", "include_once")); $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("eval", "create_function", "assert", "mb_ereg_replace")); // function with eval capabilities + $forbiddenphpmethods = array('invoke', 'invokeArgs'); // Method of ReflectionFunction to execute a function + $forbiddenphpregex = 'global\s+\$|\b('.implode('|', $forbiddenphpfunctions).')\b'; + $forbiddenphpmethodsregex = '->('.implode('|', $forbiddenphpmethods).')'; + do { $oldstringtoclean = $s; $s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s); $s = preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s); + $s = preg_replace('/'.$forbiddenphpmethodsregex.'/i', '__forbiddenstring__', $s); //$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod( } while ($oldstringtoclean != $s); diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 9dfae331e51ae..cfb2c97db4436 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1303,17 +1303,15 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ } } } - // Show page nb only on iso languages (so default Helvetica font) - $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0)); - if (getDolGlobalString('PDF_USE_GETALIASNBPAGE_FOR_TOTAL')) { - // $pagination = $pdf->getAliasNumPage().' / '.$pdf->getAliasNbPages(); // works with $pdf->Cell - $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages(); // seems to not works with all fonts like ru_UK - } else { - $pagination = $pdf->PageNo().' / '.$pdf->getNumPages(); // seems to always work even with $pdf->Cell. But some users has reported wrong nb (no way to reproduce) + // Show page nb and apply correction for some font. + $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0)); + $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages(); + $fontRenderCorrection = 0; + if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) { + $fontRenderCorrection = 10; } - - $pdf->MultiCell(18, 2, $pagination, 0, 'R', 0); + $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', 0); // Show Draft Watermark if (!empty($watermark)) { diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index f6c4bdcdb5f98..ea495890ad893 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -452,7 +452,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_propale['nb']; print ''; - print $product->stats_propale['qty']; + print price($product->stats_propale['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -471,7 +471,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_proposal_supplier['nb']; print ''; - print $product->stats_proposal_supplier['qty']; + print price($product->stats_proposal_supplier['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -490,7 +490,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_commande['nb']; print ''; - print $product->stats_commande['qty']; + print price($product->stats_commande['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -509,7 +509,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_commande_fournisseur['nb']; print ''; - print $product->stats_commande_fournisseur['qty']; + print price($product->stats_commande_fournisseur['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -528,7 +528,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_facture['nb']; print ''; - print $product->stats_facture['qty']; + print price($product->stats_facture['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -566,7 +566,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_facture_fournisseur['nb']; print ''; - print $product->stats_facture_fournisseur['qty']; + print price($product->stats_facture_fournisseur['qty'], 1, $langs, 0, 0); print ''; print ''; } @@ -586,7 +586,7 @@ function show_stats_for_company($product, $socid) print ''; print $product->stats_contrat['nb']; print ''; - print $product->stats_contrat['qty']; + print price($product->stats_contrat['qty'], 1, $langs, 0, 0); print ''; print ''; } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 257fd2775146b..baa71408fd6a9 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -553,14 +553,16 @@ function project_admin_prepare_head() $head[$h][2] = 'attributes'; $h++; - $head[$h][0] = DOL_URL_ROOT.'/projet/admin/project_task_extrafields.php'; - $head[$h][1] = $langs->trans("ExtraFieldsProjectTask"); - $nbExtrafields = $extrafields->attributes['projet_task']['count']; - if ($nbExtrafields > 0) { - $head[$h][1] .= ''.$nbExtrafields.''; + if (empty($conf->global->PROJECT_HIDE_TASKS)) { + $head[$h][0] = DOL_URL_ROOT . '/projet/admin/project_task_extrafields.php'; + $head[$h][1] = $langs->trans("ExtraFieldsProjectTask"); + $nbExtrafields = $extrafields->attributes['projet_task']['count']; + if ($nbExtrafields > 0) { + $head[$h][1] .= '' . $nbExtrafields . ''; + } + $head[$h][2] = 'attributes_task'; + $h++; } - $head[$h][2] = 'attributes_task'; - $h++; if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { $langs->load("members"); diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 2f4d4fe2f839a..7609da636fe8d 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -884,7 +884,10 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $feature = 'agenda'; $dbtablename = 'actioncomm'; } - if ($feature == 'payment_sc') { + if ($feature == 'payment_sc' && empty($parenttableforentity)) { + // If we check perm on payment page but $parenttableforentity not defined, we force value on parent table + $parenttableforentity = ''; + $dbtablename = "chargesociales"; $feature = "chargesociales"; $objectid = $object->fk_charge; } @@ -892,7 +895,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $checkonentitydone = 0; // Array to define rules of checks to do - $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales'); // Test on entity only (Objects with no link to company) + $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales', 'knowledgemanagement'); // Test on entity only (Objects with no link to company) $checksoc = array('societe'); // Test for object Societe $checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...). $checkproject = array('projet', 'project'); // Test for project object diff --git a/htdocs/core/lib/ticket.lib.php b/htdocs/core/lib/ticket.lib.php index 0e6ddfba0b562..fd777fbac2b1c 100644 --- a/htdocs/core/lib/ticket.lib.php +++ b/htdocs/core/lib/ticket.lib.php @@ -162,7 +162,7 @@ function showDirectPublicLink($object) $email = CMailFile::getValidAddress($object->origin_email, 2); $url = ''; if ($email) { - $url = dol_buildpath('/public/ticket/view.php', 3).'?track_id='.$object->track_id.'&email='.$email; + $url = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/', 3)).'view.php?track_id='.$object->track_id.'&email='.$email; } $out = ''; diff --git a/htdocs/core/lib/treeview.lib.php b/htdocs/core/lib/treeview.lib.php index 8e8cfc453d1fa..e13e6654cfc55 100644 --- a/htdocs/core/lib/treeview.lib.php +++ b/htdocs/core/lib/treeview.lib.php @@ -103,7 +103,7 @@ function tree_showpad(&$fulltree, $key, $silent = 0) * TODO Replace with jstree plugin instead of treeview plugin. * * @param array $tab Array of all elements - * @param array $pere Array with parent ids ('rowid'=>,'mainmenu'=>,'leftmenu'=>,'fk_mainmenu=>,'fk_leftmenu=>) + * @param array $pere Array with parent ids ('rowid'=>,'mainmenu'=>,'leftmenu'=>,'fk_mainmenu'=>,'fk_leftmenu'=>) * @param int $rang Level of element * @param string $iddivjstree Id to use for parent ul element * @param int $donoresetalreadyloaded Do not reset global array $donoresetalreadyloaded used to avoid to go down on an aleady processed record @@ -142,13 +142,14 @@ function tree_recur($tab, $pere, $rang, $iddivjstree = 'iddivjstree', $donoreset return; // Protect against infinite loop. Max 50 depth } - //ballayage du tableau - $sizeoftab = count($tab); + // Loop on each element of tree $ulprinted = 0; - for ($x = 0; $x < $sizeoftab; $x++) { + foreach ($tab as $tmpkey => $tmpval) { + $x = $tmpkey; + //var_dump($tab[$x]);exit; // If an element has $pere for parent - if ($tab[$x]['fk_menu'] != -1 && $tab[$x]['fk_menu'] == $pere['rowid']) { + if ($tab[$x]['fk_menu'] != -1 && ((int) $tab[$x]['fk_menu']) == $pere['rowid']) { //print 'rang='.$rang.'-x='.$x." rowid=".$tab[$x]['rowid']." tab[x]['fk_leftmenu'] = ".$tab[$x]['fk_leftmenu']." leftmenu pere = ".$pere['leftmenu']."
    \n"; if (empty($ulprinted) && !empty($pere['rowid'])) { if (!empty($tree_recur_alreadyadded[$tab[$x]['rowid']])) { @@ -175,7 +176,7 @@ function tree_recur($tab, $pere, $rang, $iddivjstree = 'iddivjstree', $donoreset // And now we search all its sons of lower level tree_recur($tab, $tab[$x], $rang + 1, 'iddivjstree', 0, $showfk); print ''; - } elseif (!empty($tab[$x]['rowid']) && $tab[$x]['fk_menu'] == -1 && $tab[$x]['fk_mainmenu'] == $pere['mainmenu'] && $tab[$x]['fk_leftmenu'] == $pere['leftmenu']) { + } elseif (!empty($tab[$x]['rowid']) && ((int) $tab[$x]['fk_menu']) == -1 && $tab[$x]['fk_mainmenu'] == $pere['mainmenu'] && $tab[$x]['fk_leftmenu'] == $pere['leftmenu']) { //print 'rang='.$rang.'-x='.$x." rowid=".$tab[$x]['rowid']." tab[x]['fk_leftmenu'] = ".$tab[$x]['fk_leftmenu']." leftmenu pere = ".$pere['leftmenu']."
    \n"; if (empty($ulprinted) && !empty($pere['rowid'])) { if (!empty($tree_recur_alreadyadded[$tab[$x]['rowid']])) { diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index b95271560b2a3..86bfb42028351 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -412,6 +412,10 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("takepos") || isModEnabled("cashdesk"))', __HANDLER__, 'left', 6100__+MAX_llx_menu__, 'bank', 'cashcontrol', 14__+MAX_llx_menu__, '/compta/cashcontrol/cashcontrol_list.php?mainmenu=bank&action=list', 'CashControl', 0, 'cashdesk', '$user->hasRight("cashdesk", "run")|| $user->hasRight("takepos", "run")', '', 2, 6, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("takepos") || isModEnabled("cashdesk") && $leftmenu=="cashcontrol")', __HANDLER__, 'left', 6101__+MAX_llx_menu__, 'bank', 'cashcontrol', 6100__+MAX_llx_menu__, '/compta/cashcontrol/cashcontrol_card.php?mainmenu=bank&action=create', 'NewCashFence', 1, 'cashdesk', '$user->hasRight("cashdesk", "run")|| $user->hasRight("takepos", "run")', '', 2, 6, __ENTITY__); +-- Bank - Cash control POS +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("takepos") || isModEnabled("cashdesk"))', __HANDLER__, 'left', 6100__+MAX_llx_menu__, 'bank', 'cashcontrol', 14__+MAX_llx_menu__, '/compta/cashcontrol/cashcontrol_list.php?mainmenu=bank&action=list', 'CashControl', 0, 'cashdesk', '$user->hasRight("cashdesk", "run")|| $user->hasRight("takepos", "run")', '', 2, 6, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("takepos") || isModEnabled("cashdesk") && $leftmenu=="cashcontrol")', __HANDLER__, 'left', 6101__+MAX_llx_menu__, 'bank', 'cashcontrol', 6100__+MAX_llx_menu__, '/compta/cashcontrol/cashcontrol_card.php?mainmenu=bank&action=create', 'NewCashFence', 1, 'cashdesk', '$user->hasRight("cashdesk", "run")|| $user->hasRight("takepos", "run")', '', 2, 6, __ENTITY__); + -- Project insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("project")', __HANDLER__, 'left', 3600__+MAX_llx_menu__, 'project', 'projects', 7__+MAX_llx_menu__, '/projet/index.php?mainmenu=project&leftmenu=projects', 'LeadsOrProjects', 0, 'projects', '$user->hasRight("projet","lire")', '', 2, 0, __ENTITY__); diff --git a/htdocs/core/menus/standard/auguria.lib.php b/htdocs/core/menus/standard/auguria.lib.php index 091f2b7e9699e..6039dfad6212e 100644 --- a/htdocs/core/menus/standard/auguria.lib.php +++ b/htdocs/core/menus/standard/auguria.lib.php @@ -342,7 +342,7 @@ function print_left_auguria_menu($db, $menu_array_before, $menu_array_after, &$t $newmenu = $menuArbo->menuLeftCharger($newmenu, $mainmenu, $leftmenu, ($user->socid ? 1 : 0), 'auguria', $tabMenu); // We update newmenu for special dynamic menus - if (isModEnabled('banque') && $user->rights->banque->lire && $mainmenu == 'bank') { // Entry for each bank account + if (isModEnabled('banque') && $user->hasRight('banque', 'lire') && $mainmenu == 'bank') { // Entry for each bank account include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Required for to get Account::TYPE_CASH for example $sql = "SELECT rowid, label, courant, rappro, courant"; diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index b603f607e878d..dcaead425efc2 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1191,7 +1191,7 @@ function get_left_menu_home($mainmenu, &$newmenu, $usemenuhider = 1, $leftmenu = $newmenu->add("/categories/index.php?leftmenu=users&type=7", $langs->trans("UsersCategoriesShort"), 2, $user->hasRight('categorie', 'lire'), '', $mainmenu, 'cat'); } $newmenu->add("", $langs->trans("Groups"), 1, ($user->hasRight('user', 'user', 'lire') || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))); - $newmenu->add("/user/group/card.php?leftmenu=users&action=create", $langs->trans("NewGroup"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->hasRight("user", "group_advance", "create") : $user->hasRight("user", "user", "create")) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))); + $newmenu->add("/user/group/card.php?leftmenu=users&action=create", $langs->trans("NewGroup"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->hasRight("user", "group_advance", "create") : $user->hasRight("user", "user", "creer")) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))); $newmenu->add("/user/group/list.php?leftmenu=users", $langs->trans("ListOfGroups"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->hasRight('user', 'group_advance', 'read') : $user->hasRight('user', 'user', 'lire')) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))); } } @@ -1403,7 +1403,7 @@ function get_left_menu_commercial($mainmenu, &$newmenu, $usemenuhider = 1, $left if ($usemenuhider || empty($leftmenu) || $leftmenu == "contracts") { $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=0", $langs->trans("MenuInactiveServices"), 2, $user->hasRight('contrat', 'lire')); $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=4", $langs->trans("MenuRunningServices"), 2, $user->hasRight('contrat', 'lire')); - $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=4&filter=expired", $langs->trans("MenuExpiredServices"), 2, $user->hasRight('contrat', 'lire')); + $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=4%26filter=expired", $langs->trans("MenuExpiredServices"), 2, $user->hasRight('contrat', 'lire')); $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=5", $langs->trans("MenuClosedServices"), 2, $user->hasRight('contrat', 'lire')); } } @@ -1494,7 +1494,7 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen if (isModEnabled('commande')) { $langs->load("orders"); if (isModEnabled('facture')) { - $newmenu->add("/commande/list.php?leftmenu=orders&search_status=-3&billed=0&contextpage=billableorders", $langs->trans("MenuOrdersToBill2"), 0, $user->hasRight('commande', 'lire'), '', $mainmenu, 'orders', 0, '', '', '', img_picto('', 'order', 'class="paddingright pictofixedwidth"')); + $newmenu->add("/commande/list.php?leftmenu=orders&search_status=-3&search_billed=0&contextpage=billableorders", $langs->trans("MenuOrdersToBill2"), 0, $user->hasRight('commande', 'lire'), '', $mainmenu, 'orders', 0, '', '', '', img_picto('', 'order', 'class="paddingright pictofixedwidth"')); } //if ($usemenuhider || empty($leftmenu) || $leftmenu=="orders") $newmenu->add("/commande/", $langs->trans("StatusOrderToBill"), 1, $user->hasRight('commande', 'lire')); } @@ -1503,7 +1503,7 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen if (isModEnabled('supplier_invoice')) { if (!empty($conf->global->SUPPLIER_MENU_ORDER_RECEIVED_INTO_INVOICE)) { $langs->load("supplier"); - $newmenu->add("/fourn/commande/list.php?leftmenu=orders&search_status=5&billed=0", $langs->trans("MenuOrdersSupplierToBill"), 0, $user->hasRight('commande', 'lire'), '', $mainmenu, 'orders', 0, '', '', '', img_picto('', 'supplier_order', 'class="paddingright pictofixedwidth"')); + $newmenu->add("/fourn/commande/list.php?leftmenu=orders&search_status=5&search_billed=0", $langs->trans("MenuOrdersSupplierToBill"), 0, $user->hasRight('commande', 'lire'), '', $mainmenu, 'orders', 0, '', '', '', img_picto('', 'supplier_order', 'class="paddingright pictofixedwidth"')); //if ($usemenuhider || empty($leftmenu) || $leftmenu=="orders") $newmenu->add("/commande/", $langs->trans("StatusOrderToBill"), 1, $user->hasRight('commande', 'lire')); } } diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index b3852a562fbbd..a53c92736ffd3 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2003-2007 Rodolphe Quiedeville * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2004 Benoit Mortier - * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2004-2023 Eric Seigne * Copyright (C) 2005-2013 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2014 Raphaël Doursenaud @@ -1501,6 +1501,7 @@ public function insert_cronjobs() $frequency = isset($this->cronjobs[$key]['frequency']) ? $this->cronjobs[$key]['frequency'] : ''; $unitfrequency = isset($this->cronjobs[$key]['unitfrequency']) ? $this->cronjobs[$key]['unitfrequency'] : ''; $priority = isset($this->cronjobs[$key]['priority']) ? $this->cronjobs[$key]['priority'] : ''; + $datenextrun = isset($this->cronjobs[$key]['datenextrun']) ? $this->cronjobs[$key]['datenextrun'] : ''; $datestart = isset($this->cronjobs[$key]['datestart']) ? $this->cronjobs[$key]['datestart'] : ''; $dateend = isset($this->cronjobs[$key]['dateend']) ? $this->cronjobs[$key]['dateend'] : ''; $status = isset($this->cronjobs[$key]['status']) ? $this->cronjobs[$key]['status'] : ''; @@ -1536,7 +1537,7 @@ public function insert_cronjobs() $this->db->begin(); if (!$err) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."cronjob (module_name, datec, datestart, dateend, label, jobtype, classesname, objectname, methodename, command, params, note,"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."cronjob (module_name, datec, datenextrun, datestart, dateend, label, jobtype, classesname, objectname, methodename, command, params, note,"; if (is_int($frequency)) { $sql .= ' frequency,'; } @@ -1553,6 +1554,7 @@ public function insert_cronjobs() $sql .= " VALUES ("; $sql .= "'".$this->db->escape(empty($this->rights_class) ?strtolower($this->name) : $this->rights_class)."', "; $sql .= "'".$this->db->idate($now)."', "; + $sql .= ($datenextrun ? "'".$this->db->idate($datenextrun)."'" : "'".$this->db->idate($now)."'").", "; $sql .= ($datestart ? "'".$this->db->idate($datestart)."'" : "'".$this->db->idate($now)."'").", "; $sql .= ($dateend ? "'".$this->db->idate($dateend)."'" : "NULL").", "; $sql .= "'".$this->db->escape($label)."', "; diff --git a/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php b/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php index 15d95bde92e1a..ca77c6f13d088 100644 --- a/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php +++ b/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php @@ -262,8 +262,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php index 56057582d1100..cd47953cf86d9 100644 --- a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php +++ b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php @@ -1051,7 +1051,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php index 1fcc55446a8b2..9e3df7965fb1e 100644 --- a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php +++ b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php @@ -274,8 +274,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php index e8d7abfe0d701..6388479530797 100644 --- a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php +++ b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php @@ -280,8 +280,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 3f1a62c1b2b7e..7a5a2087e3445 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -988,8 +988,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1018,8 +1020,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1079,8 +1083,11 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1112,8 +1119,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1413,7 +1422,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index f6f9cf79bfa93..28e0db2d5f455 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1194,8 +1194,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1224,8 +1226,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1285,8 +1289,11 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1318,8 +1325,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1588,7 +1597,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index 515109c4f2036..dffded5555504 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -278,8 +278,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/contract/doc/pdf_strato.modules.php b/htdocs/core/modules/contract/doc/pdf_strato.modules.php index fe6f77b9b9ac4..5283418997894 100644 --- a/htdocs/core/modules/contract/doc/pdf_strato.modules.php +++ b/htdocs/core/modules/contract/doc/pdf_strato.modules.php @@ -7,6 +7,7 @@ * Copyright (C) 2013-2020 Philippe Grand * Copyright (C) 2015 Marcos García * Copyright (C) 2018-2020 Frédéric France + * Copyright (C) 2024 Éric Seigne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -300,11 +301,24 @@ public function write_file($object, $outputlangs, $srctemplatepath = '', $hidede $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 : 10); // Display notes - if (!empty($object->note_public)) { + $notetoshow = empty($object->note_public) ? '' : $object->note_public; + + // Extrafields in note + $extranote = $this->getExtrafieldsInHtml($object, $outputlangs); + if (!empty($extranote)) { + $notetoshow = dol_concatdesc($notetoshow, $extranote); + } + + if (!empty($notetoshow)) { $tab_top -= 2; + $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); + $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); + $pdf->SetFont('', '', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($object->note_public), 0, 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1); $nexY = $pdf->GetY(); $height_note = $nexY - $tab_top; diff --git a/htdocs/core/modules/contract/modules_contract.php b/htdocs/core/modules/contract/modules_contract.php index 577ec4be5d961..2089736b5c28c 100644 --- a/htdocs/core/modules/contract/modules_contract.php +++ b/htdocs/core/modules/contract/modules_contract.php @@ -41,6 +41,7 @@ abstract class ModelePDFContract extends CommonDocGenerator * @var string Error code (or message) */ public $error = ''; + public $posxdesc; // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php index 219c0f47029d5..a678d8265c527 100644 --- a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php +++ b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php @@ -278,8 +278,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index 297013ed8ac1e..a7481c0be4beb 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -847,11 +847,11 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $object->volume_units = $object->size_units * 3; } - if ($totalWeight != '') { - $totalWeighttoshow = showDimensionInBestUnit($totalWeight, 0, "weight", $outputlangs); + if (!empty($totalWeight)) { + $totalWeighttoshow = showDimensionInBestUnit($totalWeight, 0, "weight", $outputlangs, -1, 'no', 1); } - if ($totalVolume != '') { - $totalVolumetoshow = showDimensionInBestUnit($totalVolume, 0, "volume", $outputlangs); + if (!empty($totalVolume)) { + $totalVolumetoshow = showDimensionInBestUnit($totalVolume, 0, "volume", $outputlangs, -1, 'no', 1); } if ($object->trueWeight) { $totalWeighttoshow = showDimensionInBestUnit($object->trueWeight, $object->weight_units, "weight", $outputlangs); diff --git a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php index 11635c6511bcb..2b10608ab9319 100644 --- a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php @@ -734,11 +734,11 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $object->volume_units = $object->size_units * 3; } - if ($totalWeight != '') { - $totalWeighttoshow = showDimensionInBestUnit($totalWeight, 0, "weight", $outputlangs); + if (!empty($totalWeight)) { + $totalWeighttoshow = showDimensionInBestUnit($totalWeight, 0, "weight", $outputlangs, -1, 'no', 1); } - if ($totalVolume != '') { - $totalVolumetoshow = showDimensionInBestUnit($totalVolume, 0, "volume", $outputlangs); + if (!empty($totalVolume)) { + $totalVolumetoshow = showDimensionInBestUnit($totalVolume, 0, "volume", $outputlangs, -1, 'no', 1); } if (!empty($object->trueWeight)) { $totalWeighttoshow = showDimensionInBestUnit($object->trueWeight, $object->weight_units, "weight", $outputlangs); diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php index b74934d96a4e6..66182bcebba5b 100644 --- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php +++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php @@ -253,7 +253,7 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails $object->fetch_thirdparty(); - $dir = $conf->facture->dir_output; + $dir = empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity]; $objectref = dol_sanitizeFileName($object->ref); if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; @@ -278,8 +278,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index a0b26a8b17c84..dee3bb26f92d8 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1426,8 +1426,6 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull) { // Nothing to do } else { - // FIXME amount of vat not supported with multicurrency - //Local tax 1 before VAT //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') //{ @@ -1454,8 +1452,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1485,8 +1485,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1546,8 +1548,11 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1576,8 +1581,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } //} @@ -2032,7 +2039,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 57596f3edca70..5f4db6651d6de 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1689,8 +1689,6 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT_IFNULL) && $tvaisnull) { // Nothing to do } else { - // FIXME amount of vat not supported with multicurrency - //Local tax 1 before VAT //if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') //{ @@ -1717,8 +1715,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1748,8 +1748,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1833,8 +1835,11 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1866,8 +1871,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -2290,7 +2297,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php index 2076e156bac9f..bff58b2737fcb 100644 --- a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php +++ b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php @@ -268,8 +268,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $mode = 'mem // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index 439826effdf5d..e9e9ccc79a6f0 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -89,7 +89,7 @@ public function __construct($db) $this->const[$r][0] = "MOUVEMENT_ADDON_PDF"; $this->const[$r][1] = "chaine"; $this->const[$r][2] = "stdmovement"; - $this->const[$r][3] = 'Name of PDF model of stock mouvement'; + $this->const[$r][3] = 'Name of PDF model of stock movement'; $this->const[$r][4] = 0; $r++; @@ -113,78 +113,83 @@ public function __construct($db) $this->rights = array(); $this->rights_class = 'stock'; - $this->rights[0][0] = 1001; - $this->rights[0][1] = 'Lire les stocks'; - $this->rights[0][2] = 'r'; - $this->rights[0][3] = 0; - $this->rights[0][4] = 'lire'; - $this->rights[0][5] = ''; - - $this->rights[1][0] = 1002; - $this->rights[1][1] = 'Creer/Modifier les stocks'; - $this->rights[1][2] = 'w'; - $this->rights[1][3] = 0; - $this->rights[1][4] = 'creer'; - $this->rights[1][5] = ''; - - $this->rights[2][0] = 1003; - $this->rights[2][1] = 'Supprimer les stocks'; - $this->rights[2][2] = 'd'; - $this->rights[2][3] = 0; - $this->rights[2][4] = 'supprimer'; - $this->rights[2][5] = ''; - - $this->rights[3][0] = 1004; - $this->rights[3][1] = 'Lire mouvements de stocks'; - $this->rights[3][2] = 'r'; - $this->rights[3][3] = 0; - $this->rights[3][4] = 'mouvement'; - $this->rights[3][5] = 'lire'; - - $this->rights[4][0] = 1005; - $this->rights[4][1] = 'Creer/modifier mouvements de stocks'; - $this->rights[4][2] = 'w'; - $this->rights[4][3] = 0; - $this->rights[4][4] = 'mouvement'; - $this->rights[4][5] = 'creer'; - - $this->rights[5][0] = 1011; - $this->rights[5][1] = 'inventoryReadPermission'; // Permission label - $this->rights[5][3] = 0; // Permission by default for new user (0/1) - $this->rights[5][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[5][5] = 'read'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - - $this->rights[6][0] = 1012; - $this->rights[6][1] = 'inventoryCreatePermission'; // Permission label - $this->rights[6][3] = 0; // Permission by default for new user (0/1) - $this->rights[6][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[6][5] = 'write'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - - $this->rights[6][0] = 1013; - $this->rights[6][1] = 'inventoryDeletePermission'; // Permission label - $this->rights[6][3] = 0; // Permission by default for new user (0/1) - $this->rights[6][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[6][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $r = 0; + + $this->rights[$r][0] = 1001; + $this->rights[$r][1] = 'Read stocks'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'lire'; + $this->rights[$r][5] = ''; + + $r++; + $this->rights[$r][0] = 1002; + $this->rights[$r][1] = 'Create/Modify stocks'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'creer'; + $this->rights[$r][5] = ''; + + $r++; + $this->rights[$r][0] = 1003; + $this->rights[$r][1] = 'Delete stock'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'supprimer'; + $this->rights[$r][5] = ''; + + $r++; + $this->rights[$r][0] = 1004; + $this->rights[$r][1] = 'Read stock movements'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'mouvement'; + $this->rights[$r][5] = 'lire'; + + $r++; + $this->rights[$r][0] = 1005; + $this->rights[$r][1] = 'Create/modify stock movements'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'mouvement'; + $this->rights[$r][5] = 'creer'; + $r++; + $this->rights[$r][0] = 1011; + $this->rights[$r][1] = 'inventoryReadPermission'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][5] = 'read'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $r++; + $this->rights[$r][0] = 1012; + $this->rights[$r][1] = 'inventoryCreatePermission'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][5] = 'write'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + + $r++; + $this->rights[$r][0] = 1013; + $this->rights[$r][1] = 'inventoryDeletePermission'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + + // TODO and if MAIN_FEATURES_LEVEL >= 2 after module is activated ? if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - $this->rights[8][0] = 1014; - $this->rights[8][1] = 'inventoryValidatePermission'; // Permission label - $this->rights[8][3] = 0; // Permission by default for new user (0/1) - $this->rights[8][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[8][5] = 'validate'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - - $this->rights[9][0] = 1015; - $this->rights[9][1] = 'inventoryChangePMPPermission'; // Permission label - $this->rights[9][3] = 0; // Permission by default for new user (0/1) - $this->rights[9][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[9][5] = 'changePMP'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - - $this->rights[10][0] = 1016; - $this->rights[10][1] = 'inventoryDeletePermission'; // Permission label - $this->rights[10][3] = 0; // Permission by default for new user (0/1) - $this->rights[10][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) - $this->rights[10][5] = 'delete'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $r++; + $this->rights[$r][0] = 1014; + $this->rights[$r][1] = 'inventoryValidatePermission'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][5] = 'validate'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + + $r++; + $this->rights[$r][0] = 1015; + $this->rights[$r][1] = 'inventoryChangePMPPermission'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'inventory_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][5] = 'changePMP'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) } // Main menu entries diff --git a/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php b/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php index fe18e6eb6ead8..fe33eec3bbaf8 100644 --- a/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php +++ b/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php @@ -267,8 +267,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php index 2728bf266c2ed..8f799be03aee9 100644 --- a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php +++ b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php @@ -276,8 +276,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php index e8c1357e7a2dd..d3cf5e7440c4a 100644 --- a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php +++ b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php @@ -559,8 +559,8 @@ public function write_file($object, $outputlangs, $srctemplatepath) //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 734ebdc513763..0c6ef9df011bb 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -312,8 +312,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 85576e467ec97..ed21843f07b3b 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -1168,8 +1168,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1186,8 +1188,6 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs if ($tvakey != 0) { // On affiche pas taux 0 //$this->atleastoneratenotnull++; - - $index++; $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); @@ -1200,8 +1200,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1260,8 +1262,11 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1292,8 +1297,10 @@ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1620,7 +1627,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell(100, 3, $outputlangs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 153a0460d8403..06fbdeb6414b9 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -1289,8 +1289,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1307,8 +1309,6 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan if ($tvakey != 0) { // On affiche pas taux 0 //$this->atleastoneratenotnull++; - - $index++; $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); @@ -1322,8 +1322,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1377,8 +1379,11 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1410,8 +1415,10 @@ protected function drawTotalTable(&$pdf, $object, $deja_regle, $posy, $outputlan $totalvat .= vatrate(abs($tvakey), 1).$tvacompl; $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', 1); + $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, price($tvaval, 0, $outputlangs), 0, 'R', 1); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', 1); } } } @@ -1697,7 +1704,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php index 2bc493eb58008..71fcf65b19773 100644 --- a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php +++ b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php @@ -271,8 +271,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php b/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php index 261aeef9ad532..374c44c7a25d5 100644 --- a/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php +++ b/htdocs/core/modules/societe/doc/doc_generic_odt.modules.php @@ -252,8 +252,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails $newfiletmp = dol_sanitizeFileName(dol_string_nospecial($object->name)) . '-' . $newfiletmp; $newfiletmp = preg_replace('/__+/', '_', $newfiletmp); // Replace repeated _ into one _ (to avoid string with substitution syntax) } - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php index 5aae143fc2bd8..a0e89ad1d7684 100644 --- a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php +++ b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php @@ -278,8 +278,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php index 83f0cb802e9b7..0b7dead51b4ae 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php @@ -1305,7 +1305,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlek $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell(100, 3, $outputlangs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php b/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php index 6031907b3057e..27cb836e42000 100644 --- a/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php +++ b/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php @@ -271,8 +271,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php b/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php index 285be7c2799a8..ff7a4f33d3688 100644 --- a/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php +++ b/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php @@ -266,8 +266,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt'; // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php index bbc0fdb583af9..35bf81667f8d6 100644 --- a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php @@ -300,8 +300,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php index 7aa6b4a07e417..9b6646c313b37 100644 --- a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php +++ b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php @@ -266,8 +266,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php index d6e52e2f21ed4..6e671eadae01b 100644 --- a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php +++ b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php @@ -300,8 +300,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php index 74ad5902966f0..666a7945e2d64 100644 --- a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php +++ b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php @@ -282,8 +282,8 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails // Get extension (ods or odt) $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); - if (getDolGlobalInt('MAIN_DOC_USE_TIMING')) { - $format = getDolGlobalInt('MAIN_DOC_USE_TIMING'); + if (getDolGlobalString('MAIN_DOC_USE_TIMING')) { + $format = getDolGlobalString('MAIN_DOC_USE_TIMING'); if ($format == '1') { $format = '%Y%m%d%H%M%S'; } diff --git a/htdocs/core/tpl/contacts.tpl.php b/htdocs/core/tpl/contacts.tpl.php index 7f4b3971205c2..75bc8de4791f0 100644 --- a/htdocs/core/tpl/contacts.tpl.php +++ b/htdocs/core/tpl/contacts.tpl.php @@ -143,7 +143,7 @@
    socid) ? 0 : $object->socid); - $selectedCompany = $formcompany->selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany', '', 0, '', 'minwidth300imp'); // This also print the select component + $selectedCompany = $formcompany->selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany', '', 0, '', 'minwidth300imp maxwidth400 widthcentpercentminusx'); // This also print the select component ?>
    diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index 4ab2d41045d71..5277a7c6e603f 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -204,7 +204,7 @@ } ?> -" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" autofocus="autofocus" /> +" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" autofocus="autofocus" autocapitalize="off" autocomplete="on" spellcheck="false" autocorrect="off" />
    diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 42377634ff942..7a5f36af59299 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -1035,12 +1035,36 @@ function(data) { var supplier_ref = $('option:selected', this).attr('data-supplier-ref'); // When select is done from HTML select if (typeof supplier_ref === 'undefined') { supplier_ref = jQuery('#idprodfournprice').attr('data-supplier-ref');} // When select is done from HTML input with ajax autocomplete - console.log("objectline_create.tpl We find supplier price : up = "+up+", up_locale = "+up_locale+", supplier_ref = "+supplier_ref+" qty = "+qty+", tva_tx = "+tva_tx+", default_vat_code = "+default_vat_code+", stringforvatrateselection="+stringforvatrateselection+", discount = "+discount+" for product supplier ref id = "+jQuery('#idprodfournprice').val()); + var has_multicurrency_up = false; + multicurrency_code != $conf->currency) { + ?> + var object_multicurrency_code = 'multicurrency_code); ?>'; - if (typeof up_locale === 'undefined') { - jQuery("#price_ht").val(up); - } else { - jQuery("#price_ht").val(up_locale); + var multicurrency_code = $('option:selected', this).attr('data-multicurrency-code'); // When select is done from HTML select + if (multicurrency_code == undefined) { multicurrency_code = jQuery('#idprodfournprice').attr('data-multicurrency-code'); } // When select is done from HTML input with ajax autocomplete + + var multicurrency_up = parseFloat($('option:selected', this).attr('data-multicurrency-unitprice')); // When select is done from HTML select + if (isNaN(multicurrency_up)) { multicurrency_up = parseFloat(jQuery('#idprodfournprice').attr('data-multicurrency-unitprice')); } // When select is done from HTML input with ajax autocomplete + + if (multicurrency_code == object_multicurrency_code) { + has_multicurrency_up = true; + jQuery("#multicurrency_price_ht").val(multicurrency_up); + } + + console.log("objectline_create.tpl Multicurrency values : object_multicurrency_code = "+object_multicurrency_code+", multicurrency_code = "+multicurrency_code+", multicurrency_up = "+multicurrency_up); + + + console.log("objectline_create.tpl We find supplier price : up = "+up+", up_locale = "+up_locale+", has_multicurrency_up = "+has_multicurrency_up+", supplier_ref = "+supplier_ref+" qty = "+qty+", tva_tx = "+tva_tx+", default_vat_code = "+default_vat_code+", stringforvatrateselection="+stringforvatrateselection+", discount = "+discount+" for product supplier ref id = "+jQuery('#idprodfournprice').val()); + + if (has_multicurrency_up === false) { + if (typeof up_locale === 'undefined') { + jQuery("#price_ht").val(up); + } else { + jQuery("#price_ht").val(up_locale); + } } // Set supplier_ref diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index f2e72ef4fd2d4..efd543597eca3 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -150,7 +150,7 @@
    -" id="username" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" /> +" id="username" name="username" class="flat input-icon-user minwidth150" value="" tabindex="1" autocapitalize="off" autocomplete="on" spellcheck="false" autocorrect="off" />
    diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 993cbc8206d59..520c6795d1eb5 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -116,6 +116,14 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf if ($ret < 0) { $this->error = $newobject->error; $this->errors[] = $newobject->error; + } else { + if (empty($object->fk_account) && !empty($object->thirdparty->fk_account) && !getDolGlobalInt('BANK_ASK_PAYMENT_BANK_DURING_ORDER')) { + $res = $newobject->setBankAccount($object->thirdparty->fk_account, true, $user); + if ($ret < 0) { + $this->error = $newobject->error; + $this->errors[] = $newobject->error; + } + } } $object->clearObjectLinkedCache(); @@ -272,8 +280,8 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf $totalonlinkedelements += $element->total_ht; } } - dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG); - if ($totalonlinkedelements == $object->total_ht) { + dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".((string) $totalonlinkedelements == (string) $object->total_ht), LOG_DEBUG); + if ( (string) $totalonlinkedelements == (string) $object->total_ht) { foreach ($object->linkedObjects['reception'] as $element) { $ret = $element->setBilled(); if ($ret < 0) { @@ -451,45 +459,42 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf if ($action == 'TICKET_CREATE') { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - // Auto link contract - if (!empty($conf->contract->enabled) && isModEnabled('ticket') && isModEnabled('ficheinter') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_LINK_CONTRACT) && !empty($conf->global->TICKET_PRODUCT_CATEGORY) && !empty($object->fk_soc)) { + // Auto link ticket to contract + if (isModEnabled('contract') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT') && getDolGlobalString('TICKET_PRODUCT_CATEGORY') && !empty($object->fk_soc)) { $societe = new Societe($this->db); - $company_ids = (empty($conf->global->WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS)) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]); + $company_ids = (!getDolGlobalString('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS')) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]); $contrat = new Contrat($this->db); $number_contracts_found = 0; foreach ($company_ids as $company_id) { $contrat->socid = $company_id; - $list = $contrat->getListOfContracts($option = 'all', $status = [Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED], $product_categories = [$conf->global->TICKET_PRODUCT_CATEGORY], $line_status = [ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN]); - if (is_array($list) && !empty($list)) { - $number_contracts_found = count($list); - if ($number_contracts_found == 1) { - foreach ($list as $linked_contract) { - $object->setContract($linked_contract->id); - } - break; - } elseif ($number_contracts_found > 1) { - foreach ($list as $linked_contract) { - $object->setContract($linked_contract->id); - // don't set '$contractid' so it is not used when creating an intervention. - } - if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings'); - break; - } + $list = $contrat->getListOfContracts('all', array(Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED), array(getDolGlobalString('TICKET_PRODUCT_CATEGORY')), array(ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN)); + if (!is_array($list) || empty($list)) { + continue; + } + $number_contracts_found = count($list); + + foreach ($list as $linked_contract) { + $object->setContract($linked_contract->id); + // don't set '$contractid' so it is not used when creating an intervention. + } + + if ($number_contracts_found > 1 && !defined('NOLOGIN')) { + setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings'); } } - if ($number_contracts_found == 0) { - if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs'); + if ($number_contracts_found == 0 && !defined('NOLOGIN')) { + setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs'); } } // Automatically create intervention - if (isModEnabled('ficheinter') && isModEnabled('ticket') && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_CREATE_INTERVENTION)) { + if (isModEnabled('ficheinter') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_CREATE_INTERVENTION')) { $fichinter = new Fichinter($this->db); $fichinter->socid = (int) $object->fk_soc; - $fichinter->fk_project = $projectid; + $fichinter->fk_project = (int) $object->fk_project; $fichinter->fk_contrat = (int) $object->fk_contract; $fichinter->author = $user->id; - $fichinter->model_pdf = (!empty($conf->global->FICHEINTER_ADDON_PDF)) ? $conf->global->FICHEINTER_ADDON_PDF : 'soleil'; + $fichinter->model_pdf = getDolGlobalString('FICHEINTER_ADDON_PDF', 'soleil'); $fichinter->origin = $object->element; $fichinter->origin_id = $object->id; diff --git a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php index f18526a9d199e..58eeaf18dc3a6 100644 --- a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php +++ b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php @@ -246,13 +246,15 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf $linked_contacts = array_merge($linked_contacts, $object->listeContact(-1, 'internal')); if (empty($linked_contacts) && !empty($conf->global->TICKET_NOTIFY_AT_CLOSING) && !empty($object->fk_soc)) { $object->fetch_thirdparty(); - $linked_contacts[] = $object->thirdparty->email; + $linked_contacts[]['email'] = $object->thirdparty->email; } $contactid = GETPOST('contactid', 'int'); $res = 0; if ($contactid > 0) { + // TODO This security test has no sens. We must check that $contactid is inside $linked_contacts[]['id'] when $linked_contacts[]['source'] = 'external' or 'thirdparty' + // Refuse email if not $contact = new Contact($this->db); $res = $contact->fetch($contactid); if (! in_array($contact, $linked_contacts)) { @@ -417,7 +419,8 @@ private function composeAndSendCustomerMessage($sendto, $base_subject, $body, $s $message = dol_nl2br($message); } $message_customer .= '

    '.$langs->trans('Message').' :

    '.$message.'


    '; - $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; + + $url_public_ticket = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/', 2)).'view.php?track_id='.$object->track_id; $message_customer .= '

    '.$langs->trans($see_ticket).' : '.$url_public_ticket.'

    '; $message_customer .= '

    '.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'

    '; diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index 684e47fcdc0da..199fc1ccdd0b0 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -1314,7 +1314,7 @@ public function run_jobs($userlogin) $error++; } else { dol_syslog(get_class($this)."::run_jobs END"); - $this->lastoutput = dol_substr((empty($object->output) ? "" : $object->output."\n").$errmsg, 0, $this::MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD, 'UTF-8', 1); + $this->lastoutput = dol_substr((empty($object->output) ? "" : $object->output."\n"), 0, $this::MAXIMUM_LENGTH_FOR_LASTOUTPUT_FIELD, 'UTF-8', 1); $this->lastresult = var_export($result, true); $retval = $this->lastresult; } diff --git a/htdocs/delivery/class/delivery.class.php b/htdocs/delivery/class/delivery.class.php index f44c531160bf1..91086b15d07c4 100644 --- a/htdocs/delivery/class/delivery.class.php +++ b/htdocs/delivery/class/delivery.class.php @@ -1107,7 +1107,7 @@ public function setDeliveryDate($user, $delivery_date) * @param int $hideref Hide ref * @return int 0 if KO, 1 if OK */ - public function generateDocument($modele, $outputlangs = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0) { global $conf, $langs; diff --git a/htdocs/document.php b/htdocs/document.php index 089bdf4b66b1c..394e470257ad4 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -209,20 +209,17 @@ function llxFooter() $original_file = str_replace('..\\', '/', $original_file); -// Find the subdirectory name as the reference -$refname = basename(dirname($original_file)."/"); - // Security check if (empty($modulepart)) { accessforbidden('Bad value for parameter modulepart'); } // Check security and set return info with full path of file -$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $user, $refname); +$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $user, ''); $accessallowed = $check_access['accessallowed']; $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals']; $fullpath_original_file = $check_access['original_file']; // $fullpath_original_file is now a full path name -//var_dump($fullpath_original_file.' '.$original_file.' '.$refname.' '.$accessallowed);exit; +//var_dump($fullpath_original_file.' '.$original_file.' '.$accessallowed);exit; if (!empty($hashp)) { $accessallowed = 1; // When using hashp, link is public so we force $accessallowed @@ -282,7 +279,7 @@ function llxFooter() // Hooks $hookmanager->initHooks(array('document')); $parameters = array('ecmfile' => $ecmfile, 'modulepart' => $modulepart, 'original_file' => $original_file, - 'entity' => $entity, 'refname' => $refname, 'fullpath_original_file' => $fullpath_original_file, + 'entity' => $entity, 'fullpath_original_file' => $fullpath_original_file, 'filename' => $filename, 'fullpath_original_file_osencoded' => $fullpath_original_file_osencoded); $object = new stdClass(); $reshook = $hookmanager->executeHooks('downloadDocument', $parameters, $object, $action); // Note that $action and $object may have been @@ -293,6 +290,7 @@ function llxFooter() exit; } + // Permissions are ok and file found, so we return it top_httphead($type); header('Content-Description: File Transfer'); @@ -300,6 +298,7 @@ function llxFooter() header('Content-Encoding: '.$encoding); } // Add MIME Content-Disposition from RFC 2183 (inline=automatically displayed, attachment=need user action to open) + if ($attachment) { header('Content-Disposition: attachment; filename="'.$filename.'"'); } else { diff --git a/htdocs/ecm/index_medias.php b/htdocs/ecm/index_medias.php index 1fa0e03a1a7d7..3527523b49c97 100644 --- a/htdocs/ecm/index_medias.php +++ b/htdocs/ecm/index_medias.php @@ -37,6 +37,7 @@ // Get parameters $action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); $socid = GETPOST('socid', 'int'); diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 65df587e29963..2f1cb7931999e 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1268,6 +1268,8 @@ public function doCollectOneCollector($mode = 0) if (strpos($rule['rulevalue'], '!') === 0) { // The value start with !, so we exclude the criteria $not = 'NOT '; + // Then remove the ! from the string for next filters + $rule['rulevalue'] = substr($rule['rulevalue'], 1); } if ($rule['type'] == 'from') { @@ -1399,6 +1401,8 @@ public function doCollectOneCollector($mode = 0) if (strpos($rule['rulevalue'], '!') === 0) { // The value start with !, so we exclude the criteria $not = 'NOT '; + // Then remove the ! from the string for next filters + $rule['rulevalue'] = substr($rule['rulevalue'], 1); } if ($rule['type'] == 'from') { @@ -2353,10 +2357,25 @@ public function doCollectOneCollector($mode = 0) if ($operation['type'] == 'loadthirdparty') { dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found"); - $errorforactions++; - $langs->load("errors"); - $this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty, $namealiastouseforthirdparty); - $this->errors[] = $this->error; + //search into contacts of thirdparty + $resultContact = $contactstatic->fetch('', '', '', $emailtouseforthirdparty); + if ($resultContact > 0) { + $idtouseforthirdparty = $contactstatic->socid; + $result = $thirdpartystatic->fetch($idtouseforthirdparty); + if ($result > 0) { + dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was found thanks to linked contact search"); + } else { + $errorforactions++; + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty, $namealiastouseforthirdparty); + $this->errors[] = $this->error; + } + } else { + $errorforactions++; + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty, $namealiastouseforthirdparty); + $this->errors[] = $this->error; + } } elseif ($operation['type'] == 'loadandcreatethirdparty') { dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found. We try to create it."); @@ -2739,7 +2758,7 @@ public function doCollectOneCollector($mode = 0) $sql .= ' FROM ' . MAIN_DB_PREFIX . $objectdesc['table'] . ' AS t'; $sql .= ' WHERE '; foreach ($objectdesc['fields'] as $field) { - $sql .= "'" .$this->db->escape($subject) . "' LIKE CONCAT('%', t." . $field . ", '%') OR "; + $sql .= "('" .$this->db->escape($subject) . "' LIKE CONCAT('%', t." . $field . ", '%') AND t." . $field . "<>'') OR "; } $sql = substr($sql, 0, -4); diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index c0a7a713075ff..d35b2e1b57766 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -1121,6 +1121,30 @@ public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id) return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables); } + + /** + * Return full name ('name+' '+lastname) + * + * @param Translate $langs Language object for translation of civility (used only if option is 1) + * @param int $option 0=No option + * @param int $nameorder -1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname, 2=Firstname, 3=Firstname if defined else lastname, 4=Lastname, 5=Lastname if defined else firstname + * @param int $maxlen Maximum length + * @return string String with full name + */ + public function getFullName($langs, $option = 0, $nameorder = -1, $maxlen = 0) + { + $lastname = $this->lastname; + $firstname = $this->firstname; + if (empty($lastname)) { + $lastname = (isset($this->lastname) ? $this->lastname : (isset($this->name) ? $this->name : (isset($this->nom) ? $this->nom : (isset($this->societe) ? $this->societe : (isset($this->company) ? $this->company : ''))))); + } + + $ret = ''; + + $ret .= dolGetFirstLastname($firstname, $lastname, $nameorder); + + return dol_trunc($ret, $maxlen); + } } diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 318d66635ec69..dd56966bea6cc 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -1370,9 +1370,42 @@ //var_dump($dbatch); $batchStock = + $dbatch->qty; // To get a numeric $deliverableQty = min($quantityToBeDelivered, $batchStock); + + // Now we will check if we have to reduce the deliverableQty by taking into account the qty already suggested in previous line + if (isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) { + $deliverableQty = min($quantityToBeDelivered, $batchStock - $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)]); + } else { + if (!isset($alreadyQtyBatchSetted[$line->fk_product])) { + $alreadyQtyBatchSetted[$line->fk_product] = array(); + } + + if (!isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch])) { + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch] = array(); + } + + $deliverableQty = min($quantityToBeDelivered, $batchStock); + } + + if ($deliverableQty < 0) $deliverableQty = 0; + + $inputName = 'qtyl'.$indiceAsked.'_'.$subj; + if (GETPOSTISSET($inputName)) { + $deliverableQty = GETPOST($inputName, 'int'); + } + + $tooltipClass = $tooltipTitle = ''; + if (!empty($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) { + $tooltipClass = ' classfortooltip'; + $tooltipTitle = $langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines').' : '.$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)]; + } else { + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = 0 ; + } + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = $deliverableQty + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)]; + print ''; print ''; - print ''; + + print ''; print ''; print ''; @@ -1424,7 +1457,7 @@ $nbofsuggested = 0; foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) { - if ($stock_warehouse->real > 0) { + if ($stock_warehouse->real > 0 || !empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) { $nbofsuggested++; } } @@ -1437,7 +1470,7 @@ } $tmpwarehouseObject->fetch($warehouse_id); - if ($stock_warehouse->real > 0) { + if ($stock_warehouse->real > 0 || !empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) { $stock = + $stock_warehouse->real; // Convert it to number $deliverableQty = min($quantityToBeDelivered, $stock); $deliverableQty = max(0, $deliverableQty); @@ -1457,9 +1490,10 @@ if ($deliverableQty < 0) $deliverableQty = 0; - $tooltip = ''; + $tooltipClass = $tooltipTitle = ''; if (!empty($alreadyQtySetted[$line->fk_product][intval($warehouse_id)])) { - $tooltip = ' class="classfortooltip" title="'.$langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines').' : '.$alreadyQtySetted[$line->fk_product][intval($warehouse_id)].'" '; + $tooltipClass = ' classfortooltip'; + $tooltipTitle = $langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines').' : '.$alreadyQtySetted[$line->fk_product][intval($warehouse_id)]; } else { $alreadyQtySetted[$line->fk_product][intval($warehouse_id)] = 0; } @@ -1471,7 +1505,7 @@ $deliverableQty = GETPOST($inputName, 'int'); } - print ''; + print ''; print ''; } else { if (getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) { @@ -1536,7 +1570,7 @@ // Define nb of lines suggested for this order line $nbofsuggested = 0; foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) { - if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) { + if (($stock_warehouse->real > 0 || !empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) && (count($stock_warehouse->detail_batch))) { $nbofsuggested+=count($stock_warehouse->detail_batch); } } @@ -1549,7 +1583,7 @@ } $tmpwarehouseObject->fetch($warehouse_id); - if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) { + if (($stock_warehouse->real > 0 || !empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) && (count($stock_warehouse->detail_batch))) { foreach ($stock_warehouse->detail_batch as $dbatch) { $batchStock = + $dbatch->qty; // To get a numeric if (isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) { @@ -1634,6 +1668,9 @@ $disabled = 'disabled="disabled"'; } print ' '; + if (empty($disabled) && !empty($conf->global->STOCK_ALLOW_NEGATIVE_TRANSFER)) { + print ''; + } } else { print $langs->trans("NA"); } diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index eaff6848ad802..bcc6b74598067 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -2295,7 +2295,11 @@ private function manageStockMvtOnEvt($user, $labelmovement = 'ShipmentClassifyCl $error ++; } - return $error; + if (!$error) { + return 1; + } else { + return -1; + } } /** diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 610cf814a3e02..d85f44c29f504 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -542,8 +542,7 @@ // CONTENT $link = $urlwithroot.'/expensereport/card.php?id='.$object->id; $link = ''.$link.''; - $dateRefusEx = explode(" ", $object->date_refuse); - $message = $langs->transnoentities("ExpenseReportWaitingForReApprovalMessage", $dateRefusEx[0], $object->detail_refuse, $expediteur->getFullName($langs), $link); + $message = $langs->transnoentities("ExpenseReportWaitingForReApprovalMessage", dol_print_date($object->date_refuse, 'day'), $object->detail_refuse, $expediteur->getFullName($langs), get_date_range($object->date_debut, $object->date_fin, '', $langs), $link); // Rebuild pdf /* @@ -2217,7 +2216,11 @@ } } - if (!$thumbshown) { + if (!$thumbshown && $fileinfo['extension'] == 'pdf' && !empty($filepdf) && !empty($relativepath) && !empty($fileinfo['filename'])) { + $formFile = new FormFile($db); + $imgpreview = $formFile->showPreview([], $modulepart, $relativepath.'/'.$fileinfo['filename'].'.'.strtolower($fileinfo['extension']), 0); + print $imgpreview; + } elseif (!$thumbshown) { print img_mime($ecmfilesstatic->filename); } } @@ -2867,7 +2870,7 @@ } // Presend form -$modelmail = 'expensereport'; +$modelmail = 'expensereport_send'; $defaulttopic = 'SendExpenseReportRef'; $diroutput = $conf->expensereport->dir_output; $trackid = 'exp'.$object->id; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 8477e4f49ced9..8400f31502649 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -592,7 +592,8 @@ public function setValid($user, $notrigger = 0) $sql .= ", date_valid = '".$this->db->idate($now)."'"; $sql .= ", fk_user_valid = ".($user->id > 0 ? (int) $user->id : "null"); $sql .= " WHERE rowid = ".((int) $this->id); - $sql .= " AND entity = ".((int) $conf->entity); + $sql .= " AND entity = ".((int) $this->entity); + $sql .= " AND fk_statut = 0"; dol_syslog(get_class($this)."::setValid", LOG_DEBUG); @@ -620,7 +621,7 @@ public function setValid($user, $notrigger = 0) // Now we rename also files into index $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'ficheinter/".$this->db->escape($this->newref)."'"; - $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'ficheinter/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'ficheinter/".$this->db->escape($this->ref)."' and entity = ".((int) $this->entity); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->error = $this->db->lasterror(); diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index cba47566c2bac..9e1046d439f94 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -34,7 +34,7 @@ define('DOL_APPLICATION_TITLE', 'Dolibarr'); } if (!defined('DOL_VERSION')) { - define('DOL_VERSION', '18.0.5'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c + define('DOL_VERSION', '18.0.6'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c } if (!defined('EURO')) { diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 2c9436f7bd740..705eb5ba5beee 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -532,7 +532,7 @@ public function fetch_lines($only_product = 0) $sql = "SELECT l.rowid, l.fk_commande, l.ref as ref_supplier, l.fk_product, l.product_type, l.label, l.description, l.qty,"; $sql .= " l.vat_src_code, l.tva_tx, l.remise_percent, l.subprice,"; $sql .= " l.localtax1_tx, l. localtax2_tx, l.localtax1_type, l. localtax2_type, l.total_localtax1, l.total_localtax2,"; - $sql .= " l.total_ht, l.total_tva, l.total_ttc, l.special_code, l.fk_parent_line, l.rang,"; + $sql .= " l.total_ht, l.total_tva, l.total_ttc, l.info_bits, l.special_code, l.fk_parent_line, l.rang,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.description as product_desc, p.tobatch as product_tobatch, p.barcode as product_barcode,"; $sql .= " l.fk_unit,"; $sql .= " l.date_start, l.date_end,"; @@ -633,6 +633,7 @@ public function fetch_lines($only_product = 0) $line->multicurrency_total_tva = $objp->multicurrency_total_tva; $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc; + $line->info_bits = $objp->info_bits; $line->special_code = $objp->special_code; $line->fk_parent_line = $objp->fk_parent_line; @@ -4134,7 +4135,7 @@ public function delete($notrigger = 0) return -1; } - $sql1 = 'UPDATE '.MAIN_DB_PREFIX."commandedet SET fk_commandefourndet = NULL WHERE rowid=".((int) $this->id); + $sql1 = 'UPDATE '.MAIN_DB_PREFIX."commandedet SET fk_commandefourndet = NULL WHERE fk_commandefourndet=".((int) $this->id); $resql = $this->db->query($sql1); if (!$resql) { $this->db->rollback(); diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 978f350b352c1..f02b938b3b3e0 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -4,7 +4,7 @@ * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005 Marc Barilley * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2010-2020 Juanjo Menent + * Copyright (C) 2010-2023 Juanjo Menent * Copyright (C) 2013-2019 Philippe Grand * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2016 Marcos García @@ -1201,10 +1201,14 @@ public function update($user = null, $notrigger = 0) if (empty($this->total_tva)) { $this->total_tva = 0; } - // if (isset($this->total_localtax1)) $this->total_localtax1=trim($this->total_localtax1); - // if (isset($this->total_localtax2)) $this->total_localtax2=trim($this->total_localtax2); + if (empty($this->total_localtax1)) { + $this->total_localtax1 = 0; + } + if (empty($this->total_localtax2)) { + $this->total_localtax2 = 0; + } if (isset($this->total_ttc)) { - $this->total_ttc = trim($this->total_ttc); + $this->total_ttc = (float) $this->total_ttc; } if (isset($this->statut)) { $this->statut = (int) $this->statut; @@ -1262,8 +1266,8 @@ public function update($user = null, $notrigger = 0) $sql .= " paye=".(isset($this->paye) ? ((int) $this->paye) : "0").","; $sql .= " close_code=".(isset($this->close_code) ? "'".$this->db->escape($this->close_code)."'" : "null").","; $sql .= " close_note=".(isset($this->close_note) ? "'".$this->db->escape($this->close_note)."'" : "null").","; - $sql .= " localtax1=".(isset($this->localtax1) ? ((float) $this->localtax1) : "null").","; - $sql .= " localtax2=".(isset($this->localtax2) ? ((float) $this->localtax2) : "null").","; + $sql .= " localtax1=".(isset($this->total_localtax1) ? ((float) $this->total_localtax1) : "null").","; + $sql .= " localtax2=".(isset($this->total_localtax2) ? ((float) $this->total_localtax2) : "null").","; $sql .= " total_ht=".(isset($this->total_ht) ? ((float) $this->total_ht) : "null").","; $sql .= " total_tva=".(isset($this->total_tva) ? ((float) $this->total_tva) : "null").","; $sql .= " total_ttc=".(isset($this->total_ttc) ? ((float) $this->total_ttc) : "null").","; @@ -1901,7 +1905,7 @@ public function validate($user, $force_number = '', $idwarehouse = 0, $notrigger // Set new ref and define current statut if (!$error) { - $this->ref = $num; + $this->ref = $this->newref; $this->statut = self::STATUS_VALIDATED; //$this->date_validation=$now; this is stored into log table } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index c9e5e8f4fee32..2c1e723df006f 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1350,8 +1350,6 @@ $tva_tx = get_default_tva($soc, $mysoc, $lines[$i]->fk_product, $product_fourn_price_id); } - $object->special_code = $lines[$i]->special_code; - $result = $object->addline( $desc, $lines[$i]->subprice, @@ -1374,7 +1372,9 @@ $lines[$i]->fk_unit, 0, $element, - !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid + !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid, + -1, + $lines[$i]->special_code ); if ($result < 0) { diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 307d82ebdd3a7..dfff2f7051cb4 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -258,7 +258,7 @@ } // We ask to move a qty - if (GETPOST($qty) != 0) { + if ((float) GETPOST($qty) != 0) { if (!(GETPOST($ent, 'int') > 0)) { dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.'); $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline); diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 0258622e476f3..454af46592040 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -869,10 +869,10 @@ $sql .= " AND cf.date_livraison <= '".$db->idate($search_date_delivery_end)."'"; } if ($search_date_valid_start) { - $sql .= " AND cf.date_commande >= '".$db->idate($search_date_valid_start)."'"; + $sql .= " AND cf.date_valid >= '".$db->idate($search_date_valid_start)."'"; } if ($search_date_valid_end) { - $sql .= " AND cf.date_commande <= '".$db->idate($search_date_valid_end)."'"; + $sql .= " AND cf.date_valid <= '".$db->idate($search_date_valid_end)."'"; } if ($search_date_approve_start) { $sql .= " AND cf.date_livraison >= '".$db->idate($search_date_approve_start)."'"; diff --git a/htdocs/fourn/facture/card-rec.php b/htdocs/fourn/facture/card-rec.php index 24abf113c9b28..ae26587c6bc92 100644 --- a/htdocs/fourn/facture/card-rec.php +++ b/htdocs/fourn/facture/card-rec.php @@ -537,8 +537,8 @@ $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : ''); // Update if prices fields are defined - $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); - $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); + $tva_tx = get_default_tva($object->thirdparty, $mysoc, $prod->id); + $tva_npr = get_default_npr($object->thirdparty, $mysoc, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; } @@ -546,7 +546,7 @@ // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp']. $pqp = (GETPOST('pbq', 'int') ? GETPOST('pbq', 'int') : 0); - $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp); + $datapriceofproduct = $prod->getSellPrice($object->thirdparty, $mysoc, $pqp); $pu_ht = $datapriceofproduct['pu_ht']; $pu_ttc = $datapriceofproduct['pu_ttc']; @@ -661,8 +661,8 @@ $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we must keep this value // Local Taxes - $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr); - $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr); + $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr); + $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr); $info_bits = 0; if ($tva_npr) { $info_bits |= 0x01; @@ -780,7 +780,7 @@ $special_code = 3; } - $remise_percent = price2num(GETPOST('remise_percent'), '', 2); + $remise_percent = price2num(GETPOST('remise_percent'), '', 2) ?: 0; // Check minimum price $productid = GETPOST('productid', 'int'); @@ -1082,7 +1082,7 @@ $disableedit = 1; $disablemove = 1; $disableremove = 1; - $object->printObjectLines('', $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice + $object->printObjectLines('', $object->thirdparty, $mysoc, $lineid, 0); // No date selector for template invoice } print "\n"; @@ -1571,7 +1571,7 @@ $canchangeproduct = 0; $object->statut = $object->suspended; - $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice + $object->printObjectLines($action, $object->thirdparty, $mysoc, $lineid, 0); // No date selector for template invoice } // Form to add new line diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index a941819759254..23b9be4300cd0 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -4,7 +4,7 @@ * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005 Marc Barilley * Copyright (C) 2005-2013 Regis Houssin - * Copyright (C) 2010-2019 Juanjo Menent + * Copyright (C) 2010-2023 Juanjo Menent * Copyright (C) 2013-2022 Philippe Grand * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2016 Marcos García @@ -389,9 +389,8 @@ } if (!$error) { - $old_date_echeance = $object->date_echeance; $new_date_echeance = $object->calculate_date_lim_reglement(); - if ($new_date_echeance > $old_date_echeance) { + if ($new_date_echeance) { $object->date_echeance = $new_date_echeance; } if ($object->date_echeance < $object->date) { @@ -455,7 +454,7 @@ $object->date = $newdate; $date_echence_calc = $object->calculate_date_lim_reglement(); - if (!empty($object->date_echeance) && $object->date_echeance < $date_echence_calc) { + if (!empty($object->date_echeance)) { $object->date_echeance = $date_echence_calc; } if ($object->date_echeance && $object->date_echeance < $object->date) { @@ -1648,14 +1647,6 @@ $ref_supplier = $productsupplier->ref_supplier; - $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha')); - $tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha')); - if (empty($tva_tx)) { - $tva_npr = 0; - } - $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr); - $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr); - if (empty($pu)) { $pu = 0; // If pu is '' or null, we force to have a numeric value } diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 2f8fb164205cb..f071292aa33a7 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -628,17 +628,17 @@ $listofcategoryid = ''; foreach ($searchCategoryProductList as $searchCategoryProduct) { if (intval($searchCategoryProduct) == -2) { - $searchCategoryProductSqlList[] = "NOT EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND p.rowid = ck.fk_product)"; + $searchCategoryProductSqlList[] = "NOT EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND fd.fk_product = ck.fk_product)"; } elseif (intval($searchCategoryProduct) > 0) { if ($searchCategoryProductOperator == 0) { - $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND p.rowid = ck.fk_product AND ck.fk_categorie = ".((int) $searchCategoryProduct).")"; + $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND fd.fk_product = ck.fk_product AND ck.fk_categorie = ".((int) $searchCategoryProduct).")"; } else { $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryProduct); } } } if ($listofcategoryid) { - $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND p.rowid = ck.fk_product AND ck.fk_categorie IN (".$db->sanitize($listofcategoryid)."))"; + $searchCategoryProductSqlList[] = " EXISTS (SELECT ck.fk_product FROM ".MAIN_DB_PREFIX."categorie_product as ck, ".MAIN_DB_PREFIX."facture_fourn_det as fd WHERE fd.fk_facture_fourn = f.rowid AND fd.fk_product = ck.fk_product AND ck.fk_categorie IN (".$db->sanitize($listofcategoryid)."))"; } if ($searchCategoryProductOperator == 1) { if (!empty($searchCategoryProductSqlList)) { diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php index b64072f36da71..0e50d980c183c 100644 --- a/htdocs/fourn/facture/paiement.php +++ b/htdocs/fourn/facture/paiement.php @@ -822,10 +822,10 @@ function callForResult(imgId) print '
    '; if (!empty($totalpayment)) { - $text = $langs->trans('ConfirmSupplierPayment', price($totalpayment), $langs->trans("Currency".$conf->currency)); + $text = $langs->trans('ConfirmSupplierPayment', price($totalpayment), $langs->transnoentitiesnoconv("Currency".$conf->currency)); } if (!empty($multicurrency_totalpayment)) { - $text .= '
    '.$langs->trans('ConfirmSupplierPayment', price($multicurrency_totalpayment), $langs->trans("paymentInInvoiceCurrency")); + $text .= '
    '.$langs->trans('ConfirmSupplierPayment', price($multicurrency_totalpayment), $langs->transnoentitiesnoconv("paymentInInvoiceCurrency")); } if (GETPOST('closepaidinvoices')) { $text .= '
    '.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed"); diff --git a/htdocs/fourn/paiement/list.php b/htdocs/fourn/paiement/list.php index 05528f2d8a13a..308ac2125e65c 100644 --- a/htdocs/fourn/paiement/list.php +++ b/htdocs/fourn/paiement/list.php @@ -68,6 +68,7 @@ $search_cheque_num = GETPOST('search_cheque_num', 'alpha'); $search_bank_account = GETPOST('search_bank_account', 'int'); $search_amount = GETPOST('search_amount', 'alpha'); // alpha because we must be able to search on '< x' +$search_sale = GETPOST('search_sale', 'int'); $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -113,6 +114,10 @@ $hookmanager->initHooks(array('paymentsupplierlist')); $object = new PaiementFourn($db); +if (!$user->hasRight('societe', 'client', 'voir')) { + $search_sale = $user->id; +} + // Security check if ($user->socid) { $socid = $user->socid; @@ -176,33 +181,32 @@ $companystatic = new Societe($db); $paymentfournstatic = new PaiementFourn($db); -$sql = 'SELECT p.rowid, p.ref, p.datep, p.amount as pamount, p.num_paiement'; -$sql .= ', s.rowid as socid, s.nom as name, s.email'; +$sql = 'SELECT p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount'; $sql .= ', c.code as paiement_type, c.libelle as paiement_libelle'; $sql .= ', ba.rowid as bid, ba.ref as bref, ba.label as blabel, ba.number, ba.account_number as account_number, ba.iban_prefix, ba.bic, ba.currency_code, ba.fk_accountancy_journal as accountancy_journal'; -if (!$user->hasRight("societe", "client", "voir")) { - $sql .= ', sc.fk_soc, sc.fk_user'; -} -$sql .= ', SUM(pf.amount)'; +$sql .= ', s.rowid as socid, s.nom as name, s.email'; +// We need an aggregate because we added a left join to get the thirdparty. In real world, it should be the same thirdparty if payment is same (but not in database structure) +// so SUM(pf.amount) should be equal to p.amount but if we filter on $socid, it may differ +$sql .= ", SUM(pf.amount) as totalamount, COUNT(f.rowid) as nbinvoices"; + +$sqlfields = $sql; // $sql fields to remove for count total $sql .= ' FROM '.MAIN_DB_PREFIX.'paiementfourn AS p'; -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn_facturefourn AS pf ON p.rowid=pf.fk_paiementfourn'; -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facture_fourn AS f ON f.rowid=pf.fk_facturefourn'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement AS c ON p.fk_paiement = c.id'; -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON s.rowid = f.fk_soc'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON b.fk_account = ba.rowid'; -if (!$user->hasRight("societe", "client", "voir")) { - $sql .= ', '.MAIN_DB_PREFIX.'societe_commerciaux as sc'; -} -$sql .= ' WHERE f.entity = '.$conf->entity; -if (!$user->hasRight("societe", "client", "voir")) { - $sql .= ' AND s.rowid = sc.fk_soc AND sc.fk_user = '.((int) $user->id); -} +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn_facturefourn AS pf ON p.rowid=pf.fk_paiementfourn'; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'facture_fourn AS f ON f.rowid=pf.fk_facturefourn'; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON s.rowid = f.fk_soc'; + +$sql .= ' WHERE f.entity IN ('.getEntity('supplier_invoice').')'; // TODO We should use p.entity that does not exists yet in this table if ($socid > 0) { - $sql .= ' AND f.fk_soc = '.((int) $socid); + $sql .= " AND EXISTS (SELECT f.fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn as f, ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf"; + $sql .= " WHERE p.rowid = pf.fk_paiementfourn AND pf.fk_facturefourn = f.rowid AND f.fk_soc = ".((int) $socid).")"; } + +// Search criteria if ($search_ref) { $sql .= natural_search('p.ref', $search_ref); } @@ -217,13 +221,16 @@ $sql .= natural_search('s.nom', $search_company); } if ($search_payment_type != '') { - $sql .= " AND c.code='".$db->escape($search_payment_type)."'"; + $sql .= " AND c.code = '".$db->escape($search_payment_type)."'"; } if ($search_cheque_num != '') { $sql .= natural_search('p.num_paiement', $search_cheque_num); } if ($search_amount) { - $sql .= natural_search('p.amount', $search_amount, 1); + $sql .= " AND (".natural_search('p.amount', $search_amount, 1, 1); + $sql .= " OR "; + $sql .= natural_search('pf.amount', $search_amount, 1, 1); + $sql .= ")"; } if ($search_bank_account > 0) { $sql .= ' AND b.fk_account = '.((int) $search_bank_account); @@ -231,29 +238,48 @@ if ($search_all) { $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } +// Search on sale representative +if ($search_sale && $search_sale != '-1') { + if ($search_sale == -2) { + $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = f.fk_soc)"; + } elseif ($search_sale > 0) { + $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = f.fk_soc AND sc.fk_user = ".((int) $search_sale).")"; + } +} // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; -$sql .= ' GROUP BY p.rowid, p.ref, p.datep, p.amount, p.num_paiement, s.rowid, s.nom, s.email, c.code, c.libelle,'; +$sql .= ' GROUP BY p.rowid, p.ref, p.datep, p.fk_bank, p.statut, p.num_paiement, p.amount, s.rowid, s.nom, s.email, c.code, c.libelle,'; $sql .= ' ba.rowid, ba.ref, ba.label, ba.number, ba.account_number, ba.iban_prefix, ba.bic, ba.currency_code, ba.fk_accountancy_journal'; -if (!$user->hasRight("societe", "client", "voir")) { - $sql .= ', sc.fk_soc, sc.fk_user'; -} - -$sql .= $db->order($sortfield, $sortorder); +// Count total nb of records $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { - $result = $db->query($sql); - $nbtotalofrecords = $db->num_rows($result); - if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(DISTINCT p.rowid) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } -$sql .= $db->plimit($limit + 1, $offset); +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} +//print $sql; $resql = $db->query($sql); if (!$resql) { @@ -476,6 +502,7 @@ $paymentfournstatic->id = $objp->rowid; $paymentfournstatic->ref = $objp->ref; $paymentfournstatic->datepaye = $db->jdate($objp->datep); + $paymentfournstatic->amount = $objp->amount; $companystatic->id = $objp->socid; $companystatic->name = $objp->name; @@ -493,7 +520,9 @@ // Ref if (!empty($arrayfields['p.ref']['checked'])) { - print ''.$paymentfournstatic->getNomUrl(1).''; + print ''; + print $paymentfournstatic->getNomUrl(1); + print ''; if (!$i) { $totalarray['nbfield']++; } @@ -566,12 +595,17 @@ // Amount if (!empty($arrayfields['p.amount']['checked'])) { - print ''.price($objp->pamount).''; + print ''; + if ($objp->nbinvoices > 1 || ($objp->totalamount && $objp->amount != $objp->totalamount)) { + print $form->textwithpicto('', $langs->trans("PaymentMadeForSeveralInvoices")); + } + print ''.price($objp->amount).''; + print ''; if (!$i) { $totalarray['nbfield']++; } $totalarray['pos'][$checkedCount] = 'amount'; - $totalarray['val']['amount'] += $objp->pamount; + $totalarray['val']['amount'] += $objp->amount; } // Buttons diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index cb0308124d36d..101bef49b3d35 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1067,6 +1067,13 @@ public function update($user = null, $notrigger = 0) $error++; $this->errors[] = "Error ".$this->db->lasterror(); } + if (!$error) { + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; + } + } + if (!$error) { if (!$notrigger) { // Call trigger diff --git a/htdocs/holiday/month_report.php b/htdocs/holiday/month_report.php index e73e83861c89f..ab1cd83ee0b30 100644 --- a/htdocs/holiday/month_report.php +++ b/htdocs/holiday/month_report.php @@ -39,7 +39,7 @@ $massaction = GETPOST('massaction', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ'); $optioncss = GETPOST('optioncss', 'aZ'); -$socid = 0; + $id = GETPOST('id', 'int'); $search_ref = GETPOST('search_ref', 'alphanohtml'); @@ -73,7 +73,11 @@ //$socid = $user->socid; accessforbidden(); } -$result = restrictedArea($user, 'holiday', $id, ''); +$result = restrictedArea($user, 'holiday', $id); + +if (!$user->hasRight('holiday', 'readall')) { + accessforbidden(); +} /* diff --git a/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php b/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php index a5a1fd98750e0..0f5b2c4e9f733 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php @@ -268,8 +268,8 @@ private function loadLastResort($className, $loader = null) return $this->loadThisLoader($className, $loader); } foreach ($loaders as $loader) - if (false !== $file = $this->loadThisLoader($className, $loader)) - return $file; + if (false !== $file = $this->loadThisLoader($className, $loader)) + return $file; return false; } @@ -285,23 +285,52 @@ private function loadLastResort($className, $loader = null) */ private function loadThisLoader($className, $loader) { + if (is_array($loader) + && is_callable($loader)) { + $b = new $loader[0]; + //avoid PHP Fatal error: Uncaught Error: Access to undeclared static property: Composer\\Autoload\\ClassLoader::$loader + //in case of multiple autoloader systems + if (property_exists($b, $loader[1])) { + if (false !== $file = $b::$loader[1]($className) + && $this->exists($className, $b::$loader[1])) { + return $file; + } + } + } elseif (is_callable($loader) + && false !== $file = $loader($className) + && $this->exists($className, $loader)) { + return $file; + } + return false; + + /* other code tested to reduce autoload conflict + $s = ''; if (is_array($loader) && is_callable($loader)) { + // @CHANGE DOL avoid autoload conflict + if (!preg_match('/LuraCast/', get_class($loader[0]))) { + return false; + } $b = new $loader[0]; - //avoid PHP Fatal error: Uncaught Error: Access to undeclared static property: Composer\\Autoload\\ClassLoader::$loader + // @CHANGE DOL avoid PHP Fatal error: Uncaught Error: Access to undeclared static property: Composer\\Autoload\\ClassLoader::$loader //in case of multiple autoloader systems if (property_exists($b, $loader[1])) { if (false !== $file = $b::$loader[1]($className) - && $this->exists($className, $b::$loader[1])) { - return $file; - } + && $this->exists($className, $b::$loader[1])) { + return $file; + } + } + } elseif (is_callable($loader, false, $s)) { + // @CHANGE DOL avoid PHP infinite loop (detected when xdebug is on) + if ($s == 'Luracast\Restler\AutoLoader::__invoke') { + return false; + } + if (false !== ($file = $loader($className)) && $this->exists($className, $loader)) { + return $file; } - } elseif (is_callable($loader) - && false !== $file = $loader($className) - && $this->exists($className, $loader)) { - return $file; } return false; + */ } /** @@ -417,7 +446,7 @@ public function __invoke($className) if (false !== $includeReference = $this->discover($className)) return $includeReference; - static::thereCanBeOnlyOne(); + //static::thereCanBeOnlyOne(); if (false !== $includeReference = $this->loadAliases($className)) return $includeReference; @@ -426,7 +455,7 @@ public function __invoke($className) return $includeReference; if (false !== $includeReference = $this->loadLastResort($className)) - return $includeReference; + return $includeReference; static::seen($className, true); return null; diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index ac0ffcb881259..fcd3132c2f246 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -316,9 +316,9 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 2 -- SWITZERLAND (id country=6) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 61, 6, '0','0','VAT rate 0', 1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 62, 6, '3.7','0','VAT rate - reduced',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 63, 6, '2.5','0','VAT rate - super-reduced',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 64, 6, '7.7','0','VAT rate - standard',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 62, 6, '3.8','0','VAT rate - reduced',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 63, 6, '2.6','0','VAT rate - super-reduced',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 64, 6, '8.1','0','VAT rate - standard',1); -- SRI LANKA (id country=207) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (2071, 207, '0','0','VAT 0', 1); diff --git a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql index 9510ca261a5ab..8cf14549e5f06 100644 --- a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -569,3 +569,8 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('HRM_EVALUATION_DELETE', 'HR Evaluation deleted', 'Executed when an evaluation is dleted', 'hrm', 4005); UPDATE llx_menu SET url = '/fourn/paiement/list.php?mainmenu=billing&leftmenu=suppliers_bills_payment' WHERE leftmenu = 'suppliers_bills_payment'; + +UPDATE llx_paiement SET ref = rowid WHERE ref IS NULL OR ref = ''; + +-- rename const WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE to WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE +UPDATE llx_const SET name = 'WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE' WHERE name = 'WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE'; diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index d7fba7d6918fd..ef8989f34da0c 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -310,7 +310,7 @@ drop table tmp_societe_double; -- Sequence to removed duplicated values of llx_accounting_account. Run several times if you still have duplicate. drop table tmp_accounting_account_double; --select account_number, fk_pcg_version, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_accounting_account where label is not null group by account_number, fk_pcg_version having count(rowid) >= 2; -create table tmp_accounting_account_double as (select account_number, fk_pcg_version, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_accounting_account where label is not null group by account_number, fk_pcg_version having count(rowid) >= 2); +create table tmp_accounting_account_double as (select account_number, fk_pcg_version, entity, max(rowid) as max_rowid, count(rowid) as count_rowid from llx_accounting_account where label is not null group by account_number, fk_pcg_version, entity having count(rowid) >= 2); --select * from tmp_accounting_account_double; delete from llx_accounting_account where (rowid) in (select max_rowid from tmp_accounting_account_double); --update to avoid duplicate, delete to delete drop table tmp_accounting_account_double; diff --git a/htdocs/langs/ar_SA/workflow.lang b/htdocs/langs/ar_SA/workflow.lang index a0a44bde14b14..405b59d5748ea 100644 --- a/htdocs/langs/ar_SA/workflow.lang +++ b/htdocs/langs/ar_SA/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=تصنيف أمر ش descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=تصنيف أمر شراء المصدر المرتبط على أنه تم استلامه عند التحقق من صحة الاستلام (وإذا كانت الكمية المستلمة من قبل جميع الاستقبالات هي نفسها الموجودة في أمر الشراء للتحديث) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=تصنيف أمر شراء المصدر المرتبط كما تم استلامه عند إغلاق الاستلام (وإذا كانت الكمية المستلمة من قبل جميع الاستدعاءات هي نفسها الموجودة في أمر الشراء للتحديث) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=عند إنشاء تذكرة ، قم بربط العقود المتاحة لمطابقة الطرف الثالث descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=عند ربط العقود ، ابحث بين تلك الخاصة بالشركات الأم diff --git a/htdocs/langs/ca_ES/companies.lang b/htdocs/langs/ca_ES/companies.lang index 0522b5c630006..9d711237e176c 100644 --- a/htdocs/langs/ca_ES/companies.lang +++ b/htdocs/langs/ca_ES/companies.lang @@ -340,7 +340,7 @@ Contact=Contacte/Adreça Contacts=Contactes ContactId=Id contacte ContactsAddresses=Contactes/Adreces -FromContactName=Nom: +FromContactName=Nom NoContactDefinedForThirdParty=Cap contacte definit per a aquest tercer NoContactDefined=Cap contacte definit DefaultContact=Contacte per defecte diff --git a/htdocs/langs/ca_ES/workflow.lang b/htdocs/langs/ca_ES/workflow.lang index fb65a49a9f341..d950e0930bb30 100644 --- a/htdocs/langs/ca_ES/workflow.lang +++ b/htdocs/langs/ca_ES/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classifica la comanda descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classifica com a rebuda l'ordre de compra d'origen enllaçada quan es valida una recepció (i si la quantitat rebuda per totes les recepcions és la mateixa que a l'ordre de compra per a actualitzar) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classifica com a rebuda l'ordre de compra d'origen enllaçada quan es tanca una recepció (i si la quantitat rebuda per totes les recepcions és la mateixa que a l'ordre de compra per a actualitzar) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Quan creeu un bitllet, enllaceu els contractes disponibles del tercer coincident descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=En enllaçar contractes, cerqueu entre els de les empreses matrius diff --git a/htdocs/langs/cs_CZ/workflow.lang b/htdocs/langs/cs_CZ/workflow.lang index df5523148a60f..4d89d43135c27 100644 --- a/htdocs/langs/cs_CZ/workflow.lang +++ b/htdocs/langs/cs_CZ/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Zařadit propojenou o descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/cy_GB/workflow.lang b/htdocs/langs/cy_GB/workflow.lang index 6b7442731b135..a39746b48a7f5 100644 --- a/htdocs/langs/cy_GB/workflow.lang +++ b/htdocs/langs/cy_GB/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Dosbarthu archeb bryn descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Dosbarthwch archeb brynu ffynhonnell gysylltiedig fel y'i derbyniwyd pan ddilysir derbyniad (ac os yw'r swm a dderbynnir gan bob derbyniad yr un peth ag yn yr archeb brynu i ddiweddaru) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Dosbarthwch archeb brynu ffynhonnell gysylltiedig fel un a dderbyniwyd pan fydd derbyniad ar gau (ac os yw'r swm a dderbynnir gan bob derbynfa yr un peth ag yn yr archeb brynu i ddiweddaru) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/da_DK/companies.lang b/htdocs/langs/da_DK/companies.lang index 2cbc39266733c..be447550d4ff7 100644 --- a/htdocs/langs/da_DK/companies.lang +++ b/htdocs/langs/da_DK/companies.lang @@ -340,7 +340,7 @@ Contact=Kontakt/Adresse Contacts=Kontakter/adresser ContactId=Kontakt id ContactsAddresses=Kontakter/adresser -FromContactName=Navn: +FromContactName=Navn NoContactDefinedForThirdParty=Ingen kontakt defineret for denne tredjepart NoContactDefined=Ingen kontakt defineret DefaultContact=Standard kontakt/adresse diff --git a/htdocs/langs/da_DK/workflow.lang b/htdocs/langs/da_DK/workflow.lang index ec88edf8ff82f..72ef6c416a9c7 100644 --- a/htdocs/langs/da_DK/workflow.lang +++ b/htdocs/langs/da_DK/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Klassificer købt kø descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Klassificer linket kildeindkøbsordre som modtaget, når en modtagelse er valideret (og hvis mængden modtaget af alle modtagelser er den samme som i indkøbsordren, der skal opdateres) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Klassificer tilknyttet kildeindkøbsordre som modtaget, når en modtagelse lukkes (og hvis mængden modtaget af alle modtagelser er den samme som i indkøbsordren for at opdatere) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Klassificer modtagelser til "faktureret", når en tilknyttet købsfaktura er valideret (og hvis fakturabeløbet er det samme som det samlede beløb for de tilknyttede modtagelser) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Klassificer modtagelser til "faktureret", når en tilknyttet købsfaktura er valideret (og hvis fakturabeløbet er det samme som det samlede beløb for de tilknyttede modtagelser) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Når du opretter en billet, skal du linke tilgængelige kontrakter fra matchende tredjepart descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Når du sammenkæder kontrakter, søg blandt moderselskabers diff --git a/htdocs/langs/de_DE/companies.lang b/htdocs/langs/de_DE/companies.lang index 9a6fc76d005d8..ce8da429ffe1d 100644 --- a/htdocs/langs/de_DE/companies.lang +++ b/htdocs/langs/de_DE/companies.lang @@ -340,7 +340,7 @@ Contact=Kontakt/Adresse Contacts=Kontakte/Adressen ContactId=Kontakt-ID ContactsAddresses=Kontakte/Adressen -FromContactName=Name: +FromContactName=Name NoContactDefinedForThirdParty=Für diesen Geschäftspartner ist kein Kontakt eingetragen NoContactDefined=kein Kontakt für diesen Partner DefaultContact=Standardkontakt diff --git a/htdocs/langs/de_DE/workflow.lang b/htdocs/langs/de_DE/workflow.lang index 6cfee1bd30c3e..c703aacccbac9 100644 --- a/htdocs/langs/de_DE/workflow.lang +++ b/htdocs/langs/de_DE/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Kennzeichne die verkn descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Verknüpfte Lieferantenbestellung als eingegangen klassifizieren, wenn ein Wareneingang freigegeben wird (und wenn die von allen Wareneingängen eingegangene Menge mit der zu aktualisierenden Lieferantenbestellung übereinstimmt) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Verknüpfte Lieferantenbestellung als eingegangen klassifizieren, wenn ein Wareneingang geschlossen wird (und wenn die von allen Wareneingängen eingegangene Menge mit der zu aktualisierenden Bestellung übereinstimmt) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Wareneingänge als „abgerechnet“ klassifizieren, wenn eine verknüpfte Einkaufsrechnung freigegeben wird (und wenn der Rechnungsbetrag mit dem Gesamtbetrag der verknüpften Wareneingänge übereinstimmt) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Wareneingänge als „abgerechnet“ klassifizieren, wenn eine verknüpfte Einkaufsrechnung freigegeben wird (und wenn der Rechnungsbetrag mit dem Gesamtbetrag der verknüpften Wareneingänge übereinstimmt) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Verknüpfen Sie beim Erstellen eines Tickets verfügbare Verträge passender Geschäftspartner descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Beim Verknüpfen von Verträgen unter denen der Mutterunternehmen suchen diff --git a/htdocs/langs/el_GR/companies.lang b/htdocs/langs/el_GR/companies.lang index d5b5d16d6d02b..17b5ed5c57b7a 100644 --- a/htdocs/langs/el_GR/companies.lang +++ b/htdocs/langs/el_GR/companies.lang @@ -340,7 +340,7 @@ Contact=Επαφή/Διεύθυνση Contacts=Επαφές/Διευθύνσεις ContactId=Αναγνωριστικό επαφής ContactsAddresses=Επαφές/Διευθύνσεις -FromContactName=Όνομα: +FromContactName=Όνομα NoContactDefinedForThirdParty=Δεν έχει οριστεί επαφή για αυτό το τρίτο μέρος NoContactDefined=Δεν έχει οριστεί επαφή DefaultContact=Προεπιλεγμένη επαφή/διεύθυνση diff --git a/htdocs/langs/el_GR/workflow.lang b/htdocs/langs/el_GR/workflow.lang index 43b9141582571..2612e4f7c8353 100644 --- a/htdocs/langs/el_GR/workflow.lang +++ b/htdocs/langs/el_GR/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Ταξινόμηση descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Ταξινόμηση της παραγγελίας αγοράς συνδεδεμένης πηγής ως ληφθείσας όταν επικυρωθεί μια παραλαβή (και εάν η ποσότητα που παρελήφθη από όλες τις παραλαβές είναι η ίδια με την παραγγελία αγοράς προς ενημέρωση) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Ταξινόμηση παραγγελίας αγοράς από συνδεδεμένη πηγή ως ληφθείσας όταν μια παραλαβή είναι κλειστή (και εάν η ποσότητα που παρελήφθη από όλες τις παραλαβές είναι η ίδια με την παραγγελία αγοράς προς ενημέρωση) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Ταξινόμηση των παραλαβών σε "τιμολογημένες" όταν επικυρώνεται ένα συνδεδεμένο τιμολόγιο αγοράς (και εάν το ποσό του τιμολογίου είναι το ίδιο με το συνολικό ποσό των συνδεδεμένων παραλαβών) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Ταξινόμηση των παραλαβών σε "τιμολογημένες" όταν επικυρώνεται ένα συνδεδεμένο τιμολόγιο αγοράς (και εάν το ποσό του τιμολογίου είναι το ίδιο με το συνολικό ποσό των συνδεδεμένων παραλαβών) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Κατά τη δημιουργία ενός ticket, συνδέστε τα διαθέσιμα συμβόλαια του αντίστοιχου τρίτου μέρους descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Όταν συνδέετε συμβόλαια, αναζητήστε μεταξύ αυτών των μητρικών εταιρειών diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index d37c8de7daa61..1863ccd312a41 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -878,13 +878,13 @@ Permission401=Read discounts Permission402=Create/modify discounts Permission403=Validate discounts Permission404=Delete discounts -Permission430=Use Debug Bar +Permission431=Use Debug Bar Permission511=Read salaries and payments (yours and subordinates) Permission512=Create/modify salaries and payments Permission514=Delete salaries and payments Permission517=Read salaries and payments everybody Permission519=Export salaries -Permission520=Read Loans +Permission521=Read Loans Permission522=Create/modify loans Permission524=Delete loans Permission525=Access loan calculator @@ -905,12 +905,12 @@ Permission609=Delete stickers Permission611=Read attributes of variants Permission612=Create/Update attributes of variants Permission613=Delete attributes of variants -Permission650=Read Bills of Materials -Permission651=Create/Update Bills of Materials -Permission652=Delete Bills of Materials -Permission660=Read Manufacturing Order (MO) -Permission661=Create/Update Manufacturing Order (MO) -Permission662=Delete Manufacturing Order (MO) +Permission651=Read Bills of Materials +Permission652=Create/Update Bills of Materials +Permission653=Delete Bills of Materials +Permission661=Read Manufacturing Order (MO) +Permission662=Create/Update Manufacturing Order (MO) +Permission663=Delete Manufacturing Order (MO) Permission701=Read donations Permission702=Create/modify donations Permission703=Delete donations @@ -982,7 +982,7 @@ Permission2515=Setup documents directories Permission2610=Generate/modify users API key Permission2801=Use FTP client in read mode (browse and download only) Permission2802=Use FTP client in write mode (delete or upload files) -Permission3200=Read archived events and fingerprints +Permission3201=Read archived events and fingerprints Permission3301=Generate new modules Permission4001=Read skill/job/position Permission4002=Create/modify skill/job/position @@ -1019,9 +1019,9 @@ Permission50152=Edit sales lines Permission50153=Edit ordered sales lines Permission50201=Read transactions Permission50202=Import transactions -Permission50330=Read objects of Zapier -Permission50331=Create/Update objects of Zapier -Permission50332=Delete objects of Zapier +Permission50331=Read objects of Zapier +Permission50332=Create/Update objects of Zapier +Permission50333=Delete objects of Zapier Permission50401=Bind products and invoices with accounting accounts Permission50411=Read operations in ledger Permission50412=Write/Edit operations in ledger @@ -1046,7 +1046,7 @@ Permission63002=Create/modify resources Permission63003=Delete resources Permission63004=Link resources to agenda events Permission64001=Allow direct printing -Permission67000=Allow printing of receipts +Permission67001=Allow printing of receipts Permission68001=Read intracomm report Permission68002=Create/modify intracomm report Permission68004=Delete intracomm report diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 0569c9b4b01f5..f5172f26ac0ed 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -641,3 +641,4 @@ MentionCategoryOfOperations=Category of operations MentionCategoryOfOperations0=Delivery of goods MentionCategoryOfOperations1=Provision of services MentionCategoryOfOperations2=Mixed - Delivery of goods & provision of services +PaymentMadeForSeveralInvoices=Payment made for several invoices \ No newline at end of file diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 840817f24bc38..8f308aff2e343 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -340,7 +340,7 @@ Contact=Contact/Address Contacts=Contacts/Addresses ContactId=Contact id ContactsAddresses=Contacts/Addresses -FromContactName=Name: +FromContactName=Name NoContactDefinedForThirdParty=No contact defined for this third party NoContactDefined=No contact defined DefaultContact=Default contact/address diff --git a/htdocs/langs/en_US/contracts.lang b/htdocs/langs/en_US/contracts.lang index 6b83094fabece..aa2db72fb41e8 100644 --- a/htdocs/langs/en_US/contracts.lang +++ b/htdocs/langs/en_US/contracts.lang @@ -47,6 +47,7 @@ DateContract=Contract date DateServiceActivate=Service activation date ListOfServices=List of services ListOfInactiveServices=List of not active services +ListOfNotExpiredServices=List of unexpired active services ListOfExpiredServices=List of expired active services ListOfClosedServices=List of closed services ListOfRunningServices=List of running services diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 6940ff6c467be..0d14e5be1c445 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -320,6 +320,7 @@ ErrorFixThisHere=Fix this here ErrorTheUrlOfYourDolInstanceDoesNotMatchURLIntoOAuthSetup=Error: The URL of you current instance (%s) does not match the URL defined into your OAuth2 login setup (%s). Doing OAuth2 login in such a configuration is not allowed. ErrorMenuExistValue=A Menu already exist with this Title or URL ErrorSVGFilesNotAllowedAsLinksWithout=SVG files are not allowed as external links without the option %s +ErrorGeneratingBarcode=Error while generating the barcode (probably invalid code shape) ErrorTypeMenu=Impossible to add another menu for the same module on the navbar, not handle yet ErrorFailedToCreateSymLinkToMedias=Failed to create the symlinks %s to point to %s diff --git a/htdocs/langs/en_US/interventions.lang b/htdocs/langs/en_US/interventions.lang index b92474e7f914b..570fdcc8a5f96 100644 --- a/htdocs/langs/en_US/interventions.lang +++ b/htdocs/langs/en_US/interventions.lang @@ -69,4 +69,9 @@ GenerateInter=Generate intervention FichinterNoContractLinked=Intervention %s has been created without a linked contract. ErrorFicheinterCompanyDoesNotExist=Company does not exist. Intervention has not been created. NextDateToIntervention=Date for next intervention generation -NoIntervention=No intervention \ No newline at end of file +NoIntervention=No intervention +##### Contact types ##### +TypeContact_fichinter_internal_INTERREPFOLL=Responsible for intervention follow-up +TypeContact_fichinter_internal_INTERVENING=Intervenant +TypeContact_fichinter_external_BILLING=Contact customer of intervention billing +TypeContact_fichinter_external_CUSTOMER=Customer contact of intervention follow-up diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index e2bcbe62fc360..1a6cf929f12ce 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -432,3 +432,4 @@ ConfirmEditExtrafield = Select the extrafield you want modify ConfirmEditExtrafieldQuestion = Are you sure you want to modify this extrafield? ModifyValueExtrafields = Modify value of an extrafield OrProductsWithCategories=Or products with tags/categories +AlwaysPropagateToVariants = Always propagate the modifications to the variants diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 9c49da5066df6..e58bd6f3ebc1f 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -132,3 +132,4 @@ ShowAllPerms=Show all permission rows HideAllPerms=Hide all permission rows UserPublicPageDesc=You can enable a virtual card for this user. An url with the user profile and a barcode will be available to allow anybody with a smartphone to scan it and add your contact to its address book. EnablePublicVirtualCard=Enable the user's virtual business card +ExcludedByFilter=Non qualified by filters but shown to see its hierarchy diff --git a/htdocs/langs/en_US/workflow.lang b/htdocs/langs/en_US/workflow.lang index a2b6b4c1f95a1..970dede1550c0 100644 --- a/htdocs/langs/en_US/workflow.lang +++ b/htdocs/langs/en_US/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classify linked sourc descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/es_ES/companies.lang b/htdocs/langs/es_ES/companies.lang index 9f3376401fa15..360a4369eefee 100644 --- a/htdocs/langs/es_ES/companies.lang +++ b/htdocs/langs/es_ES/companies.lang @@ -340,7 +340,7 @@ Contact=Contacto/Dirección Contacts=Contactos ContactId=Id contacto ContactsAddresses=Contactos/Direcciones -FromContactName=Nombre: +FromContactName=Nombre NoContactDefinedForThirdParty=Ningún contacto definido para este tercero NoContactDefined=Ningún contacto definido DefaultContact=Contacto por defecto diff --git a/htdocs/langs/es_ES/workflow.lang b/htdocs/langs/es_ES/workflow.lang index 4d66e803a613d..1b311283d6393 100644 --- a/htdocs/langs/es_ES/workflow.lang +++ b/htdocs/langs/es_ES/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Clasificar automátic descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Clasifique la orden de compra de fuente vinculada como recibida cuando se valida una recepción (y si la cantidad recibida por todas las recepciones es la misma que en la orden de compra para actualizar) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Clasifique la orden de compra de fuente vinculada como recibida cuando una recepción está cerrada (y si la cantidad recibida por todas las recepciones es la misma que en la orden de compra para actualizar) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Clasificar las recepciones como "facturadas" cuando se valida una factura de compra vinculada (y si el monto de la factura es el mismo que el monto total de las recepciones vinculadas) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Clasificar las recepciones como "facturadas" cuando se valida una factura de compra vinculada (y si el monto de la factura es el mismo que el monto total de las recepciones vinculadas) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Al crear un ticket, vincule los contratos disponibles de terceros coincidentes descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=A la hora de vincular contratos, buscar entre los de las casas matrices diff --git a/htdocs/langs/et_EE/workflow.lang b/htdocs/langs/et_EE/workflow.lang index 99ae21a10805b..7605c4b361cc3 100644 --- a/htdocs/langs/et_EE/workflow.lang +++ b/htdocs/langs/et_EE/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classify linked sourc descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/fr_CA/companies.lang b/htdocs/langs/fr_CA/companies.lang index 9651cc0af4cdb..d10b18b79df7d 100644 --- a/htdocs/langs/fr_CA/companies.lang +++ b/htdocs/langs/fr_CA/companies.lang @@ -17,7 +17,7 @@ ProfId2MX=ID. Prof. 2 (R..P. IMSS) ProfId3MX=Id. Prof. 3 (Charte Profesionnelle) CompanyHasNoAbsoluteDiscount=Ce client n'a pas ou plus de remise fixe disponible ContactId=ID de contact -FromContactName=Prénom: +FromContactName=Nom ListOfContactsAddresses=Liste des contacts ContactForOrdersOrShipments=Contact de commandes ou de livraison NoContactForAnyOrderOrShipments=Ce contact n'est contact d'aucune commande ou livraison diff --git a/htdocs/langs/fr_FR/companies.lang b/htdocs/langs/fr_FR/companies.lang index 6e67d36fc41c2..caba316ce0e7f 100644 --- a/htdocs/langs/fr_FR/companies.lang +++ b/htdocs/langs/fr_FR/companies.lang @@ -340,7 +340,7 @@ Contact=Contact/Adresse Contacts=Contacts ContactId=Id du contact ContactsAddresses=Contacts/Adresses -FromContactName=Nom: +FromContactName=Nom NoContactDefinedForThirdParty=Aucun contact défini pour ce tiers NoContactDefined=Aucun contact défini DefaultContact=Contact par défaut diff --git a/htdocs/langs/fr_FR/contracts.lang b/htdocs/langs/fr_FR/contracts.lang index 9337aa4240c91..704f13b091774 100644 --- a/htdocs/langs/fr_FR/contracts.lang +++ b/htdocs/langs/fr_FR/contracts.lang @@ -47,6 +47,7 @@ DateContract=Date contrat DateServiceActivate=Date activation du service ListOfServices=Liste des services ListOfInactiveServices=Liste des services inactifs +ListOfNotExpiredServices=Liste des services actifs non expirés ListOfExpiredServices=Liste des services actifs expirés ListOfClosedServices=Liste des services fermés ListOfRunningServices=Liste des services actifs diff --git a/htdocs/langs/fr_FR/errors.lang b/htdocs/langs/fr_FR/errors.lang index 84fbfaf4a21b2..a30241dd3ce1b 100644 --- a/htdocs/langs/fr_FR/errors.lang +++ b/htdocs/langs/fr_FR/errors.lang @@ -319,6 +319,7 @@ ErrorFixThisHere= Corrigez ceci ici ErrorTheUrlOfYourDolInstanceDoesNotMatchURLIntoOAuthSetup=Erreur : L'URL de votre instance actuelle (%s) ne correspond pas à l'URL définie dans votre configuration de connexion OAuth2 (%s). La connexion OAuth2 dans une telle configuration n'est pas autorisée. ErrorMenuExistValue=Un menu existe déjà avec ce titre ou cette URL ErrorSVGFilesNotAllowedAsLinksWithout=Les fichiers SVG ne sont pas autorisés en tant que liens externes sans l'option %s +ErrorGeneratingBarcode=Erreur à la génération du code-barre (probablement une valeur invalide) ErrorTypeMenu=Impossible d'ajouter un autre menu pour le même module sur la barre de navigation, pas encore géré ErrorTableExist=Le tableau %s existe déjà ErrorDictionaryNotFound=Dictionnaire %s introuvable diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index 060f7780a7000..3196df3f86936 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -432,3 +432,4 @@ ConfirmEditExtrafield = Sélectionnez l'extrafield que vous souhaitez modifier ConfirmEditExtrafieldQuestion = Voulez-vous vraiment modifier cet extrafield ? ModifyValueExtrafields = Modifier la valeur d'un extrafield OrProductsWithCategories=Ou des produits avec des tags/catégories +AlwaysPropagateToVariants = Toujours propager les modifications aux variantes diff --git a/htdocs/langs/fr_FR/workflow.lang b/htdocs/langs/fr_FR/workflow.lang index c1d12c6751a52..b2dc08ee869a4 100644 --- a/htdocs/langs/fr_FR/workflow.lang +++ b/htdocs/langs/fr_FR/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classer la ou les com descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classer le bon de commande source liée comme reçu lorsqu'une réception est validée (et si la quantité reçue par toutes les réceptions est la même que dans le bon de commande à mettre à jour) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classer le bon de commande source lié comme reçu lorsqu'une réception est clôturée (et si la quantité reçue par toutes les réceptions est la même que dans le bon de commande à mettre à jour) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classer les réceptions en "facturées" lorsqu'une facture d'achat liée est validée (et si le montant de la facture est égal au montant total des réceptions liées) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classer les réceptions en "facturées" lorsqu'une facture d'achat liée est validée (et si le montant de la facture est égal au montant total des réceptions liées) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=A la création d'un ticket, les contacts liés à au tiers sont liés au ticket. descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Les contacts liés au tiers du ticket sont utilisés pour le ticket diff --git a/htdocs/langs/gl_ES/workflow.lang b/htdocs/langs/gl_ES/workflow.lang index 4a754c5419f7f..4e1bf73207c5a 100644 --- a/htdocs/langs/gl_ES/workflow.lang +++ b/htdocs/langs/gl_ES/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Clasificar o pediment descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Clasifica o pedimento a cliente de orixe ligado como recibido cando se valida unha recepción (e se a cantidade recibida por todas as recepcións é a mesma que no pedimento que se actualiza) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Clasifica o pedimento a cliente de orixe ligado como recibido cando se pecha unha recepción (e se a cantidade recibida por todas as recepcións é a mesma que no pedimento que se actualiza) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Clasifica as recepcións como "facturadas" cando se valida unha factura de compra ligada (e se o importe da factura é o mesmo que o importe total das recepcións ligadas) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Clasifica as recepcións como "facturadas" cando se valida unha factura de compra ligada (e se o importe da factura é o mesmo que o importe total das recepcións ligadas) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Ao crear un ticket, liga os contratos dispoñibles do terceiro coincidente descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Ao ligar contratos, busca entre os das empresas matrices diff --git a/htdocs/langs/he_IL/companies.lang b/htdocs/langs/he_IL/companies.lang index b6d8bf20d3f10..63f5a6dbde189 100644 --- a/htdocs/langs/he_IL/companies.lang +++ b/htdocs/langs/he_IL/companies.lang @@ -336,7 +336,7 @@ Contact=Contact/Address Contacts=Contacts/Addresses ContactId=Contact id ContactsAddresses=Contacts/Addresses -FromContactName=Name: +FromContactName=Name NoContactDefinedForThirdParty=No contact defined for this third party NoContactDefined=No contact defined DefaultContact=Default contact/address diff --git a/htdocs/langs/hu_HU/workflow.lang b/htdocs/langs/hu_HU/workflow.lang index dc5632dab19b6..b2c9e4751ad5c 100644 --- a/htdocs/langs/hu_HU/workflow.lang +++ b/htdocs/langs/hu_HU/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=A kapcsolt forrás be descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=A kapcsolt forrásból származó beszerzési rendelés besorolása beérkezettként, amikor egy fogadás érvényesül (és ha az összes fogadás által beérkezett mennyiség megegyezik a frissítendő beszerzési rendelésben szereplő mennyiséggel) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=A kapcsolt forrásból származó beszerzési rendelés besorolása a fogadás lezárásakor (és ha az összes fogadás által kapott mennyiség megegyezik a frissítendő beszerzési rendelésben szereplő mennyiséggel) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Jegy létrehozásakor kapcsolja össze a megfelelő harmadik fél elérhető szerződéseit descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=A szerződések összekapcsolásakor keressen az anyavállalatok szerződései között diff --git a/htdocs/langs/id_ID/companies.lang b/htdocs/langs/id_ID/companies.lang index 669da132c78e1..1f60885ba675e 100644 --- a/htdocs/langs/id_ID/companies.lang +++ b/htdocs/langs/id_ID/companies.lang @@ -337,7 +337,7 @@ Contact=Kontak Alamat Contacts=Kontak/Alamat ContactId=Hubungi id ContactsAddresses=Kontak/Alamat -FromContactName=Nama: +FromContactName=Nama NoContactDefinedForThirdParty=Tidak ada kontak yang ditentukan untuk pihak ketiga ini NoContactDefined=Tidak ada kontak yang ditentukan DefaultContact=Kontak/alamat default diff --git a/htdocs/langs/id_ID/workflow.lang b/htdocs/langs/id_ID/workflow.lang index e33a89e1b0a23..b3d275dd5e2ae 100644 --- a/htdocs/langs/id_ID/workflow.lang +++ b/htdocs/langs/id_ID/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Klasifikasi sumber pe descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/it_IT/companies.lang b/htdocs/langs/it_IT/companies.lang index 9edbbd6adb338..362f1744d6695 100644 --- a/htdocs/langs/it_IT/companies.lang +++ b/htdocs/langs/it_IT/companies.lang @@ -340,7 +340,7 @@ Contact=Contatto/Indirizzo Contacts=Contatti/indirizzi ContactId=Id contatto ContactsAddresses=Contatti/Indirizzi -FromContactName=Nome: +FromContactName=Nome NoContactDefinedForThirdParty=Nessun contatto per questo soggetto terzo NoContactDefined=Nessun contatto definito DefaultContact=Contatto predefinito diff --git a/htdocs/langs/it_IT/workflow.lang b/htdocs/langs/it_IT/workflow.lang index 0ed0577720d2d..164ffc191d445 100644 --- a/htdocs/langs/it_IT/workflow.lang +++ b/htdocs/langs/it_IT/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classifica "fatturato descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classificare l'ordine di acquisto di origine collegato come ricevuto quando viene convalidato un ricevimento (e se la quantità ricevuta da tutti i ricevimenti è la stessa dell'ordine di acquisto da aggiornare) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classificare l'ordine di acquisto di origine collegata come ricevuto alla chiusura di un ricevimento (e se la quantità ricevuta da tutti i ricevimenti è la stessa dell'ordine di acquisto da aggiornare) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Quando crei un biglietto, collega i contratti disponibili di terze parti corrispondenti descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Quando si collegano i contratti, cercare tra quelli delle società madri diff --git a/htdocs/langs/ja_JP/workflow.lang b/htdocs/langs/ja_JP/workflow.lang index 8e5c9ec5a3b14..830b1e158e837 100644 --- a/htdocs/langs/ja_JP/workflow.lang +++ b/htdocs/langs/ja_JP/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=仕入先の請求書 descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=リンクされたソース購買発注を、領収は検証済なら受領したものとして指定する(ただし、全領収での受領済数量が更新する購買発注と同じである場合)。 descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=リンクされたソース購買発注を、領収終了時に受領したものとして指定する(ただし、全領収での受領数量が更新する購買発注と同じである場合)。 # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=リンクされた購入請求書が検証された場合 (および請求書の金額がリンクされた受信の合計金額と同じ場合) に、受信を「請求済み」に分類する。 +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=リンクされた購入請求書が検証された場合 (および請求書の金額がリンクされた受信の合計金額と同じ場合) に、受信を「請求済み」に分類する。 # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=チケットを作成するときは、一致するサードパーティの利用可能な契約をリンクする descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=契約をリンクする場合は、親会社の契約を検索すること diff --git a/htdocs/langs/kk_KZ/workflow.lang b/htdocs/langs/kk_KZ/workflow.lang index 20ba196f12def..21455f317f149 100644 --- a/htdocs/langs/kk_KZ/workflow.lang +++ b/htdocs/langs/kk_KZ/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Сатып алушы descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/lo_LA/workflow.lang b/htdocs/langs/lo_LA/workflow.lang index 2f33616ee980e..248fb84575a4c 100644 --- a/htdocs/langs/lo_LA/workflow.lang +++ b/htdocs/langs/lo_LA/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=ຈັດປະເພ descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/lv_LV/workflow.lang b/htdocs/langs/lv_LV/workflow.lang index 8b4c42911b5c2..621ee84c58b29 100644 --- a/htdocs/langs/lv_LV/workflow.lang +++ b/htdocs/langs/lv_LV/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Klasificēt saistīto descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Klasificēt saistītā avota pirkuma pasūtījumu kā saņemtu, kad saņemšana ir apstiprināta (un ja visu pieņemšanu saņemtais daudzums ir tāds pats kā atjaunināmajā pirkuma pasūtījumā) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Saistītā avota pirkuma pasūtījuma klasificēšana kā saņemta, kad pieņemšana ir slēgta (un ja visu pieņemšanu saņemtais daudzums ir tāds pats kā atjaunināmajā pirkuma pasūtījumā) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Klasificējiet pieņemšanas kā "rēķins", kad ir apstiprināts saistītais pirkuma rēķins (un ja rēķina summa ir tāda pati kā saistīto pieņemšanu kopējā summa) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Klasificējiet pieņemšanas kā "rēķins", kad ir apstiprināts saistītais pirkuma rēķins (un ja rēķina summa ir tāda pati kā saistīto pieņemšanu kopējā summa) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Veidojot biļeti, saistiet pieejamos atbilstošās trešās puses līgumus descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Saistot līgumus, meklējiet starp mātesuzņēmumu līgumiem diff --git a/htdocs/langs/nb_NO/workflow.lang b/htdocs/langs/nb_NO/workflow.lang index 40b45b0919d4a..0bdd21977e60f 100644 --- a/htdocs/langs/nb_NO/workflow.lang +++ b/htdocs/langs/nb_NO/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Klassifiser kildekjø descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Klassifiser koblet kilde-innkjøpsordre som mottatt når et mottak er validert (og hvis antallet mottatt av alle mottak er det samme som i innkjøpsordren som skal oppdateres) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Klassifiser koblet kilde-innkjøpsordre som mottatt når et mottak er stengt (og hvis antallet mottatt av alle mottak er det samme som i innkjøpsordren som skal oppdatere) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Klassifiser mottak til "fakturert" når en koblet kjøpsfaktura er validert (og hvis beløpet på fakturaen er det samme som totalbeløpet for de tilknyttede mottakene) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Klassifiser mottak til "fakturert" når en koblet kjøpsfaktura er validert (og hvis beløpet på fakturaen er det samme som totalbeløpet for de tilknyttede mottakene) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Når du oppretter en billett, kobler du tilgjengelige kontrakter til samsvarende tredjepart descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Når du kobler sammen kontrakter, søk blant de fra morselskapene diff --git a/htdocs/langs/nl_NL/companies.lang b/htdocs/langs/nl_NL/companies.lang index e429ef81dacbe..dffaa52e50e6b 100644 --- a/htdocs/langs/nl_NL/companies.lang +++ b/htdocs/langs/nl_NL/companies.lang @@ -340,7 +340,7 @@ Contact=Contact adres Contacts=Contactpersonen ContactId=ID contactpersoon ContactsAddresses=Contacpersonen / adressen -FromContactName=Naam: +FromContactName=Naam NoContactDefinedForThirdParty=Geen contact opgegeven voor deze derde partij NoContactDefined=Geen contactpersoon ingesteld voor deze Klant DefaultContact=Standaard contactpersoon diff --git a/htdocs/langs/nl_NL/workflow.lang b/htdocs/langs/nl_NL/workflow.lang index 2592cf1f069ac..a01f4be48de7a 100644 --- a/htdocs/langs/nl_NL/workflow.lang +++ b/htdocs/langs/nl_NL/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classificeer gekoppel descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classificeer inkooporder met gekoppelde bron als ontvangen wanneer een ontvangst is gevalideerd (en als de hoeveelheid die door alle ontvangsten is ontvangen hetzelfde is als in de inkooporder die moet worden bijgewerkt) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classificeer inkooporder met gekoppelde bron als ontvangen wanneer een ontvangst wordt gesloten (en als de hoeveelheid die door alle ontvangsten wordt ontvangen hetzelfde is als in de inkooporder die moet worden bijgewerkt) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classificeer ontvangsten als "gefactureerd" wanneer een gekoppelde aankoopfactuur gevalideerd is (en als het bedrag van de factuur gelijk is aan het totaalbedrag van de gekoppelde ontvangsten) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classificeer ontvangsten als "gefactureerd" wanneer een gekoppelde aankoopfactuur gevalideerd is (en als het bedrag van de factuur gelijk is aan het totaalbedrag van de gekoppelde ontvangsten) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Koppel bij het aanmaken van een ticket beschikbare contracten van bijpassende derde partijen descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Zoek bij het koppelen van contracten onder die van moederbedrijven diff --git a/htdocs/langs/pl_PL/companies.lang b/htdocs/langs/pl_PL/companies.lang index c55e1f33e4a64..7d348d77f02bb 100644 --- a/htdocs/langs/pl_PL/companies.lang +++ b/htdocs/langs/pl_PL/companies.lang @@ -340,7 +340,7 @@ Contact=Kontakt/Adres Contacts=Kontakty/adresy ContactId=Identyfikator kontaktu ContactsAddresses=Kontakty / Adresy -FromContactName=Nazwa: +FromContactName=Nazwa NoContactDefinedForThirdParty=Brak zdefiniowanych kontaktów dla tego kontrahenta NoContactDefined=Brak zdefinowanych kontaktów DefaultContact=Domyślny kontakt/adres diff --git a/htdocs/langs/pl_PL/workflow.lang b/htdocs/langs/pl_PL/workflow.lang index ee9fd64b10963..2bdaab963c6b6 100644 --- a/htdocs/langs/pl_PL/workflow.lang +++ b/htdocs/langs/pl_PL/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Sklasyfikuj zamówien descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/pt_PT/companies.lang b/htdocs/langs/pt_PT/companies.lang index 2e887e0dc1af3..7830ebb004bf1 100644 --- a/htdocs/langs/pt_PT/companies.lang +++ b/htdocs/langs/pt_PT/companies.lang @@ -337,7 +337,7 @@ Contact=Endereço de contacto Contacts=Contactos ContactId=ID de contacto ContactsAddresses=Contato / Endereços -FromContactName=Nome: +FromContactName=Nome NoContactDefinedForThirdParty=Não existem contactos definidos para este terceiro NoContactDefined=Nenhum contacto definido para este terceiro DefaultContact=Contacto por Defeito diff --git a/htdocs/langs/ro_RO/companies.lang b/htdocs/langs/ro_RO/companies.lang index 14f51de3069a4..87fab0ea9ed5a 100644 --- a/htdocs/langs/ro_RO/companies.lang +++ b/htdocs/langs/ro_RO/companies.lang @@ -340,7 +340,7 @@ Contact=Contact/Adresă Contacts=Contacte/Adrese ContactId=Id contact ContactsAddresses=Contacte/Adrese -FromContactName=Nume: +FromContactName=Nume NoContactDefinedForThirdParty=Niciun contact definit pentru acest terţ NoContactDefined=Niciun contact definit DefaultContact=Contact/adresă implicită diff --git a/htdocs/langs/ro_RO/workflow.lang b/htdocs/langs/ro_RO/workflow.lang index e166a0fb76814..27262eac10e0b 100644 --- a/htdocs/langs/ro_RO/workflow.lang +++ b/htdocs/langs/ro_RO/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Clasificați comanda descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Clasifică comanda de achiziție sursă asociată ca primită atunci când o recepție este validată (și dacă cantitatea primită de toate recepțiile este aceeași cu cea din comanda de achiziţie pentru actualizare) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Clasifică comanda de achiziție sursă asociată ca primită atunci când o recepție este închisă (și dacă cantitatea primită de toate recepțiile este aceeași cu cea din comanda de achiziţie pentru actualizare) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Clasifică recepțiile ca "facturate" atunci când o factură de achiziție asociată este validată (și dacă suma facturii este aceeași cu suma totală a recepțiilor asociate) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Clasifică recepțiile ca "facturate" atunci când o factură de achiziție asociată este validată (și dacă suma facturii este aceeași cu suma totală a recepțiilor asociate) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=La crearea unui tichet , asociază contractele disponibile ale terților care se potrivesc descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Când se asociază contracte, caută printre cele ale companiilor-mamă diff --git a/htdocs/langs/ru_RU/companies.lang b/htdocs/langs/ru_RU/companies.lang index 1a7e9a6940d70..49ca37d884aec 100644 --- a/htdocs/langs/ru_RU/companies.lang +++ b/htdocs/langs/ru_RU/companies.lang @@ -340,7 +340,7 @@ Contact=Контакт/адрес Contacts=Контакты/Адреса ContactId=id контакта ContactsAddresses=Контакты/Адреса -FromContactName=Имя: +FromContactName=Имя NoContactDefinedForThirdParty=Не задан контакт для этого контрагента NoContactDefined=У этого контрагента не указаны контакты DefaultContact=Контакт по умолчанию diff --git a/htdocs/langs/ru_RU/workflow.lang b/htdocs/langs/ru_RU/workflow.lang index a5e753ca226b7..02bd467727286 100644 --- a/htdocs/langs/ru_RU/workflow.lang +++ b/htdocs/langs/ru_RU/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Классифици descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Классифицировать связанный исходный заказ на покупку как полученный, когда прием подтвержден (и если количество, полученное всеми приемами, такое же, как в заказе на покупку для обновления) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Классифицировать связанный исходный заказ на покупку как полученный, когда прием закрыт (и если количество, полученное всеми приемами, такое же, как в заказе на покупку для обновления) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=При создании тикета свяжите доступные контракты соответствующей третьей стороны descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=При привязке договоров искать среди договоров материнских компаний diff --git a/htdocs/langs/sk_SK/companies.lang b/htdocs/langs/sk_SK/companies.lang index 29fe6611cf541..26f40f16b3f88 100644 --- a/htdocs/langs/sk_SK/companies.lang +++ b/htdocs/langs/sk_SK/companies.lang @@ -337,7 +337,7 @@ Contact=Contact/Address Contacts=Kontakty / adresy ContactId=Contact id ContactsAddresses=Kontakty / adresy -FromContactName=Name: +FromContactName=Name NoContactDefinedForThirdParty=Žiadny kontakt definovaná pre túto tretiu stranu NoContactDefined=Žiadny kontakt definované DefaultContact=Predvolené kontakt / adresa diff --git a/htdocs/langs/sl_SI/workflow.lang b/htdocs/langs/sl_SI/workflow.lang index 1f361b60af754..52e8c68aa2105 100644 --- a/htdocs/langs/sl_SI/workflow.lang +++ b/htdocs/langs/sl_SI/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Razvrsti naročilo po descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Razvrsti naročilo povezanega vira kot prejeto, ko je sprejem potrjen (in če je količina, ki so jo prejeli vsi sprejemi, enaka kot v naročilu za posodobitev) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Razvrstite naročilo povezanega vira kot prejeto, ko je sprejem zaprt (in če je količina, ki so jo prejeli vsi sprejemi, enaka kot v naročilu za posodobitev) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Prejeme razvrstite v »zaračunane«, ko je povezan račun za nakup potrjen (in če je znesek računa enak skupnemu znesku povezanih prejemov) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Prejeme razvrstite v »zaračunane«, ko je povezan račun za nakup potrjen (in če je znesek računa enak skupnemu znesku povezanih prejemov) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Ko ustvarjate vstopnico, povežite razpoložljive pogodbe z partnerjem descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Pri povezovanju pogodb iščite med pogodbami matičnih podjetij diff --git a/htdocs/langs/sv_SE/workflow.lang b/htdocs/langs/sv_SE/workflow.lang index 0311dba3df8c8..0fed558ee010f 100644 --- a/htdocs/langs/sv_SE/workflow.lang +++ b/htdocs/langs/sv_SE/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Märk länkad inköps descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Märk länkad inköpsorder som mottagen när en mottagning bekräftas (och om antalet som tas emot i alla mottagningar är densamma som i inköpsordern som ska uppdateras) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Märk länkad inköpsorder som mottagen när en mottagning stängs (och om antalet som tas emot i alla mottagningar är densamma som i inköpsordern som ska uppdateras) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Märk mottagningar som "fakturerade" när en länkad inköpsfaktura bekräftas (och om fakturabeloppet är detsamma som det totala beloppet för de länkade mottagningarna) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Märk mottagningar som "fakturerade" när en länkad inköpsfaktura bekräftas (och om fakturabeloppet är detsamma som det totala beloppet för de länkade mottagningarna) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=När du skapar ett ärende, länka tillgängliga kontrakt från matchande tredjepart descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=När du kopplar kontrakt sök bland moderbolagens diff --git a/htdocs/langs/sw_SW/workflow.lang b/htdocs/langs/sw_SW/workflow.lang index b3f7783945e47..7fed4f3347a19 100644 --- a/htdocs/langs/sw_SW/workflow.lang +++ b/htdocs/langs/sw_SW/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Panga agizo la ununuz descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Bainisha agizo la ununuzi la chanzo kilichounganishwa kama lilivyopokelewa wakati mapokezi yamethibitishwa (na ikiwa kiasi kilichopokelewa na mapokezi yote ni sawa na katika agizo la ununuzi la kusasisha) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Panga agizo la ununuzi la chanzo kilichounganishwa kama lilivyopokelewa wakati upokezi umefungwa (na ikiwa kiasi kilichopokelewa na mapokezi yote ni sawa na katika agizo la ununuzi la kusasishwa) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Panga mapokezi kuwa "yanayotozwa" wakati ankara ya ununuzi iliyounganishwa imethibitishwa (na ikiwa kiasi cha ankara ni sawa na jumla ya kiasi cha mapokezi yaliyounganishwa) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Panga mapokezi kuwa "yanayotozwa" wakati ankara ya ununuzi iliyounganishwa imethibitishwa (na ikiwa kiasi cha ankara ni sawa na jumla ya kiasi cha mapokezi yaliyounganishwa) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Wakati wa kuunda tikiti, unganisha mikataba inayopatikana ya watu wengine wanaolingana descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Wakati wa kuunganisha mikataba, tafuta kati ya wale wa makampuni ya wazazi diff --git a/htdocs/langs/ta_IN/workflow.lang b/htdocs/langs/ta_IN/workflow.lang index a1bab1b40a7ea..db5f4fdbe632f 100644 --- a/htdocs/langs/ta_IN/workflow.lang +++ b/htdocs/langs/ta_IN/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=விற்பனை descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=ஒரு வரவேற்பு சரிபார்க்கப்படும் போது பெறப்பட்ட இணைக்கப்பட்ட மூல கொள்முதல் ஆர்டரை வகைப்படுத்தவும் (மற்றும் அனைத்து வரவேற்புகளிலும் பெறப்பட்ட அளவு வாங்குதல் ஆர்டரில் உள்ளதைப் போலவே புதுப்பிக்கவும்) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=ஒரு வரவேற்பு மூடப்படும் போது பெறப்பட்ட இணைக்கப்பட்ட மூல கொள்முதல் ஆர்டரை வகைப்படுத்தவும் (மற்றும் அனைத்து வரவேற்புகளிலும் பெறப்பட்ட அளவு வாங்குதல் ஆர்டரில் உள்ளதைப் போலவே புதுப்பிக்கவும்) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/tg_TJ/workflow.lang b/htdocs/langs/tg_TJ/workflow.lang index 923592fa2bb3f..c534d6dab6877 100644 --- a/htdocs/langs/tg_TJ/workflow.lang +++ b/htdocs/langs/tg_TJ/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Фармоиши ха descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/tr_TR/companies.lang b/htdocs/langs/tr_TR/companies.lang index 03db3db97d1e4..985760cbd712d 100644 --- a/htdocs/langs/tr_TR/companies.lang +++ b/htdocs/langs/tr_TR/companies.lang @@ -337,7 +337,7 @@ Contact=Contact/Address Contacts=Kişiler/Adresler ContactId=Kişi kimliği ContactsAddresses=Kişiler/adresler -FromContactName=Hazırlayan: +FromContactName=Hazırlayan NoContactDefinedForThirdParty=Bu üçüncü parti için tanımlı kişi yok NoContactDefined=Bu üçüncü parti için kişi tanımlanmamış DefaultContact=Varsayılan kişi diff --git a/htdocs/langs/tr_TR/workflow.lang b/htdocs/langs/tr_TR/workflow.lang index 333c51646f6bf..6d021e19af182 100644 --- a/htdocs/langs/tr_TR/workflow.lang +++ b/htdocs/langs/tr_TR/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Tedarikçi faturası descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/uk_UA/companies.lang b/htdocs/langs/uk_UA/companies.lang index ebfedcbc54d9f..377d8a3586fbd 100644 --- a/htdocs/langs/uk_UA/companies.lang +++ b/htdocs/langs/uk_UA/companies.lang @@ -337,7 +337,7 @@ Contact=Контакт/адреса Contacts=онтакти/адреси ContactId=id контакту ContactsAddresses=Контакти/адреси -FromContactName=Назва: +FromContactName=Назва NoContactDefinedForThirdParty=З цим контрагентом не зв'язано жодного контакту NoContactDefined=Контакт не призначено DefaultContact=Контакт/адреса за промовчанням diff --git a/htdocs/langs/uk_UA/workflow.lang b/htdocs/langs/uk_UA/workflow.lang index f86ee72d0d060..3627307e2b4da 100644 --- a/htdocs/langs/uk_UA/workflow.lang +++ b/htdocs/langs/uk_UA/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Класифікув descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Класифікувати пов’язане джерело замовлення на закупівлю як отримане, коли прийом підтверджено (і якщо кількість, отримана всіма прийомами, така ж, як у замовленні на покупку для оновлення) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Класифікувати замовлення на закупівлю з пов’язаним джерелом як отримане, коли прийом закритий (і якщо кількість, отримана всіма прийомами, така ж, як у замовленні на покупку для оновлення) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=При створенні квитка зв’яжіть доступні контракти відповідної третьої сторони descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Зв’язуючи договори, шукайте серед тих материнських компаній diff --git a/htdocs/langs/ur_PK/workflow.lang b/htdocs/langs/ur_PK/workflow.lang index 7da2a5f992f45..67d1cbe648f76 100644 --- a/htdocs/langs/ur_PK/workflow.lang +++ b/htdocs/langs/ur_PK/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=جب وینڈر ان descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=جب کسی استقبالیہ کی توثیق ہو جاتی ہے تو منسلک ذریعہ خریداری کے آرڈر کو موصول ہونے کے مطابق درجہ بندی کریں (اور اگر تمام استقبالیوں کو موصول ہونے والی مقدار وہی ہے جو اپ ڈیٹ کرنے کے لیے خریداری آرڈر میں ہے) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=ریسیپشن بند ہونے پر موصول ہونے والے لنکڈ سورس پرچیز آرڈر کی درجہ بندی کریں (اور اگر تمام ریسپشنز کو موصول ہونے والی مقدار وہی ہے جو اپ ڈیٹ کرنے کے لیے خریداری آرڈر میں ہے) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/uz_UZ/workflow.lang b/htdocs/langs/uz_UZ/workflow.lang index dd4d1430c94a6..d614511ef973a 100644 --- a/htdocs/langs/uz_UZ/workflow.lang +++ b/htdocs/langs/uz_UZ/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Sotib oluvchi hisob-f descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Bog'langan manba sotib olish buyurtmasini qabul qilish tasdiqlanganda olingan deb tasniflang (va barcha qabullar tomonidan qabul qilingan miqdor yangilash uchun xarid buyurtmasi bilan bir xil bo'lsa) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Bog'langan manba buyurtmasini qabulxona yopilganda olingan deb tasniflang (va barcha qabulxonalar tomonidan qabul qilingan miqdor yangilash uchun xarid buyurtmasidagi bilan bir xil bo'lsa) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=Chipta yaratishda, mos keladigan uchinchi tomonning mavjud shartnomalarini bog'lang descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=Shartnomalarni ulashda, ota-onalar kompaniyalari orasidan qidiring diff --git a/htdocs/langs/vi_VN/companies.lang b/htdocs/langs/vi_VN/companies.lang index 21fce333e9a96..ad3c41cb6c3c0 100644 --- a/htdocs/langs/vi_VN/companies.lang +++ b/htdocs/langs/vi_VN/companies.lang @@ -337,7 +337,7 @@ Contact=Contact/Address Contacts=Liên lạc/Địa chỉ ContactId=ID Liên lạc ContactsAddresses=Liên lạc/địa chỉ -FromContactName=Tên: +FromContactName=Tên NoContactDefinedForThirdParty=Không có liên lạc được xác định cho bên thứ ba này NoContactDefined=Không liên lạc được xác định DefaultContact=Liên lạc/địa chỉ mặc định diff --git a/htdocs/langs/zh_CN/workflow.lang b/htdocs/langs/zh_CN/workflow.lang index 1252f53e21678..56f59b7da84a0 100644 --- a/htdocs/langs/zh_CN/workflow.lang +++ b/htdocs/langs/zh_CN/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classify linked sourc descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=验证接收时将链接源采购订单分类为已接收(并且如果所有接收收到的数量与要更新的采购订单中的数量相同) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=当接收关闭时将链接源采购订单分类为已接收(并且如果所有接收收到的数量与要更新的采购订单中的数量相同) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=当链接的采购发票经过验证(并且发票金额与链接的收款总金额相同时),将收款分类为“已开票” +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=当链接的采购发票经过验证(并且发票金额与链接的收款总金额相同时),将收款分类为“已开票” # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=创建服务工单时,链接其匹配的合作方的可用合同 descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/zh_HK/workflow.lang b/htdocs/langs/zh_HK/workflow.lang index 6c8e925b5f598..bc3dcd3cb4820 100644 --- a/htdocs/langs/zh_HK/workflow.lang +++ b/htdocs/langs/zh_HK/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classify linked sourc descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies diff --git a/htdocs/langs/zh_TW/workflow.lang b/htdocs/langs/zh_TW/workflow.lang index e869e7a60518d..dfee7735b61b9 100644 --- a/htdocs/langs/zh_TW/workflow.lang +++ b/htdocs/langs/zh_TW/workflow.lang @@ -22,7 +22,7 @@ descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=當供應商發票已 descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=在驗證收貨時將連結的來源採購訂單分類為已收貨(並且如果所有收貨的數量與要更新的採購訂單中的數量相同) descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=收貨結束時將連結的來源採購訂單分類為已收貨(如果所有收貨的數量與要更新的採購訂單中的數量相同) # Autoclassify purchase invoice -descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) +descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions) # Automatically link ticket to contract descWORKFLOW_TICKET_LINK_CONTRACT=當建立服務單時,連結符合之合作方的可用合約 descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=當連結合約時,在母公司的合約中搜尋 diff --git a/htdocs/loan/payment/payment.php b/htdocs/loan/payment/payment.php index 6a136f8ba2e3d..d65f48665a384 100644 --- a/htdocs/loan/payment/payment.php +++ b/htdocs/loan/payment/payment.php @@ -114,16 +114,16 @@ if (!$error) { $paymentid = 0; - $pay_amount_capital = price2num(GETPOST('amount_capital')); - $pay_amount_insurance = price2num(GETPOST('amount_insurance')); + $pay_amount_capital = (float) price2num(GETPOST('amount_capital')); + $pay_amount_insurance = (float) price2num(GETPOST('amount_insurance')); // User can't set interest him self if schedule is set (else value in schedule can be incoherent) if (!empty($line)) { $pay_amount_interest = $line->amount_interest; } else { - $pay_amount_interest = price2num(GETPOST('amount_interest')); + $pay_amount_interest = (float) price2num(GETPOST('amount_interest')); } - $remaindertopay = price2num(GETPOST('remaindertopay')); - $amount = $pay_amount_capital + $pay_amount_insurance + $pay_amount_interest; + $remaindertopay = (float) price2num(GETPOST('remaindertopay')); + $amount = (float) price2num($pay_amount_capital + $pay_amount_insurance + $pay_amount_interest, 'MT'); // This term is allready paid if (!empty($line) && !empty($line->fk_bank)) { diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 9aede3af25a9a..e4e85ad053ee4 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -713,7 +713,7 @@ function analyseVarsForSqlAndScriptsInjection(&$var, $type) // If in demo mode, we check we go to home page through the public/demo/index.php page if (!empty($dolibarr_main_demo) && $_SERVER['PHP_SELF'] == DOL_URL_ROOT.'/index.php') { // We ask index page if (empty($_SERVER['HTTP_REFERER']) || !preg_match('/public/', $_SERVER['HTTP_REFERER'])) { - dol_syslog("Call index page from another url than demo page (call is done from page ".$_SERVER['HTTP_REFERER'].")"); + dol_syslog("Call index page from another url than demo page (call is done from page ".(empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFER']).")"); $url = ''; $url .= ($url ? '&' : '').($dol_hide_topmenu ? 'dol_hide_topmenu='.$dol_hide_topmenu : ''); $url .= ($url ? '&' : '').($dol_hide_leftmenu ? 'dol_hide_leftmenu='.$dol_hide_leftmenu : ''); @@ -1744,6 +1744,7 @@ function top_htmlhead($head, $title = '', $disablejs = 0, $disablehead = 0, $arr } // Refresh value of MAIN_IHM_PARAMS_REV before forging the parameter line. if (GETPOST('dol_resetcache')) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); } @@ -2580,12 +2581,16 @@ function top_menu_quickadd() // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox // accesskey is for Mac: CTRL + key for all browsers $stringforfirstkey = $langs->trans("KeyboardShortcut"); - if ($conf->browser->name == 'chrome') { - $stringforfirstkey .= ' ALT +'; - } elseif ($conf->browser->name == 'firefox') { - $stringforfirstkey .= ' ALT + SHIFT +'; - } else { + if ($conf->browser->os === 'macintosh') { $stringforfirstkey .= ' CTL +'; + } else { + if ($conf->browser->name == 'chrome') { + $stringforfirstkey .= ' ALT +'; + } elseif ($conf->browser->name == 'firefox') { + $stringforfirstkey .= ' ALT + SHIFT +'; + } else { + $stringforfirstkey .= ' CTL +'; + } } $html .= ' @@ -2610,10 +2615,18 @@ function top_menu_quickadd() // Key map shortcut $(document).keydown(function(event){ - if ( event.which === 76 && event.ctrlKey && event.shiftKey ){ - console.log(\'control + shift + l : trigger open quick add dropdown\'); - openQuickAddDropDown(event); - } + var ostype = "'.$conf->browser->os.'"; + if (ostype === "macintosh") { + if ( event.which === 65 && event.ctrlKey ) { + console.log(\'control + a : trigger open quick add dropdown\'); + openQuickAddDropDown(event); + } + } else { + if ( event.which === 65 && event.ctrlKey && event.shiftKey ) { + console.log(\'control + shift + a : trigger open quick add dropdown\'); + openQuickAddDropDown(event); + } + } }); var openQuickAddDropDown = function(event) { @@ -2825,12 +2838,16 @@ function top_menu_bookmark() // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox // accesskey is for Mac: CTRL + key for all browsers $stringforfirstkey = $langs->trans("KeyboardShortcut"); - if ($conf->browser->name == 'chrome') { - $stringforfirstkey .= ' ALT +'; - } elseif ($conf->browser->name == 'firefox') { - $stringforfirstkey .= ' ALT + SHIFT +'; - } else { + if ($conf->browser->os === 'macintosh') { $stringforfirstkey .= ' CTL +'; + } else { + if ($conf->browser->name == 'chrome') { + $stringforfirstkey .= ' ALT +'; + } elseif ($conf->browser->name == 'firefox') { + $stringforfirstkey .= ' ALT + SHIFT +'; + } else { + $stringforfirstkey .= ' CTL +'; + } } if (!defined('JS_JQUERY_DISABLE_DROPDOWN') && !empty($conf->use_javascript_ajax)) { // This may be set by some pages that use different jquery version to avoid errors @@ -2868,11 +2885,19 @@ function top_menu_bookmark() }); // Key map shortcut - jQuery(document).keydown(function(event){ - if( event.which === 77 && event.ctrlKey && event.shiftKey ){ - console.log("Click on control + shift + m : trigger open bookmark dropdown"); - openBookMarkDropDown(event); - } + jQuery(document).keydown(function(event) { + var ostype = "'.$conf->browser->os.'"; + if (ostype === "macintosh") { + if ( event.which === 66 && event.ctrlKey ) { + console.log("Click on control + b : trigger open bookmark dropdown"); + openBookMarkDropDown(event); + } + } else { + if ( event.which === 66 && event.ctrlKey && event.shiftKey ) { + console.log("Click on control + shift + b : trigger open bookmark dropdown"); + openBookMarkDropDown(event); + } + } }); var openBookMarkDropDown = function(event) { diff --git a/htdocs/margin/agentMargins.php b/htdocs/margin/agentMargins.php index f369f1889c2a9..e0687a59811f4 100644 --- a/htdocs/margin/agentMargins.php +++ b/htdocs/margin/agentMargins.php @@ -226,7 +226,9 @@ $param .= "&enddateyear=".urlencode($enddateyear); } - +$totalMargin = 0; +$marginRate = ''; +$markRate = ''; dol_syslog('margin::agentMargins.php', LOG_DEBUG); $result = $db->query($sql); if ($result) { diff --git a/htdocs/margin/customerMargins.php b/htdocs/margin/customerMargins.php index 93850b8ec10c2..9009b9f8800c7 100644 --- a/htdocs/margin/customerMargins.php +++ b/htdocs/margin/customerMargins.php @@ -297,6 +297,9 @@ } } +$totalMargin = 0; +$marginRate = ''; +$markRate = ''; dol_syslog('margin::customerMargins.php', LOG_DEBUG); $result = $db->query($sql); if ($result) { diff --git a/htdocs/margin/productMargins.php b/htdocs/margin/productMargins.php index 32cb3c9292dd6..bd8ab22755946 100644 --- a/htdocs/margin/productMargins.php +++ b/htdocs/margin/productMargins.php @@ -247,6 +247,9 @@ } } +$totalMargin = 0; +$marginRate = ''; +$markRate = ''; dol_syslog('margin::productMargins.php', LOG_DEBUG); $result = $db->query($sql); if ($result) { diff --git a/htdocs/margin/tabs/productMargins.php b/htdocs/margin/tabs/productMargins.php index 1bda53b5c5df6..99c55de1e8053 100644 --- a/htdocs/margin/tabs/productMargins.php +++ b/htdocs/margin/tabs/productMargins.php @@ -75,8 +75,8 @@ $form = new Form($db); $totalMargin = 0; -$marginRate = 0; -$markRate = 0; +$marginRate = ''; +$markRate = ''; if ($id > 0 || !empty($ref)) { $result = $object->fetch($id, $ref); @@ -164,7 +164,7 @@ $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); } if (!empty($socid)) { - $sql .= " AND f.fk_soc = $socid"; + $sql .= " AND f.fk_soc = ".((int) $socid); } $sql .= " AND d.buy_price_ht IS NOT NULL"; // We should not use this here. Option ForceBuyingPriceIfNull should have effect only when inserting data. Once data is recorded, it must be used as it is for report. @@ -198,7 +198,7 @@ print_liste_field_titre("DateInvoice", $_SERVER["PHP_SELF"], "f.datef", "", "&id=".$object->id, '', $sortfield, $sortorder, 'left '); print_liste_field_titre("SellingPrice", $_SERVER["PHP_SELF"], "selling_price", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("BuyingPrice", $_SERVER["PHP_SELF"], "buying_price", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); - print_liste_field_titre("Qty", $_SERVER["PHP_SELF"], "d.qty", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); + print_liste_field_titre("Qty", $_SERVER["PHP_SELF"], "qty", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("Margin", $_SERVER["PHP_SELF"], "marge", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); if (!empty($conf->global->DISPLAY_MARGIN_RATES)) { print_liste_field_titre("MarginRate", $_SERVER["PHP_SELF"], "", "", "&id=".$object->id, '', $sortfield, $sortorder, 'right '); diff --git a/htdocs/margin/tabs/thirdpartyMargins.php b/htdocs/margin/tabs/thirdpartyMargins.php index 3202dcb93ce07..dfb080126d05c 100644 --- a/htdocs/margin/tabs/thirdpartyMargins.php +++ b/htdocs/margin/tabs/thirdpartyMargins.php @@ -93,6 +93,9 @@ $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; llxHeader('', $title, $help_url); +$totalMargin = 0; +$marginRate = ''; +$markRate = ''; if ($socid > 0) { $object = new Societe($db); $object->fetch($socid); diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php index 9baea8a2a713a..e35fb604cec1a 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php @@ -473,7 +473,7 @@ public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks // Write new file - if (getDolGlobalInt('MAIN_ODT_AS_PDF')) { + if (getDolGlobalString('MAIN_ODT_AS_PDF')) { try { $odfHandler->exportAsAttachedPDF($file); } catch (Exception $e) { diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php index 9826936f8abfa..4d6d8987f62d6 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php @@ -944,7 +944,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); $title = $outputlangs->transnoentities("PdfTitle"); - if (getDolGlobalInt('MAIN_ODT_AS_PDF') && is_object($outputlangsbis)) { + if (getDolGlobalString('MAIN_ODT_AS_PDF') && is_object($outputlangsbis)) { $title .= ' - '; $title .= $outputlangsbis->transnoentities("PdfTitle"); } @@ -1019,7 +1019,7 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 166d0a247df67..b1cf985e4f3f0 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -373,6 +373,20 @@ public function createFromClone(User $user, $fromid) unset($object->fk_user_creat); unset($object->import_key); + // We make $object->lines empty to sort it without produced and consumed lines + $TLines = $object->lines; + $object->lines = array(); + + // Remove produced and consumed lines + foreach ($TLines as $key => $line) { + if (in_array($line->role, array('consumed', 'produced'))) { + unset($object->lines[$key]); + } else { + $object->lines[] = $line; + } + } + + // Clear fields $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref : $this->fields['ref']['default']; $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php index 99fc1c2bb959d..6cb66c9c3ac31 100644 --- a/htdocs/multicurrency/class/api_multicurrencies.class.php +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -196,7 +196,7 @@ public function getRates($id) */ public function post($request_data = null) { - if (!DolibarrApiAccess::$user->rights->multicurrency->currency->create) { + if (!DolibarrApiAccess::$user->rights->multicurrency->currency->write) { throw new RestException(401, "Insufficient rights to create currency"); } @@ -240,7 +240,7 @@ public function post($request_data = null) */ public function put($id, $request_data = null) { - if (!DolibarrApiAccess::$user->rights->multicurrency->currency->create) { + if (!DolibarrApiAccess::$user->rights->multicurrency->currency->write) { throw new RestException(401, "Insufficient rights to update currency"); } @@ -307,7 +307,7 @@ public function delete($id) */ public function updateRate($id, $request_data = null) { - if (!DolibarrApiAccess::$user->rights->multicurrency->currency->create) { + if (!DolibarrApiAccess::$user->rights->multicurrency->currency->write) { throw new RestException(401, "Insufficient rights to update currency rate"); } diff --git a/htdocs/product/agenda.php b/htdocs/product/agenda.php index ed5d456b3a54a..8e15448517842 100644 --- a/htdocs/product/agenda.php +++ b/htdocs/product/agenda.php @@ -160,7 +160,7 @@ $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product'); print dol_get_fiche_head($head, 'agenda', $titre, -1, $picto); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "fk_product_type = ".((int) $object->type); $shownav = 1; diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 08d8625815006..c4dc0d6dcbe55 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1486,7 +1486,7 @@ print ''; } - if ($type != 1 && isModEnabled('stock')) { + if (($type != 1 || getDolGlobalInt('STOCK_SUPPORTS_SERVICES')) && isModEnabled('stock')) { // Default warehouse print ''.$langs->trans("DefaultWarehouse").''; print img_picto($langs->trans("DefaultWarehouse"), 'stock', 'class="pictofixedwidth"'); @@ -2053,7 +2053,7 @@ } // Stock - if ($object->isProduct() && isModEnabled('stock')) { + if (($object->isProduct() || getDolGlobalInt('STOCK_SUPPORTS_SERVICES')) && isModEnabled('stock')) { // Default warehouse print ''.$langs->trans("DefaultWarehouse").''; print img_picto($langs->trans("DefaultWarehouse"), 'stock', 'class="pictofixedwidth"'); @@ -2557,7 +2557,7 @@ } // Default warehouse - if ($object->isProduct() && isModEnabled('stock')) { + if (($object->isProduct() || getDolGlobalInt('STOCK_SUPPORTS_SERVICES')) && isModEnabled('stock')) { $warehouse = new Entrepot($db); $warehouse->fetch($object->fk_default_warehouse); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 3ba34b9672847..3f64408e57beb 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -70,7 +70,10 @@ class Product extends CommonObject 'facturedet' => array('name' => 'Invoice', 'parent' => 'facture', 'parentkey' => 'fk_facture'), 'contratdet' => array('name' => 'Contract', 'parent' => 'contrat', 'parentkey' => 'fk_contrat'), 'facture_fourn_det' => array('name' => 'SupplierInvoice', 'parent' => 'facture_fourn', 'parentkey' => 'fk_facture_fourn'), - 'commande_fournisseurdet' => array('name' => 'SupplierOrder', 'parent' => 'commande_fournisseur', 'parentkey' => 'fk_commande') + 'commande_fournisseurdet' => array('name' => 'SupplierOrder', 'parent' => 'commande_fournisseur', 'parentkey' => 'fk_commande'), + 'mrp_production' => array('name' => 'Mo', 'parent' => 'mrp_mo', 'parentkey' => 'fk_mo' ), + 'bom_bom' => array('name' => 'BOM'), + 'bom_bomline' => array('name' => 'BOMLine', 'parent' => 'bom_bom', 'parentkey' => 'fk_bom'), ); /** @@ -1272,7 +1275,6 @@ public function update($id, $user, $notrigger = false, $action = 'update', $upda // Multilangs if (getDolGlobalInt('MAIN_MULTILANGS')) { if ($this->setMultiLangs($user) < 0) { - $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql; return -2; } } @@ -1346,7 +1348,7 @@ public function update($id, $user, $notrigger = false, $action = 'update', $upda } if (!$error) { - if (isModEnabled('variants')) { + if (isModEnabled('variants') && getDolGlobalString('PRODUIT_ATTRIBUTES_PROPAGATE', 1)) { include_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php'; $comb = new ProductCombination($this->db); @@ -2538,7 +2540,7 @@ public function fetch($id = '', $ref = '', $ref_ext = '', $barcode = '', $ignore $this->fk_default_bom = $obj->fk_default_bom; $this->duration = $obj->duration; - $this->duration_value = $obj->duration ? substr($obj->duration, 0, dol_strlen($obj->duration) - 1) : null; + $this->duration_value = $obj->duration ? (int) (substr($obj->duration, 0, dol_strlen($obj->duration) - 1)) : 0; $this->duration_unit = $obj->duration ? substr($obj->duration, -1) : null; $this->canvas = $obj->canvas; $this->net_measure = $obj->net_measure; @@ -4723,8 +4725,8 @@ public function clone_fournisseurs($fromId, $toId) // les prix de fournisseurs. $sql = "INSERT ".$this->db->prefix()."product_fournisseur_price ("; - $sql .= " datec, fk_product, fk_soc, price, quantity, fk_user)"; - $sql .= " SELECT '".$this->db->idate($now)."', ".((int) $toId).", fk_soc, price, quantity, fk_user"; + $sql .= " datec, fk_product, fk_soc, price, quantity, fk_user, tva_tx)"; + $sql .= " SELECT '".$this->db->idate($now)."', ".((int) $toId).", fk_soc, price, quantity, fk_user, tva_tx"; $sql .= " FROM ".$this->db->prefix()."product_fournisseur_price"; $sql .= " WHERE fk_product = ".((int) $fromId); diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index f7ea2478da7c9..25ac2d9366411 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -226,7 +226,7 @@ * Product card */ if ($user->rights->produit->lire || $user->hasRight('service', 'lire')) { - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $shownav = 1; if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) { diff --git a/htdocs/product/document.php b/htdocs/product/document.php index f7753432043cf..c38e30123d0d5 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -239,7 +239,7 @@ } - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "fk_product_type = ".((int) $object->type); $shownav = 1; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index b36c134d20b52..455fbeea600c8 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -185,6 +185,7 @@ } if ($action == 'save_price') { + $ref_fourn_price_id = GETPOSTINT('ref_fourn_price_id'); $id_fourn = GETPOST("id_fourn"); if (empty($id_fourn)) { $id_fourn = GETPOST("search_id_fourn"); @@ -269,7 +270,7 @@ if (!$error) { $db->begin(); - if (!$error) { + if (empty($ref_fourn_price_id)) { $ret = $object->add_fournisseur($user, $id_fourn, $ref_fourn_old, $quantity); // This insert record with no value for price. Values are update later with update_buyprice if ($ret == -3) { $error++; @@ -290,8 +291,8 @@ if (!$error) { $supplier = new Fournisseur($db); $result = $supplier->fetch($id_fourn); - if (GETPOSTISSET('ref_fourn_price_id')) { - $object->fetch_product_fournisseur_price(GETPOST('ref_fourn_price_id', 'int')); + if ($ref_fourn_price_id > 0) { + $object->fetch_product_fournisseur_price($ref_fourn_price_id); } $extralabels = $extrafields->fetch_name_optionals_label("product_fournisseur_price"); $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price"); @@ -390,7 +391,7 @@ print dol_get_fiche_head($head, 'suppliers', $titre, -1, $picto); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "fk_product_type = ".((int) $object->type); $shownav = 1; diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 4ca3768fa11aa..e9ddf7ad87747 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -1045,8 +1045,9 @@ function barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,sele // Expected quantity = Quantity in stock when we start inventory print ''; $valuetoshow = $obj->qty_stock; + // For inventory not yet close, we overwrite with the real value in stock now - if ($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) { + if (($object->status == $object::STATUS_DRAFT || $object->status == $object::STATUS_VALIDATED) && !getDolGlobalString('DISABLE_QTY_OVERWRITE')) { if (isModEnabled('productbatch') && $product_static->hasbatch()) { $valuetoshow = $product_static->stock_warehouse[$obj->fk_warehouse]->detail_batch[$obj->batch]->qty; } else { @@ -1088,10 +1089,11 @@ function barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,sele //PMP Real print ''; - - - if (!empty($obj->pmp_real)) $pmp_real = $obj->pmp_real; - else $pmp_real = $product_static->pmp; + if (!empty($obj->pmp_real) || (string) $obj->pmp_real === '0') { + $pmp_real = $obj->pmp_real; + } else { + $pmp_real = $product_static->pmp; + } $pmp_valuation_real = $pmp_real * $qty_view; print ''; print ''; @@ -1306,6 +1308,7 @@ function updateTotalValuation() { })); } + trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params); } -if ($type === "" || $type == Product::TYPE_SERVICE) { +if ((isModEnabled('service') && $type === "") || $type == Product::TYPE_SERVICE) { $label = 'NewService'; $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=1', '', $perm, $params); } diff --git a/htdocs/product/note.php b/htdocs/product/note.php index f8dab5e6bf389..13a611e9f2506 100644 --- a/htdocs/product/note.php +++ b/htdocs/product/note.php @@ -122,7 +122,7 @@ print dol_get_fiche_head($head, 'note', $titre, -1, $picto); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "fk_product_type = ".((int) $object->type); $shownav = 1; diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 9dc217f782c8e..daa486f71c3d1 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -507,7 +507,9 @@ if ($action == 'activate_price_by_qty') { // Activating product price by quantity add a new price line with price_by_qty set to 1 $level = GETPOST('level', 'int'); - $ret = $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1); + $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc; + $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc; + $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 1); if ($ret < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -517,7 +519,9 @@ if ($action == 'disable_price_by_qty') { // Disabling product price by quantity add a new price line with price_by_qty set to 0 $level = GETPOST('level', 'int'); - $ret = $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 0); + $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc; + $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc; + $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 0); if ($ret < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -866,7 +870,7 @@ print dol_get_fiche_head($head, 'price', $titre, -1, $picto); -$linkback = ''.$langs->trans("BackToList").''; +$linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "fk_product_type = ".((int) $object->type); $shownav = 1; diff --git a/htdocs/product/stats/card.php b/htdocs/product/stats/card.php index a91927e77d4d1..93e3ef2d3e2b6 100644 --- a/htdocs/product/stats/card.php +++ b/htdocs/product/stats/card.php @@ -151,7 +151,7 @@ print dol_get_fiche_head($head, 'stats', $titre, -1, $picto); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', '', '', '', 0, '', '', 1); diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php index c5209b725b574..2c9befc5c4e9c 100644 --- a/htdocs/product/stats/facture.php +++ b/htdocs/product/stats/facture.php @@ -128,7 +128,7 @@ setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $shownav = 1; if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) { diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index 95457b6a973dd..afe4d282e38ae 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -941,7 +941,7 @@ public function get_children_warehouses($id, &$TChildWarehouses) * @param int $hideref Hide ref * @return int 0 if KO, 1 if OK */ - public function generateDocument($modele, $outputlangs = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0) { global $conf, $user, $langs; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 2792dfc934434..5a8abd50942e4 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -1195,7 +1195,7 @@ public function LibStatut($mode = 0) * @param int $hideref Hide ref * @return int 0 if KO, 1 if OK */ - public function generateDocument($modele, $outputlangs = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0) + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0) { global $conf, $user, $langs; diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index d52b15ca3079c..fe9d71aa52681 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -611,7 +611,7 @@ dol_htmloutput_events(); - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; $shownav = 1; if ($user->socid && !in_array('stock', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) { diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 275e08373e23c..7cfbc964e41e6 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -30,11 +30,11 @@ // Load Dolibarr environment require '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; -require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; +require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.commande.class.php'; +require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; require_once './lib/replenishment.lib.php'; // Load translation files required by the page @@ -54,7 +54,7 @@ $action = GETPOST('action', 'aZ09'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); -$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); +$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $type = GETPOST('type', 'int'); $tobuy = GETPOST('tobuy', 'int'); $salert = GETPOST('salert', 'alpha'); @@ -68,7 +68,7 @@ $fk_entrepot = GETPOST('fk_entrepot', 'int'); // List all visible warehouses -$resWar = $db->query("SELECT rowid FROM " . MAIN_DB_PREFIX . "entrepot WHERE entity IN (" . $db->sanitize(getEntity('stock')) .")"); +$resWar = $db->query("SELECT rowid FROM " . MAIN_DB_PREFIX . "entrepot WHERE entity IN (" . $db->sanitize(getEntity('stock')) . ")"); $listofqualifiedwarehousesid = ""; $count = 0; while ($tmpobj = $db->fetch_object($resWar)) { @@ -93,7 +93,7 @@ if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $offset = $limit * $page; if (!$sortfield) { @@ -161,15 +161,15 @@ $db->begin(); $suppliers = array(); - require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; + require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php'; $productsupplier = new ProductFournisseur($db); for ($i = 0; $i < $linecount; $i++) { - if (GETPOST('choose'.$i, 'alpha') === 'on' && GETPOST('fourn'.$i, 'int') > 0) { + if (GETPOST('choose' . $i, 'alpha') === 'on' && GETPOST('fourn' . $i, 'int') > 0) { //one line $box = $i; - $supplierpriceid = GETPOST('fourn'.$i, 'int'); + $supplierpriceid = GETPOST('fourn' . $i, 'int'); //get all the parameters needed to create a line - $qty = GETPOST('tobuy'.$i, 'int'); + $qty = GETPOST('tobuy' . $i, 'int'); $idprod = $productsupplier->get_buyprice($supplierpriceid, $qty); $res = $productsupplier->fetch($idprod); if ($res && $idprod > 0) { @@ -197,9 +197,19 @@ } $line->tva_tx = $productsupplier->vatrate_supplier; + $tva = $line->tva_tx / 100; + + // If we use multicurrency + if (isModEnabled('multicurrency') && !empty($productsupplier->fourn_multicurrency_code) && $productsupplier->fourn_multicurrency_code != $conf->currency) { + $line->multicurrency_code = $productsupplier->fourn_multicurrency_code; + $line->fk_multicurrency = $productsupplier->fourn_multicurrency_id; + $line->multicurrency_subprice = $productsupplier->fourn_multicurrency_unitprice; + $line->multicurrency_total_ht = $line->multicurrency_subprice * $qty; + $line->multicurrency_total_tva = $line->multicurrency_total_ht * $tva; + $line->multicurrency_total_ttc = $line->multicurrency_total_ht + $line->multicurrency_total_tva; + } $line->subprice = $productsupplier->fourn_pu; $line->total_ht = $productsupplier->fourn_pu * $qty; - $tva = $line->tva_tx / 100; $line->total_tva = $line->total_ht * $tva; $line->total_ttc = $line->total_ht + $line->total_tva; $line->remise_percent = $productsupplier->remise_percent; @@ -215,7 +225,7 @@ dol_print_error($db); } - unset($_POST['fourn'.$i]); + unset($_POST['fourn' . $i]); } unset($_POST[$i]); } @@ -229,10 +239,10 @@ $order = new CommandeFournisseur($db); // Check if an order for the supplier exists - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."commande_fournisseur"; - $sql .= " WHERE fk_soc = ".((int) $suppliersid[$i]); - $sql .= " AND source = ".((int) $order::SOURCE_ID_REPLENISHMENT)." AND fk_statut = ".((int) $order::STATUS_DRAFT); - $sql .= " AND entity IN (".getEntity('commande_fournisseur').")"; + $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "commande_fournisseur"; + $sql .= " WHERE fk_soc = " . ((int) $suppliersid[$i]); + $sql .= " AND source = " . ((int) $order::SOURCE_ID_REPLENISHMENT) . " AND fk_statut = " . ((int) $order::STATUS_DRAFT); + $sql .= " AND entity IN (" . getEntity('commande_fournisseur') . ")"; $sql .= " ORDER BY date_creation DESC"; $resql = $db->query($sql); if ($resql && $db->num_rows($resql) > 0) { @@ -264,20 +274,23 @@ null, null, 0, - $line->fk_unit + $line->fk_unit, + $line->multicurrency_subprice ?? 0 ); } if ($result < 0) { $fail++; - $msg = $langs->trans('OrderFail')." : "; + $msg = $langs->trans('OrderFail') . " : "; $msg .= $order->error; setEventMessages($msg, null, 'errors'); } else { $id = $result; } + $i++; } else { $order->socid = $suppliersid[$i]; $order->fetch_thirdparty(); + $order->multicurrency_code = $order->thirdparty->multicurrency_code; // Trick to know which orders have been generated using the replenishment feature $order->source = $order::SOURCE_ID_REPLENISHMENT; @@ -294,7 +307,7 @@ $id = $order->create($user); if ($id < 0) { $fail++; - $msg = $langs->trans('OrderFail')." : "; + $msg = $langs->trans('OrderFail') . " : "; $msg .= $order->error; setEventMessages($msg, null, 'errors'); } @@ -347,11 +360,11 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { $sql .= ' pse.desiredstock as desiredstockpse, pse.seuil_stock_alerte as seuil_stock_alertepse,'; } -$sql .= " ".$sqldesiredtock." as desiredstockcombined, ".$sqlalertstock." as seuil_stock_alertecombined,"; +$sql .= " " . $sqldesiredtock . " as desiredstockcombined, " . $sqlalertstock . " as seuil_stock_alertecombined,"; $sql .= ' s.fk_product,'; -$sql .= " SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").') as stock_physique'; +$sql .= " SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ') as stock_physique'; if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { - $sql .= ", SUM(".$db->ifsql("s.reel IS NULL OR s.fk_entrepot <> ".$fk_entrepot, "0", "s.reel").') as stock_real_warehouse'; + $sql .= ", SUM(" . $db->ifsql("s.reel IS NULL OR s.fk_entrepot <> " . $fk_entrepot, "0", "s.reel") . ') as stock_real_warehouse'; } // Add fields from hooks @@ -359,21 +372,26 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_product'; $list_warehouse = (empty($listofqualifiedwarehousesid) ? '0' : $listofqualifiedwarehousesid); -$sql .= ' AND s.fk_entrepot IN ('.$db->sanitize($list_warehouse) .')'; + +$sql .= ' FROM ' . MAIN_DB_PREFIX . 'product as p'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s ON p.rowid = s.fk_product'; +$sql .= ' AND s.fk_entrepot IN (' . $db->sanitize($list_warehouse) . ')'; + +$list_warehouse_selected = ($fk_entrepot < 0 || empty($fk_entrepot)) ? $list_warehouse : $fk_entrepot; +$sql .= ' AND s.fk_entrepot IN (' . $db->sanitize($list_warehouse_selected) . ')'; + //$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot AS ent ON s.fk_entrepot = ent.rowid AND ent.entity IN('.getEntity('stock').')'; if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.((int) $fk_entrepot).')'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = ' . ((int) $fk_entrepot) . ')'; } // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListJoin', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= ' WHERE p.entity IN ('.getEntity('product').')'; +$sql .= ' WHERE p.entity IN (' . getEntity('product') . ')'; if ($sall) { $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); } @@ -392,11 +410,11 @@ $sql .= natural_search('p.label', $search_label); } $sql .= ' AND p.tobuy = 1'; -if (!empty($conf->variants->eabled) && empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) { // Add test to exclude products that has variants - $sql .= ' AND p.rowid NOT IN (SELECT pac.fk_product_parent FROM '.MAIN_DB_PREFIX.'product_attribute_combination as pac WHERE pac.entity IN ('.getEntity('product').'))'; +if (isModEnabled('variants') && !getDolGlobalString('VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT')) { // Add test to exclude products that has variants + $sql .= ' AND p.rowid NOT IN (SELECT pac.fk_product_parent FROM ' . MAIN_DB_PREFIX . 'product_attribute_combination as pac WHERE pac.entity IN (' . getEntity('product') . '))'; } if ($fk_supplier > 0) { - $sql .= ' AND EXISTS (SELECT pfp.rowid FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid AND pfp.fk_soc = '.((int) $fk_supplier).' AND pfp.entity IN ('.getEntity('product_fournisseur_price').'))'; + $sql .= ' AND EXISTS (SELECT pfp.rowid FROM ' . MAIN_DB_PREFIX . 'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid AND pfp.fk_soc = ' . ((int) $fk_supplier) . ' AND pfp.entity IN (' . getEntity('product_fournisseur_price') . '))'; } // Add where from hooks $parameters = array(); @@ -416,9 +434,9 @@ if ($usevirtualstock) { if (isModEnabled('commande')) { - $sqlCommandesCli = "(SELECT ".$db->ifsql("SUM(cd1.qty) IS NULL", "0", "SUM(cd1.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlCommandesCli .= " FROM ".MAIN_DB_PREFIX."commandedet as cd1, ".MAIN_DB_PREFIX."commande as c1"; - $sqlCommandesCli .= " WHERE c1.rowid = cd1.fk_commande AND c1.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'commande').")"; + $sqlCommandesCli = "(SELECT " . $db->ifsql("SUM(cd1.qty) IS NULL", "0", "SUM(cd1.qty)") . " as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlCommandesCli .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd1, " . MAIN_DB_PREFIX . "commande as c1"; + $sqlCommandesCli .= " WHERE c1.rowid = cd1.fk_commande AND c1.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'commande') . ")"; $sqlCommandesCli .= " AND cd1.fk_product = p.rowid"; $sqlCommandesCli .= " AND c1.fk_statut IN (1,2))"; } else { @@ -426,14 +444,14 @@ } if (isModEnabled("expedition")) { - $sqlExpeditionsCli = "(SELECT ".$db->ifsql("SUM(ed2.qty) IS NULL", "0", "SUM(ed2.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlExpeditionsCli .= " FROM ".MAIN_DB_PREFIX."expedition as e2,"; - $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."expeditiondet as ed2,"; - $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commande as c2,"; - $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commandedet as cd2"; - $sqlExpeditionsCli .= " WHERE ed2.fk_expedition = e2.rowid AND cd2.rowid = ed2.fk_origin_line AND e2.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'expedition').")"; - $sqlExpeditionsCli .= " AND cd2.fk_commande = c2.rowid"; - $sqlExpeditionsCli .= " AND c2.fk_statut IN (1,2)"; + $sqlExpeditionsCli = "(SELECT " . $db->ifsql("SUM(ed2.qty) IS NULL", "0", "SUM(ed2.qty)") . " as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlExpeditionsCli .= " FROM " . MAIN_DB_PREFIX . "expedition as e2,"; + $sqlExpeditionsCli .= " " . MAIN_DB_PREFIX . "expeditiondet as ed2,"; + $sqlExpeditionsCli .= " " . MAIN_DB_PREFIX . "commande as c2,"; + $sqlExpeditionsCli .= " " . MAIN_DB_PREFIX . "commandedet as cd2"; + $sqlExpeditionsCli .= " WHERE ed2.fk_expedition = e2.rowid AND cd2.rowid = ed2.fk_origin_line AND e2.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'expedition') . ")"; + $sqlExpeditionsCli .= " AND cd2.fk_commande = c2.rowid"; + $sqlExpeditionsCli .= " AND c2.fk_statut IN (1,2)"; $sqlExpeditionsCli .= " AND cd2.fk_product = p.rowid"; $sqlExpeditionsCli .= " AND e2.fk_statut IN (1,2))"; } else { @@ -441,18 +459,18 @@ } if (isModEnabled("supplier_order")) { - $sqlCommandesFourn = "(SELECT ".$db->ifsql("SUM(cd3.qty) IS NULL", "0", "SUM(cd3.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlCommandesFourn .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd3,"; - $sqlCommandesFourn .= " ".MAIN_DB_PREFIX."commande_fournisseur as c3"; + $sqlCommandesFourn = "(SELECT " . $db->ifsql("SUM(cd3.qty) IS NULL", "0", "SUM(cd3.qty)") . " as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlCommandesFourn .= " FROM " . MAIN_DB_PREFIX . "commande_fournisseurdet as cd3,"; + $sqlCommandesFourn .= " " . MAIN_DB_PREFIX . "commande_fournisseur as c3"; $sqlCommandesFourn .= " WHERE c3.rowid = cd3.fk_commande"; - $sqlCommandesFourn .= " AND c3.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'supplier_order').")"; + $sqlCommandesFourn .= " AND c3.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'supplier_order') . ")"; $sqlCommandesFourn .= " AND cd3.fk_product = p.rowid"; $sqlCommandesFourn .= " AND c3.fk_statut IN (3,4))"; - $sqlReceptionFourn = "(SELECT ".$db->ifsql("SUM(fd4.qty) IS NULL", "0", "SUM(fd4.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlReceptionFourn .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as cf4,"; - $sqlReceptionFourn .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as fd4"; - $sqlReceptionFourn .= " WHERE fd4.fk_commande = cf4.rowid AND cf4.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'supplier_order').")"; + $sqlReceptionFourn = "(SELECT " . $db->ifsql("SUM(fd4.qty) IS NULL", "0", "SUM(fd4.qty)") . " as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlReceptionFourn .= " FROM " . MAIN_DB_PREFIX . "commande_fournisseur as cf4,"; + $sqlReceptionFourn .= " " . MAIN_DB_PREFIX . "commande_fournisseur_dispatch as fd4"; + $sqlReceptionFourn .= " WHERE fd4.fk_commande = cf4.rowid AND cf4.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'supplier_order') . ")"; $sqlReceptionFourn .= " AND fd4.fk_product = p.rowid"; $sqlReceptionFourn .= " AND cf4.fk_statut IN (3,4))"; } else { @@ -461,18 +479,18 @@ } if (isModEnabled('mrp')) { - $sqlProductionToConsume = "(SELECT GREATEST(0, ".$db->ifsql("SUM(".$db->ifsql("mp5.role = 'toconsume'", 'mp5.qty', '- mp5.qty').") IS NULL", "0", "SUM(".$db->ifsql("mp5.role = 'toconsume'", 'mp5.qty', '- mp5.qty').")").") as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlProductionToConsume .= " FROM ".MAIN_DB_PREFIX."mrp_mo as mm5,"; - $sqlProductionToConsume .= " ".MAIN_DB_PREFIX."mrp_production as mp5"; - $sqlProductionToConsume .= " WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'mo').")"; + $sqlProductionToConsume = "(SELECT GREATEST(0, " . $db->ifsql("SUM(" . $db->ifsql("mp5.role = 'toconsume'", 'mp5.qty', '- mp5.qty') . ") IS NULL", "0", "SUM(" . $db->ifsql("mp5.role = 'toconsume'", 'mp5.qty', '- mp5.qty') . ")") . ") as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlProductionToConsume .= " FROM " . MAIN_DB_PREFIX . "mrp_mo as mm5,"; + $sqlProductionToConsume .= " " . MAIN_DB_PREFIX . "mrp_production as mp5"; + $sqlProductionToConsume .= " WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'mo') . ")"; $sqlProductionToConsume .= " AND mp5.fk_product = p.rowid"; $sqlProductionToConsume .= " AND mp5.role IN ('toconsume', 'consumed')"; $sqlProductionToConsume .= " AND mm5.status IN (1,2))"; - $sqlProductionToProduce = "(SELECT GREATEST(0, ".$db->ifsql("SUM(".$db->ifsql("mp5.role = 'toproduce'", 'mp5.qty', '- mp5.qty').") IS NULL", "0", "SUM(".$db->ifsql("mp5.role = 'toproduce'", 'mp5.qty', '- mp5.qty').")").") as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL - $sqlProductionToProduce .= " FROM ".MAIN_DB_PREFIX."mrp_mo as mm5,"; - $sqlProductionToProduce .= " ".MAIN_DB_PREFIX."mrp_production as mp5"; - $sqlProductionToProduce .= " WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (".getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'mo').")"; + $sqlProductionToProduce = "(SELECT GREATEST(0, " . $db->ifsql("SUM(" . $db->ifsql("mp5.role = 'toproduce'", 'mp5.qty', '- mp5.qty') . ") IS NULL", "0", "SUM(" . $db->ifsql("mp5.role = 'toproduce'", 'mp5.qty', '- mp5.qty') . ")") . ") as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL + $sqlProductionToProduce .= " FROM " . MAIN_DB_PREFIX . "mrp_mo as mm5,"; + $sqlProductionToProduce .= " " . MAIN_DB_PREFIX . "mrp_production as mp5"; + $sqlProductionToProduce .= " WHERE mm5.rowid = mp5.fk_mo AND mm5.entity IN (" . getEntity(!empty($conf->global->STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE) ? 'stock' : 'mo') . ")"; $sqlProductionToProduce .= " AND mp5.fk_product = p.rowid"; $sqlProductionToProduce .= " AND mp5.role IN ('toproduce', 'produced')"; $sqlProductionToProduce .= " AND mm5.status IN (1,2))"; @@ -482,45 +500,53 @@ } $sql .= ' HAVING ('; - $sql .= " (".$sqldesiredtock." >= 0 AND (".$sqldesiredtock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; - $sql .= " - (".$sqlCommandesCli." - ".$sqlExpeditionsCli.") + (".$sqlCommandesFourn." - ".$sqlReceptionFourn.") + (".$sqlProductionToProduce." - ".$sqlProductionToConsume.")))"; + $sql .= " (" . $sqldesiredtock . " >= 0 AND (" . $sqldesiredtock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ')'; + $sql .= " - (" . $sqlCommandesCli . " - " . $sqlExpeditionsCli . ") + (" . $sqlCommandesFourn . " - " . $sqlReceptionFourn . ") + (" . $sqlProductionToProduce . " - " . $sqlProductionToConsume . ")))"; $sql .= ' OR'; if ($includeproductswithoutdesiredqty == 'on') { - $sql .= " ((".$sqlalertstock." >= 0 OR ".$sqlalertstock." IS NULL) AND (".$db->ifsql($sqlalertstock." IS NULL", "0", $sqlalertstock)." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").")"; + $sql .= " ((" . $sqlalertstock . " >= 0 OR " . $sqlalertstock . " IS NULL) AND (" . $db->ifsql($sqlalertstock . " IS NULL", "0", $sqlalertstock) . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ")"; } else { - $sql .= " (".$sqlalertstock." >= 0 AND (".$sqlalertstock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").')'; + $sql .= " (" . $sqlalertstock . " >= 0 AND (" . $sqlalertstock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ')'; } - $sql .= " - (".$sqlCommandesCli." - ".$sqlExpeditionsCli.") + (".$sqlCommandesFourn." - ".$sqlReceptionFourn.") + (".$sqlProductionToProduce." - ".$sqlProductionToConsume.")))"; + $sql .= " - (" . $sqlCommandesCli . " - " . $sqlExpeditionsCli . ") + (" . $sqlCommandesFourn . " - " . $sqlReceptionFourn . ") + (" . $sqlProductionToProduce . " - " . $sqlProductionToConsume . ")))"; $sql .= ")"; + if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { + $sql .= " AND ("; + $sql .= " pse.desiredstock > 0)"; + } - if ($salert == 'on') { // Option to see when stock is lower than alert + if ($salert == 'on') { // Option to see when stock is lower than alert $sql .= ' AND ('; if ($includeproductswithoutdesiredqty == 'on') { - $sql .= "(".$sqlalertstock." >= 0 OR ".$sqlalertstock." IS NULL) AND (".$db->ifsql($sqlalertstock." IS NULL", "0", $sqlalertstock)." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").")"; + $sql .= "(" . $sqlalertstock . " >= 0 OR " . $sqlalertstock . " IS NULL) AND (" . $db->ifsql($sqlalertstock . " IS NULL", "0", $sqlalertstock) . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ")"; } else { - $sql .= $sqlalertstock." >= 0 AND (".$sqlalertstock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").")"; + $sql .= $sqlalertstock . " >= 0 AND (" . $sqlalertstock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ")"; } - $sql .= " - (".$sqlCommandesCli." - ".$sqlExpeditionsCli.") + (".$sqlCommandesFourn." - ".$sqlReceptionFourn.") + (".$sqlProductionToProduce." - ".$sqlProductionToConsume."))"; + $sql .= " - (" . $sqlCommandesCli . " - " . $sqlExpeditionsCli . ") + (" . $sqlCommandesFourn . " - " . $sqlReceptionFourn . ") + (" . $sqlProductionToProduce . " - " . $sqlProductionToConsume . "))"; $sql .= ")"; $alertchecked = 'checked'; } } else { $sql .= ' HAVING ('; - $sql .= "(".$sqldesiredtock." >= 0 AND (".$sqldesiredtock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").")))"; + $sql .= "(" . $sqldesiredtock . " >= 0 AND (" . $sqldesiredtock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ")))"; $sql .= ' OR'; if ($includeproductswithoutdesiredqty == 'on') { - $sql .= " ((".$sqlalertstock." >= 0 OR ".$sqlalertstock." IS NULL) AND (".$db->ifsql($sqlalertstock." IS NULL", "0", $sqlalertstock)." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql .= " ((" . $sqlalertstock . " >= 0 OR " . $sqlalertstock . " IS NULL) AND (" . $db->ifsql($sqlalertstock . " IS NULL", "0", $sqlalertstock) . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ')))'; } else { - $sql .= " (".$sqlalertstock." >= 0 AND (".$sqlalertstock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").')))'; + $sql .= " (" . $sqlalertstock . " >= 0 AND (" . $sqlalertstock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . ')))'; } $sql .= ')'; + if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { + $sql .= " AND ("; + $sql .= " pse.desiredstock > 0)"; + } - if ($salert == 'on') { // Option to see when stock is lower than alert + if ($salert == 'on') { // Option to see when stock is lower than alert $sql .= " AND ("; if ($includeproductswithoutdesiredqty == 'on') { - $sql .= " (".$sqlalertstock." >= 0 OR ".$sqlalertstock." IS NULL) AND (".$db->ifsql($sqlalertstock." IS NULL", "0", $sqlalertstock)." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel")."))"; + $sql .= " (" . $sqlalertstock . " >= 0 OR " . $sqlalertstock . " IS NULL) AND (" . $db->ifsql($sqlalertstock . " IS NULL", "0", $sqlalertstock) . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . "))"; } else { - $sql .= " ".$sqlalertstock." >= 0 AND (".$sqlalertstock." > SUM(".$db->ifsql("s.reel IS NULL", "0", "s.reel").'))'; + $sql .= " " . $sqlalertstock . " >= 0 AND (" . $sqlalertstock . " > SUM(" . $db->ifsql("s.reel IS NULL", "0", "s.reel") . '))'; } $sql .= ')'; $alertchecked = 'checked'; @@ -562,11 +588,11 @@ $head = array(); -$head[0][0] = DOL_URL_ROOT.'/product/stock/replenish.php'; +$head[0][0] = DOL_URL_ROOT . '/product/stock/replenish.php'; $head[0][1] = $title; $head[0][2] = 'replenish'; -$head[1][0] = DOL_URL_ROOT.'/product/stock/replenishorders.php'; +$head[1][0] = DOL_URL_ROOT . '/product/stock/replenishorders.php'; $head[1][1] = $langs->trans("ReplenishmentOrders"); $head[1][2] = 'replenishorders'; @@ -575,48 +601,48 @@ print dol_get_fiche_head($head, 'replenish', '', -1, ''); -print ''.$langs->trans("ReplenishmentStatusDesc").''."\n"; +print '' . $langs->trans("ReplenishmentStatusDesc") . '' . "\n"; //$link = ''.$langs->trans("MenuNewWarehouse").''; if (empty($fk_entrepot) && !empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { - print ''.$langs->trans("ReplenishmentStatusDescPerWarehouse").''."\n"; + print '' . $langs->trans("ReplenishmentStatusDescPerWarehouse") . '' . "\n"; } print '

    '; if ($usevirtualstock == 1) { - print $langs->trans("CurentSelectionMode").': '; - print ''.$langs->trans("UseVirtualStock").''; - print ' 0 ? '&fk_supplier='.$fk_supplier : '').($fk_entrepot > 0 ? '&fk_entrepot='.$fk_entrepot : '').'">'.$langs->trans("UsePhysicalStock").''; + print $langs->trans("CurentSelectionMode") . ': '; + print '' . $langs->trans("UseVirtualStock") . ''; + print ' 0 ? '&fk_supplier=' . $fk_supplier : '') . ($fk_entrepot > 0 ? '&fk_entrepot=' . $fk_entrepot : '') . '">' . $langs->trans("UsePhysicalStock") . ''; print '
    '; } if ($usevirtualstock == 0) { - print $langs->trans("CurentSelectionMode").': '; - print ' 0 ? '&fk_supplier='.$fk_supplier : '').($fk_entrepot > 0 ? '&fk_entrepot='.$fk_entrepot : '').'">'.$langs->trans("UseVirtualStock").''; - print ' '.$langs->trans("UsePhysicalStock").''; + print $langs->trans("CurentSelectionMode") . ': '; + print ' 0 ? '&fk_supplier=' . $fk_supplier : '') . ($fk_entrepot > 0 ? '&fk_entrepot=' . $fk_entrepot : '') . '">' . $langs->trans("UseVirtualStock") . ''; + print ' ' . $langs->trans("UsePhysicalStock") . ''; print '
    '; } -print '
    '."\n"; +print '
    ' . "\n"; -print '
    '; -print ''; +print ''; +print ''; print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; if ($limit > 0 && $limit != $conf->liste_limit) { - print ''; + print ''; } if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print '
    '; - print $langs->trans('Warehouse').' '.$formproduct->selectWarehouses($fk_entrepot, 'fk_entrepot', '', 1); + print $langs->trans('Warehouse') . ' ' . $formproduct->selectWarehouses($fk_entrepot, 'fk_entrepot', '', 1); print '
    '; } print '
    '; $filter = '(fournisseur:=:1)'; -print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', $filter, 1); +print $langs->trans('Supplier') . ' ' . $form->select_company($fk_supplier, 'fk_supplier', $filter, 1); print '
    '; $parameters = array(); @@ -626,63 +652,63 @@ } print '
    '; -print ''; +print ''; print '
    '; print '
    '; -print '
    '; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; print ''; -print ''; +print ''; if ($search_ref || $search_label || $sall || $salert || $draftorder || GETPOST('search', 'alpha')) { - $filters = '&search_ref='.urlencode($search_ref).'&search_label='.urlencode($search_label); - $filters .= '&sall='.urlencode($sall); - $filters .= '&salert='.urlencode($salert); - $filters .= '&draftorder='.urlencode($draftorder); - $filters .= '&mode='.urlencode($mode); + $filters = '&search_ref=' . urlencode($search_ref) . '&search_label=' . urlencode($search_label); + $filters .= '&sall=' . urlencode($sall); + $filters .= '&salert=' . urlencode($salert); + $filters .= '&draftorder=' . urlencode($draftorder); + $filters .= '&mode=' . urlencode($mode); if ($fk_supplier > 0) { - $filters .= '&fk_supplier='.urlencode($fk_supplier); + $filters .= '&fk_supplier=' . urlencode($fk_supplier); } if ($fk_entrepot > 0) { - $filters .= '&fk_entrepot='.urlencode($fk_entrepot); + $filters .= '&fk_entrepot=' . urlencode($fk_entrepot); } } else { - $filters = '&search_ref='.urlencode($search_ref).'&search_label='.urlencode($search_label); - $filters .= '&fourn_id='.urlencode($fourn_id); - $filters .= (isset($type) ? '&type='.urlencode($type) : ''); - $filters .= '&='.urlencode($salert); - $filters .= '&draftorder='.urlencode($draftorder); - $filters .= '&mode='.urlencode($mode); + $filters = '&search_ref=' . urlencode($search_ref) . '&search_label=' . urlencode($search_label); + $filters .= '&fourn_id=' . urlencode($fourn_id); + $filters .= (isset($type) ? '&type=' . urlencode($type) : ''); + $filters .= '&=' . urlencode($salert); + $filters .= '&draftorder=' . urlencode($draftorder); + $filters .= '&mode=' . urlencode($mode); if ($fk_supplier > 0) { - $filters .= '&fk_supplier='.urlencode($fk_supplier); + $filters .= '&fk_supplier=' . urlencode($fk_supplier); } if ($fk_entrepot > 0) { - $filters .= '&fk_entrepot='.urlencode($fk_entrepot); + $filters .= '&fk_entrepot=' . urlencode($fk_entrepot); } } if ($limit > 0 && $limit != $conf->liste_limit) { - $filters .= '&limit='.((int) $limit); + $filters .= '&limit=' . ((int) $limit); } -if (!empty($includeproductswithoutdesiredqty)) $filters .= '&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty); -if (!empty($salert)) $filters .= '&salert='.urlencode($salert); - -$param = (isset($type) ? '&type='.urlencode($type) : ''); -$param .= '&fourn_id='.urlencode($fourn_id).'&search_label='.urlencode($search_label).'&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty).'&salert='.urlencode($salert).'&draftorder='.urlencode($draftorder); -$param .= '&search_ref='.urlencode($search_ref); -$param .= '&mode='.urlencode($mode); -$param .= '&fk_supplier='.urlencode($fk_supplier); -$param .= '&fk_entrepot='.urlencode($fk_entrepot); -if (!empty($includeproductswithoutdesiredqty)) $param .= '&includeproductswithoutdesiredqty='.urlencode($includeproductswithoutdesiredqty); -if (!empty($salert)) $param .= '&salert='.urlencode($salert); +if (!empty($includeproductswithoutdesiredqty)) $filters .= '&includeproductswithoutdesiredqty=' . urlencode($includeproductswithoutdesiredqty); +if (!empty($salert)) $filters .= '&salert=' . urlencode($salert); + +$param = (isset($type) ? '&type=' . urlencode($type) : ''); +$param .= '&fourn_id=' . urlencode($fourn_id) . '&search_label=' . urlencode($search_label) . '&includeproductswithoutdesiredqty=' . urlencode($includeproductswithoutdesiredqty) . '&salert=' . urlencode($salert) . '&draftorder=' . urlencode($draftorder); +$param .= '&search_ref=' . urlencode($search_ref); +$param .= '&mode=' . urlencode($mode); +$param .= '&fk_supplier=' . urlencode($fk_supplier); +$param .= '&fk_entrepot=' . urlencode($fk_entrepot); +if (!empty($includeproductswithoutdesiredqty)) $param .= '&includeproductswithoutdesiredqty=' . urlencode($includeproductswithoutdesiredqty); +if (!empty($salert)) $param .= '&salert=' . urlencode($salert); $stocklabel = $langs->trans('Stock'); $stocklabelbis = $langs->trans('Stock'); @@ -695,8 +721,8 @@ $stocklabel = $langs->trans('PhysicalStock'); } if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { - $stocklabelbis = $stocklabel.' (Selected warehouse)'; - $stocklabel .= ' ('.$langs->trans("AllWarehouses").')'; + $stocklabelbis = $stocklabel . ' (Selected warehouse)'; + $stocklabel .= ' (' . $langs->trans("AllWarehouses") . ')'; } $texte = $langs->trans('Replenishment'); @@ -742,25 +768,25 @@ // Fields title search print ''; print ' '; -print ''; -print ''; +print ''; +print ''; if (isModEnabled("service") && $type == 1) { print ' '; } -print ''.$form->textwithpicto($langs->trans('IncludeEmptyDesiredStock'), $langs->trans('IncludeProductWithUndefinedAlerts')).' '; +print '' . $form->textwithpicto($langs->trans('IncludeEmptyDesiredStock'), $langs->trans('IncludeProductWithUndefinedAlerts')) . ' '; print ''; -print ''.$langs->trans('AlertOnly').' '; +print '' . $langs->trans('AlertOnly') . ' '; if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { print ' '; } print ''; if (!empty($conf->global->STOCK_REPLENISH_ADD_CHECKBOX_INCLUDE_DRAFT_ORDER)) { - print $langs->trans('IncludeAlsoDraftOrders').' '; + print $langs->trans('IncludeAlsoDraftOrders') . ' '; } print ''; print ' '; // Fields from hook -$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; @@ -789,7 +815,7 @@ print_liste_field_titre('SupplierRef', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right '); // Hook fields -$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; @@ -805,14 +831,14 @@ exit; } - $prod->load_stock('warehouseopen, warehouseinternal'.(!$usevirtualstock?', novirtual':''), $draftchecked); + $prod->load_stock('warehouseopen, warehouseinternal' . (!$usevirtualstock ? ', novirtual' : ''), $draftchecked); // Multilangs if (getDolGlobalInt('MAIN_MULTILANGS')) { $sql = 'SELECT label,description'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'product_lang'; - $sql .= ' WHERE fk_product = '.((int) $objp->rowid); - $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'"; + $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product_lang'; + $sql .= ' WHERE fk_product = ' . ((int) $objp->rowid); + $sql .= " AND lang = '" . $db->escape($langs->getDefaultLang()) . "'"; $sql .= ' LIMIT 1'; $resqlm = $db->query($sql); @@ -834,7 +860,9 @@ //TODO $stockwarehouse = $prod->stock_warehouse[$fk_entrepot]->; } else { $stock = $prod->stock_reel; - $stockwarehouse = $prod->stock_warehouse[$fk_entrepot]->real; + if (!empty($prod->stock_warehouse[$fk_entrepot])) { + $stockwarehouse = $prod->stock_warehouse[$fk_entrepot]->real; + } } // Force call prod->load_stats_xxx to choose status to count (otherwise it is loaded by load_stock function) @@ -859,11 +887,11 @@ $warning = ''; if ($alertstock && ($stock < $alertstock)) { - $warning = img_warning($langs->trans('StockTooLow')).' '; + $warning = img_warning($langs->trans('StockTooLow')) . ' '; } $warningwarehouse = ''; if ($alertstockwarehouse && ($stockwarehouse < $alertstockwarehouse)) { - $warningwarehouse = img_warning($langs->trans('StockTooLow')).' '; + $warningwarehouse = img_warning($langs->trans('StockTooLow')) . ' '; } //depending on conf, use either physical stock or @@ -896,58 +924,59 @@ print ''; // Select field - print ''; + print ''; - print ''.$prod->getNomUrl(1, 'stock').''; + print '' . $prod->getNomUrl(1, 'stock') . ''; - print ''; + print ''; print dol_escape_htmltag($objp->label); - print ''; // TODO Remove this and make a fetch to get description when creating order instead of a GETPOST + print ''; // TODO Remove this and make a fetch to get description when creating order instead of a GETPOST print ''; if (isModEnabled("service") && $type == 1) { $regs = array(); if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { - $duration = $regs[1].' '.$langs->trans('DurationYear'); + $duration = $regs[1] . ' ' . $langs->trans('DurationYear'); } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) { - $duration = $regs[1].' '.$langs->trans('DurationMonth'); + $duration = $regs[1] . ' ' . $langs->trans('DurationMonth'); } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) { - $duration = $regs[1].' '.$langs->trans('DurationDay'); + $duration = $regs[1] . ' ' . $langs->trans('DurationDay'); } else { $duration = $objp->duration; } - print ''.$duration.''; + print '' . $duration . ''; } // Desired stock - print ''.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $desiredstockwarehouse : $desiredstock).''; + print '' . ((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $desiredstockwarehouse : $desiredstock) . ''; // Limit stock for alert - print ''.((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $alertstockwarehouse : $alertstock).''; + print '' . ((!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $alertstockwarehouse : $alertstock) . ''; // Current stock (all warehouses) - print ''.$warning.$stock; - print ''; + print '' . $warning . $stock; + print ''; print ''; // Current stock (warehouse selected only) if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { - print ''.$warningwarehouse.$stockwarehouse.''; + print '' . $warningwarehouse . $stockwarehouse . ''; } // Already ordered - print ''.$ordered.' '.$picto.''; + print '' . $ordered . ' ' . $picto . ''; // To order - print ''; + $tobuy = (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) > 0 ? $stocktobuywarehouse : $stocktobuy; + print ''; // Supplier print ''; - print $form->select_product_fourn_price($prod->id, 'fourn'.$i, $fk_supplier); + print $form->select_product_fourn_price($prod->id, 'fourn' . $i, $fk_supplier); print ''; // Fields from hook - $parameters = array('objp'=>$objp); + $parameters = array('objp' => $objp, 'i' => $i, 'tobuy' => $tobuy); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; @@ -964,14 +993,14 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { $colspan++; } - print ''; + print ''; print ''; print $langs->trans("None"); print ''; print ''; } -$parameters = array('sql'=>$sql); +$parameters = array('sql' => $sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; @@ -984,7 +1013,7 @@ $value = $langs->trans("CreateOrders"); -print '
    '; +print '
    '; print '
    '; diff --git a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php index a2f6707ad4012..e5d0f8eb197ba 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php @@ -57,6 +57,15 @@ class StockTransfer extends CommonObject */ public $isextrafieldmanaged = 1; + /** + * @var int Name of subtable line + */ + public $table_element_line = 'stocktransfer_stocktransferline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + public $fk_element = 'fk_stocktransfer'; /** * @var array List of child tables. To know object to delete on cascade. diff --git a/htdocs/product/stock/stocktransfer/stocktransfer_card.php b/htdocs/product/stock/stocktransfer/stocktransfer_card.php index 5dade5dc87499..45d527925a3c0 100644 --- a/htdocs/product/stock/stocktransfer/stocktransfer_card.php +++ b/htdocs/product/stock/stocktransfer/stocktransfer_card.php @@ -39,6 +39,7 @@ $langs->loadLangs(array("stocks", "other", "productbatch", "companies")); if (isModEnabled('incoterm')) $langs->load('incoterm'); + // Get parameters $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -954,12 +955,12 @@ } } } elseif ($object->status == $object::STATUS_VALIDATED && $permissiontoadd) { - print ''.$langs->trans("StockTransferDecrementation").''; + print ''.$langs->trans("StockTransferDecrementation").''; } elseif ($object->status == $object::STATUS_TRANSFERED && $permissiontoadd) { - print ''.$langs->trans("StockTransferDecrementationCancel").''; - print ''.$langs->trans("StockTransferIncrementation").''; + print ''.$langs->trans("StockTransferDecrementationCancel").''; + print ''.$langs->trans("StockTransferIncrementation").''; } elseif ($object->status == $object::STATUS_CLOSED && $permissiontoadd) { - print ''.$langs->trans("StockTransferIncrementationCancel").''; + print ''.$langs->trans("StockTransferIncrementationCancel").''; } // Clone diff --git a/htdocs/product/traduction.php b/htdocs/product/traduction.php index 1544df1ca2ca1..8fc7c41569225 100644 --- a/htdocs/product/traduction.php +++ b/htdocs/product/traduction.php @@ -212,7 +212,7 @@ print dol_get_fiche_head($head, 'translation', $titre, 0, $picto); -$linkback = ''.$langs->trans("BackToList").''; +$linkback = ''.$langs->trans("BackToList").''; $shownav = 1; if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) { diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 5c323d0bfefd8..94f04c401fe5a 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -209,6 +209,8 @@ public function create($user, $notrigger = 0) // Clean parameters $this->label = trim($this->label); $this->description = trim($this->description); + $this->note_public = trim($this->note_public); + $this->note_private = trim($this->note_private); if (!empty($this->date_start) && !empty($this->date_end) && $this->date_start > $this->date_end) { $this->errors[] = $langs->trans('StartDateCannotBeAfterEndDate'); @@ -226,6 +228,8 @@ public function create($user, $notrigger = 0) $sql .= ", fk_task_parent"; $sql .= ", label"; $sql .= ", description"; + $sql .= ", note_public"; + $sql .= ", note_private"; $sql .= ", datec"; $sql .= ", fk_user_creat"; $sql .= ", dateo"; @@ -233,6 +237,7 @@ public function create($user, $notrigger = 0) $sql .= ", planned_workload"; $sql .= ", progress"; $sql .= ", budget_amount"; + $sql .= ", priority"; $sql .= ") VALUES ("; $sql .= (!empty($this->entity) ? (int) $this->entity : (int) $conf->entity); $sql .= ", ".((int) $this->fk_project); @@ -240,6 +245,8 @@ public function create($user, $notrigger = 0) $sql .= ", ".((int) $this->fk_task_parent); $sql .= ", '".$this->db->escape($this->label)."'"; $sql .= ", '".$this->db->escape($this->description)."'"; + $sql .= ", '".$this->db->escape($this->note_public)."'"; + $sql .= ", '".$this->db->escape($this->note_private)."'"; $sql .= ", '".$this->db->idate($now)."'"; $sql .= ", ".((int) $user->id); $sql .= ", ".($this->date_start ? "'".$this->db->idate($this->date_start)."'" : 'null'); @@ -247,6 +254,7 @@ public function create($user, $notrigger = 0) $sql .= ", ".(($this->planned_workload != '' && $this->planned_workload >= 0) ? ((int) $this->planned_workload) : 'null'); $sql .= ", ".(($this->progress != '' && $this->progress >= 0) ? ((int) $this->progress) : 'null'); $sql .= ", ".(($this->budget_amount != '' && $this->budget_amount >= 0) ? ((int) $this->budget_amount) : 'null'); + $sql .= ", ".(($this->priority != '' && $this->priority >= 0) ? (int) $this->priority : 'null'); $sql .= ")"; $this->db->begin(); @@ -426,6 +434,12 @@ public function update($user = null, $notrigger = 0) if (isset($this->description)) { $this->description = trim($this->description); } + if (isset($this->note_public)) { + $this->note_public = trim($this->note_public); + } + if (isset($this->note_private)) { + $this->note_private = trim($this->note_private); + } if (isset($this->duration_effective)) { $this->duration_effective = trim($this->duration_effective); } @@ -451,13 +465,16 @@ public function update($user = null, $notrigger = 0) $sql .= " fk_task_parent=".(isset($this->fk_task_parent) ? $this->fk_task_parent : "null").","; $sql .= " label=".(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").","; $sql .= " description=".(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").","; + $sql .= " note_public=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").","; + $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").","; $sql .= " duration_effective=".(isset($this->duration_effective) ? $this->duration_effective : "null").","; $sql .= " planned_workload=".((isset($this->planned_workload) && $this->planned_workload != '') ? $this->planned_workload : "null").","; $sql .= " dateo=".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null').","; $sql .= " datee=".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null').","; $sql .= " progress=".(($this->progress != '' && $this->progress >= 0) ? $this->progress : 'null').","; $sql .= " budget_amount=".(($this->budget_amount != '' && $this->budget_amount >= 0) ? $this->budget_amount : 'null').","; - $sql .= " rang=".((!empty($this->rang)) ? $this->rang : "0"); + $sql .= " rang=".((!empty($this->rang)) ? ((int) $this->rang) : "0").","; + $sql .= " priority=".((!empty($this->priority)) ? ((int) $this->priority) : "0"); $sql .= " WHERE rowid=".((int) $this->id); $this->db->begin(); @@ -858,6 +875,7 @@ public function initAsSpecimen() $this->duration_effective = ''; $this->fk_user_creat = null; $this->progress = '25'; + $this->priority = 0; $this->fk_statut = null; $this->note = 'This is a specimen task not'; } @@ -900,9 +918,9 @@ public function getTasksArray($usert = null, $userp = null, $projectid = 0, $soc } $sql .= " p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus, p.usage_bill_time,"; $sql .= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,"; - $sql .= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang,"; - $sql .= " t.description, "; - $sql .= " t.budget_amount, "; + $sql .= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang, t.priority,"; + $sql .= " t.budget_amount,"; + $sql .= " t.note_public, t.note_private,"; $sql .= " s.rowid as thirdparty_id, s.nom as thirdparty_name, s.email as thirdparty_email,"; $sql .= " p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount as project_budget_amount"; if ($loadextras) { // TODO Replace this with a fetch_optionnal() on the project after the fetch_object of line. @@ -1013,9 +1031,9 @@ public function getTasksArray($usert = null, $userp = null, $projectid = 0, $soc $sql .= " GROUP BY p.rowid, p.ref, p.title, p.public, p.fk_statut, p.usage_bill_time,"; $sql .= " t.datec, t.dateo, t.datee, t.tms,"; $sql .= " t.rowid, t.ref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut,"; - $sql .= " t.dateo, t.datee, t.planned_workload, t.rang,"; - $sql .= " t.description, "; - $sql .= " t.budget_amount, "; + $sql .= " t.dateo, t.datee, t.planned_workload, t.rang, t.priority,"; + $sql .= " t.budget_amount,"; + $sql .= " t.note_public, t.note_private,"; $sql .= " s.rowid, s.nom, s.email,"; $sql .= " p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount"; if ($loadextras) { @@ -1082,7 +1100,10 @@ public function getTasksArray($usert = null, $userp = null, $projectid = 0, $soc $tasks[$i]->label = $obj->label; $tasks[$i]->description = $obj->description; + $tasks[$i]->fk_task_parent = $obj->fk_task_parent; + $tasks[$i]->note_public = $obj->note_public; + $tasks[$i]->note_private = $obj->note_private; $tasks[$i]->duration_effective = $obj->duration_effective; $tasks[$i]->planned_workload = $obj->planned_workload; @@ -1098,6 +1119,7 @@ public function getTasksArray($usert = null, $userp = null, $projectid = 0, $soc $tasks[$i]->date_start = $this->db->jdate($obj->date_start); $tasks[$i]->date_end = $this->db->jdate($obj->date_end); $tasks[$i]->rang = $obj->rang; + $tasks[$i]->priority = $obj->priority; $tasks[$i]->socid = $obj->thirdparty_id; // For backward compatibility $tasks[$i]->thirdparty_id = $obj->thirdparty_id; @@ -1955,6 +1977,7 @@ public function createFromClone(User $user, $fromid, $project_id, $parent_task_i $clone_task->date_c = $datec; $clone_task->planned_workload = $origin_task->planned_workload; $clone_task->rang = $origin_task->rang; + $clone_task->priority = $origin_task->priority; //Manage Task Date if ($clone_change_dt) { diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index a4ab7a26393e0..614d9d3c39f18 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -1278,8 +1278,8 @@ $filedir = $conf->fournisseur->commande->multidir_output[$element->entity].'/'.dol_sanitizeFileName($element->ref); } elseif ($element_doc === 'invoice_supplier') { $element_doc = 'facture_fournisseur'; - $filename = get_exdir($element->id, 2, 0, 0, $element, 'product').dol_sanitizeFileName($element->ref); - $filedir = $conf->fournisseur->facture->multidir_output[$element->entity].'/'.get_exdir($element->id, 2, 0, 0, $element, 'invoice_supplier').dol_sanitizeFileName($element->ref); + $filename = get_exdir($element->id, 2, 0, 0, $element, 'invoice_supplier').dol_sanitizeFileName($element->ref); + $filedir = $conf->fournisseur->facture->multidir_output[$element->entity].'/'.$filename; } print '
    '; diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 58995267410f3..57959a53398b8 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -499,8 +499,9 @@ if (getDolGlobalInt('PROJECT_USE_REAL_COST_FOR_TIME_INVOICING')) { // We set unit price to 0 to force the use of the rate saved during recording $pu_ht = 0; - } else { + } elseif ($idprod <= 0) { // We want to sell all the time spent with the last hourly rate of user + // -> but what about choice user selected ? add idprod test $pu_ht = $fuser->thm; } @@ -520,7 +521,7 @@ $localtax2line = $localtax2; // If a particular product/service was defined for the task - if (!empty($fk_product) && $fk_product !== $idprod) { + if (!empty($fk_product) && ($fk_product > 0) && ($fk_product !== $idprod)) { if (!array_key_exists($fk_product, $product_data_cache)) { $result = $tmpproduct->fetch($fk_product); if ($result < 0) { @@ -661,7 +662,7 @@ // Update lineid into line of timespent $sql = 'UPDATE '.MAIN_DB_PREFIX.'element_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); - $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).') AND fk_user = '.((int) $userid); + $sql .= ' WHERE rowid = '.((int) $timespent_id).' AND fk_user = '.((int) $userid); $result = $db->query($sql); if (!$result) { $error++; diff --git a/htdocs/public/demo/index.php b/htdocs/public/demo/index.php index c71f1d86dc703..e8563e4a9d736 100644 --- a/htdocs/public/demo/index.php +++ b/htdocs/public/demo/index.php @@ -134,7 +134,6 @@ $modules = array(); $orders = array(); $categ = array(); -$dirmod = array(); $i = 0; // is a sequencer of modules found $j = 0; // j is module number. Automatically affected if module number not defined. @@ -174,7 +173,6 @@ $filename[$i] = $modName; $orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module //print "x".$modName." ".$orders[$i]."\n
    "; - $dirmod[$i] = $dirroot; $j++; $i++; } diff --git a/htdocs/public/project/new.php b/htdocs/public/project/new.php index bd8ccd0790188..76b4333010bf9 100644 --- a/htdocs/public/project/new.php +++ b/htdocs/public/project/new.php @@ -211,7 +211,7 @@ function llxFooterVierge() if (!$error) { // Search thirdparty and set it if found to the new created project - $result = $thirdparty->fetch(0, '', '', '', '', '', '', '', '', '', $object->email); + $result = $thirdparty->fetch(0, '', '', '', '', '', '', '', '', '', GETPOST('email')); if ($result > 0) { $proj->socid = $thirdparty->id; } else { diff --git a/htdocs/public/ticket/ajax/ajax.php b/htdocs/public/ticket/ajax/ajax.php index b2c3c153f54b5..24d5c693109cb 100644 --- a/htdocs/public/ticket/ajax/ajax.php +++ b/htdocs/public/ticket/ajax/ajax.php @@ -61,7 +61,7 @@ httponly_accessforbidden('Module Ticket not enabled'); } -if (empty($conf->global->TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST)) { +if (!getDolGlobalString('TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST')) { httponly_accessforbidden('Option TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST of module ticket is not enabled'); } diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php index 464f43cb1a77d..b4ca44d896bd9 100644 --- a/htdocs/public/ticket/create_ticket.php +++ b/htdocs/public/ticket/create_ticket.php @@ -110,7 +110,7 @@ // Add file in email form if (empty($reshook)) { if ($cancel) { - $backtopage = DOL_URL_ROOT.'/public/ticket/index.php'; + $backtopage = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', DOL_URL_ROOT.'/public/ticket/'); header("Location: ".$backtopage); exit; @@ -391,7 +391,7 @@ $message = ($conf->global->TICKET_MESSAGE_MAIL_NEW ? $conf->global->TICKET_MESSAGE_MAIL_NEW : $langs->transnoentities('TicketNewEmailBody')).'

    '; $message .= $langs->transnoentities('TicketNewEmailBodyInfosTicket').'
    '; - $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; + $url_public_ticket = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/', 2)).'view.php?track_id='.$object->track_id; $infos_new_ticket = $langs->transnoentities('TicketNewEmailBodyInfosTrackId', ''.$object->track_id.'').'
    '; $infos_new_ticket .= $langs->transnoentities('TicketNewEmailBodyInfosTrackUrl').'

    '; @@ -483,6 +483,9 @@ } } } +if (!empty($object->errors) || !empty($object->error)) { + setEventMessages($object->error, $object->errors, 'errors'); +} /* @@ -499,7 +502,8 @@ } $arrayofjs = array(); -$arrayofcss = array('/opensurvey/css/style.css', '/ticket/css/styles.css.php'); + +$arrayofcss = array('/opensurvey/css/style.css', getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', '/ticket/').'css/styles.css.php'); llxHeaderTicket($langs->trans("CreateTicket"), "", 0, 0, $arrayofjs, $arrayofcss); diff --git a/htdocs/public/ticket/index.php b/htdocs/public/ticket/index.php index 70f0b027559bf..c985b92b0f44d 100644 --- a/htdocs/public/ticket/index.php +++ b/htdocs/public/ticket/index.php @@ -71,12 +71,12 @@ $form = new Form($db); $formticket = new FormTicket($db); -if (empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) { +if (!getDolGlobalString('TICKET_ENABLE_PUBLIC_INTERFACE')) { print $langs->trans('TicketPublicInterfaceForbidden'); exit; } $arrayofjs = array(); -$arrayofcss = array('/ticket/css/styles.css.php'); +$arrayofcss = array(getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', '/ticket/').'css/styles.css.php'); llxHeaderTicket($langs->trans("Tickets"), "", 0, 0, $arrayofjs, $arrayofcss); @@ -85,8 +85,10 @@ print '

    '.(getDolGlobalString("TICKET_PUBLIC_TEXT_HOME", ''.$langs->trans("TicketPublicDesc")).'

    ').'

    '; print '
    '; +$baseurl = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', DOL_URL_ROOT.'/public/ticket/'); + print '
    '; -print '

    '.dol_escape_htmltag($langs->trans("CreateTicket")).'
    '; +print '

    '.dol_escape_htmltag($langs->trans("CreateTicket")).'
    '; print '

    '.dol_escape_htmltag($langs->trans("ViewMyTicketList")).'
    '; print '
    '.img_picto('', 'ticket', 'class="fa-15"').'
    '.dol_escape_htmltag($langs->trans("ShowTicketWithTrackId")).'
    '; print '
    '; diff --git a/htdocs/public/ticket/list.php b/htdocs/public/ticket/list.php index 005c671fd431f..035e66d973178 100644 --- a/htdocs/public/ticket/list.php +++ b/htdocs/public/ticket/list.php @@ -69,10 +69,10 @@ unset($_SESSION['track_id_customer']); unset($_SESSION['email_customer']); } -if (isset($_SESSION['track_id_customer'])) { +if (empty($track_id) && isset($_SESSION['track_id_customer'])) { $track_id = $_SESSION['track_id_customer']; } -if (isset($_SESSION['email_customer'])) { +if (empty($email) && isset($_SESSION['email_customer'])) { $email = strtolower($_SESSION['email_customer']); } @@ -92,7 +92,7 @@ */ if ($cancel) { - $backtopage = DOL_URL_ROOT.'/public/ticket/index.php'; + $backtopage = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', DOL_URL_ROOT.'/public/ticket/'); header("Location: ".$backtopage); exit; @@ -181,14 +181,14 @@ $user_create = new User($db); $formTicket = new FormTicket($db); -if (!$conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) { +if (!getDolGlobalString('TICKET_ENABLE_PUBLIC_INTERFACE')) { print '
    '.$langs->trans('TicketPublicInterfaceForbidden').'
    '; $db->close(); exit(); } $arrayofjs = array(); -$arrayofcss = array('/ticket/css/styles.css.php'); +$arrayofcss = array(getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', '/ticket/').'css/styles.css.php'); llxHeaderTicket($langs->trans("Tickets"), "", 0, 0, $arrayofjs, $arrayofcss); @@ -209,6 +209,7 @@ // Store current page url $url_page_current = dol_buildpath('/public/ticket/list.php', 1); + $contextpage = $url_page_current; // Do we click on purge search criteria ? if (GETPOST("button_removefilter_x")) { @@ -259,14 +260,14 @@ //'t.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), ); - if (empty($conf->global->TICKET_SHOW_PROGRESSION)) + if (!getDolGlobalString('TICKET_SHOW_PROGRESSION')) unset($arrayfields['t.progress']); // Extra fields if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate') { - $enabled = abs(dol_eval($extrafields->attributes[$object->table_element]['list'][$key], 1, 1, 0)); + $enabled = abs((int) dol_eval($extrafields->attributes[$object->table_element]['list'][$key], 1, 1, 0)); $enabled = (($enabled == 0 || $enabled == 3) ? 0 : $enabled); $arrayfields["ef.".$key] = array('label' => $extrafields->attributes[$object->table_element]['label'][$key], 'checked' => ($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1, 'position' => $extrafields->attributes[$object->table_element]['pos'][$key], 'enabled' => $enabled && $extrafields->attributes[$object->table_element]['perms'][$key]); } @@ -347,7 +348,7 @@ $sql .= " t.message,"; $sql .= " t.fk_statut,"; $sql .= " t.resolution,"; - if (!empty($conf->global->TICKET_SHOW_PROGRESSION)) + if (getDolGlobalString('TICKET_SHOW_PROGRESSION')) $sql .= " t.progress,"; $sql .= " t.timing,"; $sql .= " t.type_code,"; @@ -479,7 +480,7 @@ print ''; } - if ((!empty($conf->global->TICKET_SHOW_PROGRESSION)) && !empty($arrayfields['t.progress']['checked'])) { + if (getDolGlobalString('TICKET_SHOW_PROGRESSION') && !empty($arrayfields['t.progress']['checked'])) { print ''; } @@ -544,7 +545,7 @@ if (!empty($arrayfields['severity.code']['checked'])) { print_liste_field_titre($arrayfields['severity.code']['label'], $url_page_current, 'severity.code', '', $param, '', $sortfield, $sortorder); } - if ((!empty($conf->global->TICKET_SHOW_PROGRESSION)) && !empty($arrayfields['t.progress']['checked'])) { + if (getDolGlobalString('TICKET_SHOW_PROGRESSION') && !empty($arrayfields['t.progress']['checked'])) { print_liste_field_titre($arrayfields['t.progress']['label'], $url_page_current, 't.progress', '', $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['t.fk_user_create']['checked'])) { @@ -636,7 +637,7 @@ } // Progression - if ((!empty($conf->global->TICKET_SHOW_PROGRESSION)) && !empty($arrayfields['t.progress']['checked'])) { + if (getDolGlobalString('TICKET_SHOW_PROGRESSION') && !empty($arrayfields['t.progress']['checked'])) { print ''; print $obj->progress; print ''; @@ -710,7 +711,9 @@ print ''; - print '
    diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index f6634e8f5521d..d2d921886629e 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -196,8 +196,9 @@ function fail($message) if ($invoice->total_ttc < 0) { $invoice->type = $invoice::TYPE_CREDIT_NOTE; - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE"; - $sql .= " fk_soc = ".((int) $invoice->socid); + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture"; + $sql .= " WHERE entity IN (".getEntity('invoice').")"; + $sql .= " AND fk_soc = ".((int) $invoice->socid); $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE; $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED; $sql .= " ORDER BY rowid DESC"; @@ -471,7 +472,10 @@ function fail($message) // If we add a line and no invoice yet, we create the invoice if (($action == "addline" || $action == "freezone") && $placeid == 0) { $invoice->socid = getDolGlobalString($constforcompanyid); - $invoice->date = dol_now('tzuserrel'); // We use the local date, only the day will be saved. + + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + $invoice->date = dol_get_first_hour(dol_now('tzuserrel')); // Invoice::create() needs a date with no hours + $invoice->module_source = 'takepos'; $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ; $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity; @@ -669,7 +673,8 @@ function fail($message) $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"]; $sql .= " SET fk_soc = ".((int) $conf->global->$varforconst).", "; $sql .= " datec = '".$db->idate(dol_now())."'"; - $sql .= " WHERE ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'"; + $sql .= " WHERE entity IN (".getEntity('invoice').")"; + $sql .= " AND ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'"; $resql1 = $db->query($sql); if ($resdeletelines && $resql1) { @@ -1168,14 +1173,14 @@ function SetNote() { global->TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED)) { // By default, only invoices with a ref not already defined can in list of open invoice we can edit. - $sql .= " WHERE ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%' AND entity IN (".getEntity('invoice').")"; + $sql .= " AND ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%'"; } else { // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined - $sql .= " WHERE pos_source = '".$db->escape($_SESSION["takeposterminal"])."'"; + $sql .= " AND pos_source = '".$db->escape($_SESSION["takeposterminal"])."'"; $sql .= " AND module_source = 'takepos'"; - $sql .= " AND entity IN (".getEntity('invoice').")"; } $sql .= $db->order('datec', 'ASC'); diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index f2e58f98573ac..84b62ebf42ee8 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -149,7 +149,9 @@ function fetchConnectionToken() { if ($invoiceid > 0) { $invoice->fetch($invoiceid); } else { - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'"; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture"; + $sql .= " WHERE entity IN (".getEntity('invoice').")"; + $sql .= " AND ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'"; $resql = $db->query($sql); $obj = $db->fetch_object($resql); if ($obj) { @@ -248,6 +250,7 @@ function fetchConnectionToken() { } } } + ?> +currency != $_SESSION["takeposcustomercurrency"]) { + //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency + $showothercurrency = 1; + include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php'; + $multicurrency = new MultiCurrency($db); + $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]); +} +?> +
    - trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?> + trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $conf->currency); + if ($showothercurrency) { + print '   (' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')'; + } + ?>
    total_ttc) { ?>
    - trans('RemainToPay'); ?>: multicurrency_code); ?> + trans('RemainToPay'); ?>: multicurrency_code); + if ($showothercurrency) { + print '   (' . price($remaintopay * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')'; + } + ?>
    - trans("Received"); ?>: multicurrency_code); ?> + trans("Received"); ?>: multicurrency_code); + if ($showothercurrency) { + print '   (' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')'; + } + ?>
    - trans("Change"); ?>: multicurrency_code); ?> + trans("Change"); ?>: multicurrency_code); + if ($showothercurrency) { + print '   (' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')'; + } + ?>
    global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) { diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index c6bdc2360dd2c..4ee2d59f8a95b 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5070,7 +5070,9 @@ .ui-dialog.ui-corner-all.ui-widget.ui-widget-content.ui-front.ui-draggable { z-index: 1005 !important; /* Default 101 with ui-jquery, top menu have a z-index of 1000 */ } - +.ui-menu.ui-widget.ui-widget-content.ui-autocomplete.ui-front { + z-index:1006 !important; /* To always be over the dialog box */ +} /* ============================================================================== */ /* For content of image preview */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index d1012802c15b7..a1ca45245ac03 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -354,7 +354,7 @@ --amountremaintopaybackcolor:none; --productlinestockod: #002200; --productlinestocktoolow: #884400; - --infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #2b2d2f, #2b2d2f, #2b2d2f, #e4efe8); + --infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #fff, #fff, #fff, #e4efe8); --tablevalidbgcolor: rgb(252, 248, 227); --butactionbg : #; --textbutaction : #; diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index 39d25c3a21547..e78bb60779894 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -99,7 +99,7 @@ accessforbidden(); } // or for unauthorized internals users -if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { +if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { accessforbidden(); } @@ -147,7 +147,7 @@ $formticket = new FormTicket($db); $title = $langs->trans("Ticket").' - '.$object->ref.' '.$object->name; -if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/ticketnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { +if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/ticketnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Info"); } $help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|DE:Modul_Terminplanung'; @@ -165,7 +165,7 @@ print dol_get_fiche_end(); } -if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { +if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id); } elseif ($user->socid > 0) { $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid); diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 1e2c849060dd5..265a661448d2a 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -212,7 +212,8 @@ $db->begin(); $getRef = GETPOST("ref", 'alphanohtml'); - if ($object->fetch('', $getRef) > 0) { + $refcheck_object = new Ticket($db); + if ($refcheck_object->fetch('', $getRef) > 0) { $object->ref = $object->getDefaultRef(); $object->track_id = null; setEventMessage($langs->trans('TicketRefAlreadyUsed', $getRef, $object->ref)); @@ -274,14 +275,14 @@ } // Auto mark as read if created from backend - if (!empty($conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND) && $user->rights->ticket->write) { + if (getDolGlobalString('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND') && $user->rights->ticket->write) { if ( ! $object->markAsRead($user) > 0) { setEventMessages($object->error, $object->errors, 'errors'); } } // Auto assign user - if (!empty($conf->global->TICKET_AUTO_ASSIGN_USER_CREATE)) { + if (getDolGlobalString('TICKET_AUTO_ASSIGN_USER_CREATE')) { $result = $object->assignUser($user, $user->id, 1); $object->add_contact($user->id, "SUPPORTTEC", 'internal'); } @@ -742,7 +743,7 @@ $formticket->withfromsocid = $socid ? $socid : $user->socid; $formticket->withfromcontactid = $contactid ? $contactid : ''; $formticket->withtitletopic = 1; - $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (empty($conf->global->TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION) ? 0 : 1)); + $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0)); $formticket->withusercreate = 0; $formticket->withref = 1; $formticket->fk_user_create = $user->id; @@ -808,7 +809,7 @@ || $action == 'editsubject' || $action == 'edit_extras' || $action == 'update_extras' || $action == 'edit_extrafields' || $action == 'set_extrafields' || $action == 'classify' || $action == 'sel_contract' || $action == 'edit_message_init' || $action == 'set_status' || $action == 'dellink') { if ($res > 0) { // or for unauthorized internals users - if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { + if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { accessforbidden('', 0, 1); } @@ -824,7 +825,7 @@ } // Default select all or no contact - $default = (!empty($conf->global->TICKET_NOTIFY_AT_CLOSING)) ? -2 : -3; + $default = (getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? -2 : -3); $formquestion = array( array( 'name' => 'contactid', @@ -930,7 +931,7 @@ print dol_get_fiche_end(); } - if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { + if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id); } elseif ($user->socid > 0) { $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid); @@ -1142,7 +1143,7 @@ print ''; print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1); print ''; - print $foundinter ? convertSecondToTime($timing, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY) : ''; + print $foundinter ? convertSecondToTime($timing, 'all', getDolGlobalString('MAIN_DURATION_OF_WORKDAY')) : ''; print ''; } @@ -1289,7 +1290,7 @@ } - if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { + if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) { print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png'); print '
    '; @@ -1335,7 +1336,7 @@ echo $companystatic->getNomUrl(-1); } if ($tab[$i]['socid'] < 0) { - echo $conf->global->MAIN_INFO_SOCIETE_NOM; + echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM'); } if (!$tab[$i]['socid']) { echo ' '; @@ -1537,7 +1538,7 @@ } // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab) - if (!empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) { + if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) { $param = '&id='.$object->id; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.$contextpage; @@ -1590,7 +1591,7 @@ print showDirectPublicLink($object).'
    '; print '
    '; - if (empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) { + if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) { print '
    '; $MAXEVENT = 10; diff --git a/htdocs/ticket/class/actions_ticket.class.php b/htdocs/ticket/class/actions_ticket.class.php index cc0a02dd29426..d1ade28f68f59 100644 --- a/htdocs/ticket/class/actions_ticket.class.php +++ b/htdocs/ticket/class/actions_ticket.class.php @@ -212,7 +212,7 @@ public function viewTicketOriginalMessage($user, $action, $object) $msg = GETPOSTISSET('message_initial') ? GETPOST('message_initial', 'restricthtml') : $object->message; include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $uselocalbrowser = true; - $ckeditorenabledforticket = $conf->global->FCKEDITOR_ENABLE_TICKET; + $ckeditorenabledforticket = getDolGlobalString('FCKEDITOR_ENABLE_TICKET'); $doleditor = new DolEditor('message_initial', $msg, '100%', 250, 'dolibarr_details', 'In', true, $uselocalbrowser, $ckeditorenabledforticket, ROWS_9, '95%'); $doleditor->Create(); } else { diff --git a/htdocs/ticket/class/cticketcategory.class.php b/htdocs/ticket/class/cticketcategory.class.php index f10309d08caba..7f55f11928e56 100644 --- a/htdocs/ticket/class/cticketcategory.class.php +++ b/htdocs/ticket/class/cticketcategory.class.php @@ -73,7 +73,7 @@ class CTicketCategory extends CommonObject * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. * 'picto' is code of a picto to show before value in forms - * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString('MY_SETUP_PARAM')) * 'position' is the sort order of field. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) @@ -186,7 +186,7 @@ public function __construct(DoliDB $db) $this->db = $db; - if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { + if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) { $this->fields['rowid']['visible'] = 0; } if (!isModEnabled('multicompany') && isset($this->fields['entity'])) { @@ -530,7 +530,7 @@ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss $linkclose = ''; if (empty($notooltip)) { - if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { $label = $langs->trans("ShowMyObject"); $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; } diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 601806e023b6b..6d1ee87f93e8c 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -272,7 +272,7 @@ class Ticket extends CommonObject * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. * 'picto' is code of a picto to show before value in forms - * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString('MY_SETUP_PARAM')) * 'position' is the sort order of field. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) @@ -542,7 +542,7 @@ public function create($user, $notrigger = 0) $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."ticket"); } - if (!$error && !empty($conf->global->TICKET_ADD_AUTHOR_AS_CONTACT)) { + if (!$error && getDolGlobalString('TICKET_ADD_AUTHOR_AS_CONTACT')) { // add creator as contributor if ($this->add_contact($user->id, 'CONTRIBUTOR', 'internal') < 0) { $error++; @@ -992,7 +992,7 @@ public function update($user = 0, $notrigger = 0) $sql .= " fk_user_assign=".(isset($this->fk_user_assign) ? $this->fk_user_assign : "null").","; $sql .= " subject=".(isset($this->subject) ? "'".$this->db->escape($this->subject)."'" : "null").","; $sql .= " message=".(isset($this->message) ? "'".$this->db->escape($this->message)."'" : "null").","; - $sql .= " fk_statut=".(isset($this->fk_statut) ? $this->fk_statut : "null").","; + $sql .= " fk_statut=".(isset($this->fk_statut) ? $this->fk_statut : "0").","; $sql .= " resolution=".(isset($this->resolution) ? $this->resolution : "null").","; $sql .= " progress=".(isset($this->progress) ? "'".$this->db->escape($this->progress)."'" : "null").","; $sql .= " timing=".(isset($this->timing) ? "'".$this->db->escape($this->timing)."'" : "null").","; @@ -1530,7 +1530,7 @@ public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss $linkclose = ''; if (empty($notooltip)) { - if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { $label = $langs->trans("ShowTicket"); $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; } @@ -1575,6 +1575,8 @@ public function markAsRead($user, $notrigger = 0) $this->oldcopy = dol_clone($this); $this->db->begin(); + $oldStatus = $this->fk_statut; + $this->fk_statut = Ticket::STATUS_READ; $sql = "UPDATE ".MAIN_DB_PREFIX."ticket"; $sql .= " SET fk_statut = ".Ticket::STATUS_READ.", date_read = '".$this->db->idate(dol_now())."'"; @@ -1583,13 +1585,14 @@ public function markAsRead($user, $notrigger = 0) dol_syslog(get_class($this)."::markAsRead"); $resql = $this->db->query($sql); if ($resql) { - $this->actionmsg = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs)); - $this->actionmsg2 = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs)); + $this->context['actionmsg'] = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs)); + $this->context['actionmsg2'] = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs)); - if (!$error && !$notrigger) { + if (!$notrigger) { // Call trigger $result = $this->call_trigger('TICKET_MODIFY', $user); if ($result < 0) { + $this->fk_statut = $oldStatus; $error++; } // End call triggers @@ -1599,12 +1602,14 @@ public function markAsRead($user, $notrigger = 0) $this->db->commit(); return 1; } else { + $this->fk_statut = $oldStatus; $this->db->rollback(); - $this->error = join(',', $this->errors); + $this->error = implode(',', $this->errors); dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR); return -1; } } else { + $this->fk_statut = $oldStatus; $this->db->rollback(); $this->error = $this->db->lasterror(); dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR); @@ -1825,7 +1830,7 @@ public function close(User $user, $mode = 0) $error = 0; // Valid and close fichinter linked - if (isModEnabled('ficheinter') && !empty($conf->global->WORKFLOW_TICKET_CLOSE_INTERVENTION)) { + if (isModEnabled('ficheinter') && getDolGlobalString('WORKFLOW_TICKET_CLOSE_INTERVENTION')) { dol_syslog("We have closed the ticket, so we close all linked interventions"); $this->fetchObjectLinked($this->id, $this->element, null, 'fichinter'); if ($this->linkedObjectsIds) { @@ -2285,7 +2290,7 @@ public function getDefaultRef($thirdparty = '') global $conf; $defaultref = ''; - $modele = empty($conf->global->TICKET_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKET_ADDON; + $modele = getDolGlobalString('TICKET_ADDON', 'mod_ticket_simple'); // Search template files $file = ''; @@ -2547,7 +2552,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) * * Send emails to assigned users (public area notification) */ - if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ENABLED)) { + if (getDolGlobalString('TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ENABLED')) { // Retrieve internal contact datas $internal_contacts = $object->getInfosTicketInternalContact(1); @@ -2572,34 +2577,33 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) continue; } - if ($info_sendto['email'] != '') { - if (!empty($info_sendto['email'])) { - $sendto[] = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'])." <".$info_sendto['email'].">"; - } + // We check if the email address is not the assignee's address to prevent notification from being sent twice + if (!empty($info_sendto['email']) && $assigned_user->email != $info_sendto['email']) { + $sendto[] = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'])." <".$info_sendto['email'].">"; } } if (empty($sendto)) { - if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL)) { - $sendto[$conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL] = $conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL; - } elseif (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) { - $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO; + if (getDolGlobalString('TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL')) { + $sendto[getDolGlobalString('TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL')] = getDolGlobalString('TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL'); + } elseif (getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')) { + $sendto[getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'); } } // Add global email address recipient - if (!empty($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) && - !empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto) + if (getDolGlobalString('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS') && + getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO') && !array_key_exists(getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'), $sendto) ) { - $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO; + $sendto[getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'); } if (!empty($sendto)) { - $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; + $label_title = getDolGlobalString('MAIN_APPLICATION_TITLE', $mysoc->name); $subject = '['.$label_title.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage'); // Message send - $message = $langs->trans('TicketMessageMailIntroText'); + $message = getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO', $langs->trans('TicketMessageMailIntroText')); $message .= '

    '; $messagePost = GETPOST('message', 'restricthtml'); if (!dol_textishtml($messagePost)) { @@ -2644,14 +2648,14 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) $sendto = array(); if (is_array($internal_contacts) && count($internal_contacts) > 0) { // Set default subject - $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; + $label_title = getDolGlobalString('MAIN_APPLICATION_TITLE', $mysoc->name); $appli = $label_title; $subject = GETPOST('subject', 'alphanohtml') ? GETPOST('subject', 'alphanohtml') : '['.$appli.' - '.$langs->trans("Ticket").' #'.$object->track_id.'] '.$langs->trans('TicketNewMessage'); $message_intro = $langs->trans('TicketNotificationEmailBody', "#".$object->id); $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE'); - $message = $langs->trans('TicketMessageMailIntroText'); + $message = getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO', $langs->trans('TicketMessageMailIntroText')); $message .= '

    '; $messagePost = GETPOST('message', 'restricthtml'); if (!dol_textishtml($messagePost)) { @@ -2691,9 +2695,9 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) $message .= '
    '.$langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : '.$object->track_id.'
    '; // Add global email address recipient - if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) { - if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) { - $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO; + if (getDolGlobalString('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS') && !array_key_exists(getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'), $sendto)) { + if (getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')) { + $sendto[getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'); } } @@ -2725,7 +2729,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) $sendto = array(); if (is_array($external_contacts) && count($external_contacts) > 0) { // Get default subject for email to external contacts - $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; + $label_title = getDolGlobalString('MAIN_APPLICATION_TITLE', $mysoc->name); $appli = $mysoc->name; $subject = GETPOST('subject') ? GETPOST('subject') : '['.$appli.' - '.$langs->trans("Ticket").' #'.$object->track_id.'] '.$langs->trans('TicketNewMessage'); @@ -2763,8 +2767,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) } // If public interface is not enable, use link to internal page into mail - $url_public_ticket = (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) ? - (!empty($conf->global->TICKET_URL_PUBLIC_INTERFACE) ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)) : dol_buildpath('/ticket/card.php', 2)).'?track_id='.$object->track_id; + $url_public_ticket = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/view.php', 2)) . '/view.php?track_id='.$object->track_id; $message .= '
    '.$langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer').' : '.$object->track_id.'
    '; // Build final message @@ -2786,9 +2789,9 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) } // Add global email address recipient - if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) { - if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) { - $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO; + if (getDolGlobalString('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS') && !array_key_exists(getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'), $sendto)) { + if (getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')) { + $sendto[getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO')] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO'); } } @@ -2830,7 +2833,7 @@ public function newMessage($user, &$action, $private = 1, $public_area = 0) * * @param string $subject Email subject * @param string $message Email message - * @param int $send_internal_cc Receive a copy on internal email ($conf->global->TICKET_NOTIFICATION_EMAIL_FROM) + * @param int $send_internal_cc Receive a copy on internal email (getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM') * @param array $array_receiver Array of receiver. exemple array('name' => 'John Doe', 'email' => 'john@doe.com', etc...) * @param array $filename_list List of files to attach (full path of filename on file system) * @param array $mimetype_list List of MIME type of attached files @@ -2841,7 +2844,7 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = { global $conf, $langs; - if ($conf->global->TICKET_DISABLE_ALL_MAILS) { + if (getDolGlobalString('TICKET_DISABLE_ALL_MAILS')) { dol_syslog(get_class($this).'::sendTicketMessageByEmail: Emails are disable into ticket setup by option TICKET_DISABLE_ALL_MAILS', LOG_WARNING); return false; } @@ -2857,11 +2860,12 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = $array_receiver = array_merge($array_receiver, $this->getInfosTicketExternalContact(1)); } + $sendtocc = ""; if ($send_internal_cc) { - $sendtocc = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM; + $sendtocc = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM'); } - $from = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM; + $from = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM'); $is_sent = false; if (is_array($array_receiver) && count($array_receiver) > 0) { foreach ($array_receiver as $key => $receiver) { @@ -2874,7 +2878,7 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = $old_MAIN_MAIL_AUTOCOPY_TO = getDolGlobalString('MAIN_MAIL_AUTOCOPY_TO'); - if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { + if (getDolGlobalString('TICKET_DISABLE_MAIL_AUTOCOPY_TO')) { $conf->global->MAIN_MAIL_AUTOCOPY_TO = ''; } @@ -2885,10 +2889,12 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = $moreinheader = 'X-Dolibarr-Info: sendTicketMessageByEmail'."\r\n"; if (!empty($this->email_msgid)) { - $moreinheader .= 'References <'.$this->email_msgid.'>'."\r\n"; + // We must also add 1 entry In-Reply-To: <$this->email_msgid> with Message-ID we respond from (See RFC5322). + $moreinheader .= 'In-Reply-To: <'.$this->email_msgid.'>'."\r\n"; } $mailfile = new CMailFile($subject, $receiver, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', $trackid, $moreinheader, 'ticket', '', $upload_dir_tmp); + if ($mailfile->error) { setEventMessages($mailfile->error, null, 'errors'); } else { @@ -2907,7 +2913,7 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = } } - if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { + if (getDolGlobalString('TICKET_DISABLE_MAIL_AUTOCOPY_TO')) { $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO; } } diff --git a/htdocs/ticket/contact.php b/htdocs/ticket/contact.php index ba678ae2dca13..e2919e6d0c412 100644 --- a/htdocs/ticket/contact.php +++ b/htdocs/ticket/contact.php @@ -72,7 +72,7 @@ accessforbidden(); } // or for unauthorized internals users -if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { +if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { accessforbidden(); } @@ -194,7 +194,7 @@ print dol_get_fiche_end(); } - if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { + if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $object->next_prev_filter = "te.fk_user_assign ='".((int) $user->id); } elseif ($user->socid > 0) { $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid); diff --git a/htdocs/ticket/css/styles.css.php b/htdocs/ticket/css/styles.css.php index 2ebc3420a1449..5e3ec60d98ce9 100644 --- a/htdocs/ticket/css/styles.css.php +++ b/htdocs/ticket/css/styles.css.php @@ -65,7 +65,7 @@ html { global->TICKET_SHOW_MODULE_LOGO)) { +if (getDolGlobalString('TICKET_SHOW_MODULE_LOGO')) { print 'background: url("../public/img/bg_ticket.png") no-repeat 95% 90%;'; } ?> diff --git a/htdocs/ticket/document.php b/htdocs/ticket/document.php index 23e0b00882c12..9c5266d3e0172 100644 --- a/htdocs/ticket/document.php +++ b/htdocs/ticket/document.php @@ -87,7 +87,7 @@ accessforbidden(); } // or for unauthorized internals users -if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id && empty($user->rights->ticket->manage)) { +if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id && empty($user->rights->ticket->manage)) { accessforbidden(); } @@ -132,7 +132,7 @@ print dol_get_fiche_end(); } - if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { + if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id); } elseif ($user->socid > 0) { $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid); diff --git a/htdocs/ticket/index.php b/htdocs/ticket/index.php index 35e11b9f1f556..f7bd23137b470 100644 --- a/htdocs/ticket/index.php +++ b/htdocs/ticket/index.php @@ -57,7 +57,7 @@ $nowarray = dol_getdate(dol_now(), true); $nowyear = $nowarray['year']; $year = GETPOST('year', 'int') > 0 ? GETPOST('year', 'int') : $nowyear; -$startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS))); +$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS')))); $endyear = $year; // Initialize objects @@ -171,7 +171,7 @@ $sql .= " AND t.fk_soc= ".((int) $user->socid); } else { // For internals users, - if (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && !$user->rights->ticket->manage) { + if (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && !$user->rights->ticket->manage) { $sql .= " AND t.fk_user_assign = ".((int) $user->id); } } @@ -346,7 +346,7 @@ $sql .= " AND t.fk_soc= ".((int) $user->socid); } else { // Restricted to assigned user only - if (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && !$user->rights->ticket->manage) { + if (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && !$user->rights->ticket->manage) { $sql .= " AND t.fk_user_assign = ".((int) $user->id); } } diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index d0b25421b374b..704fa880adc9d 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -446,9 +446,9 @@ $sql .= " AND t.date_close <= '".$db->idate($search_dateclose_end)."'"; } -if (!$user->socid && ($mode == "mine" || (!$user->admin && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY))) { +if (!$user->socid && ($mode == "mine" || (!$user->admin && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')))) { $sql .= " AND (t.fk_user_assign = ".((int) $user->id); - if (empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { + if (!getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $sql .= " OR t.fk_user_create = ".((int) $user->id); } $sql .= ")"; @@ -497,7 +497,7 @@ $num = $db->num_rows($resql); // Direct jump if only one record found -if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { +if ($num == 1 && getDolGlobalString('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) { $obj = $db->fetch_object($resql); $id = $obj->rowid; header("Location: ".DOL_URL_ROOT.'/ticket/card.php?id='.$id); @@ -780,7 +780,7 @@ "name" => "massaction", "value" => "close" ]); - $selectedchoice = (!empty($conf->global->TICKET_NOTIFY_AT_CLOSING)) ? "yes" : "no"; + $selectedchoice = getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? "yes" : "no"; print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassTicketClosingSendEmail"), $langs->trans("ConfirmMassTicketClosingSendEmailQuestion"), 'confirm_send_close', $hidden_form, $selectedchoice, 0, 200, 500, 1); } @@ -1135,19 +1135,19 @@ // display a warning on untreated tickets $is_open = ($object->status != Ticket::STATUS_CLOSED && $object->status != Ticket::STATUS_CANCELED ); - $should_show_warning = (!empty($conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE) || !empty($conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE)); + $should_show_warning = (getDolGlobalString('TICKET_DELAY_SINCE_LAST_RESPONSE') || getDolGlobalString('TICKET_DELAY_BEFORE_FIRST_RESPONSE')); if ($is_open && $should_show_warning) { $date_last_msg_sent = (int) $object->date_last_msg_sent; $hour_diff = ($now - $date_last_msg_sent) / 3600 ; - if (!empty($conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE && $date_last_msg_sent == 0)) { + if (getDolGlobalString('TICKET_DELAY_BEFORE_FIRST_RESPONSE') && $date_last_msg_sent == 0) { $creation_date = $object->datec; $hour_diff_creation = ($now - $creation_date) / 3600 ; - if ($hour_diff_creation > $conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE) { - print " " . img_picto($langs->trans('Late') . ' : ' . $langs->trans('TicketsDelayForFirstResponseTooLong', $conf->global->TICKET_DELAY_BEFORE_FIRST_RESPONSE), 'warning', 'style="color: red;"', false, 0, 0, '', ''); + if ($hour_diff_creation > getDolGlobalString('TICKET_DELAY_BEFORE_FIRST_RESPONSE')) { + print " " . img_picto($langs->trans('Late') . ' : ' . $langs->trans('TicketsDelayForFirstResponseTooLong', getDolGlobalString('TICKET_DELAY_BEFORE_FIRST_RESPONSE')), 'warning', 'style="color: red;"', false, 0, 0, '', ''); } - } elseif (!empty($conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE) && $hour_diff > $conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE) { - print " " . img_picto($langs->trans('Late') . ' : ' . $langs->trans('TicketsDelayFromLastResponseTooLong', $conf->global->TICKET_DELAY_SINCE_LAST_RESPONSE), 'warning'); + } elseif (getDolGlobalString('TICKET_DELAY_SINCE_LAST_RESPONSE') && $hour_diff > getDolGlobalString('TICKET_DELAY_SINCE_LAST_RESPONSE')) { + print " " . img_picto($langs->trans('Late') . ' : ' . $langs->trans('TicketsDelayFromLastResponseTooLong', getDolGlobalString('TICKET_DELAY_SINCE_LAST_RESPONSE')), 'warning'); } } } else { // Example: key=fk_soc, obj->key=123 val=array('type'=>'integer', ... diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index e0926da74f0fd..a941e9adbf436 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -96,7 +96,7 @@ accessforbidden(); } // or for unauthorized internals users -if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { +if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { accessforbidden(); } @@ -144,7 +144,7 @@ $formticket = new FormTicket($db); $title = $langs->trans("Ticket").' - '.$object->ref.' '.$object->name; -if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/ticketnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { +if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/ticketnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Info"); } $help_url = 'FR:DocumentationModuleTicket'; @@ -161,7 +161,7 @@ print dol_get_fiche_end(); } -if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { +if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) { $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id); } elseif ($user->socid > 0) { $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid); diff --git a/htdocs/ticket/stats/index.php b/htdocs/ticket/stats/index.php index afc2a685048d7..b98fea75270ae 100644 --- a/htdocs/ticket/stats/index.php +++ b/htdocs/ticket/stats/index.php @@ -47,7 +47,7 @@ $nowyear = dol_print_date(dol_now('gmt'), "%Y", 'gmt'); $year = GETPOST('year') > 0 ? GETPOST('year', 'int') : $nowyear; -$startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS))); +$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS')))); $endyear = $year; // Load translation files required by the page diff --git a/htdocs/ticket/tpl/linkedobjectblock.tpl.php b/htdocs/ticket/tpl/linkedobjectblock.tpl.php index 4ba36894379d3..8fa875b8fb297 100644 --- a/htdocs/ticket/tpl/linkedobjectblock.tpl.php +++ b/htdocs/ticket/tpl/linkedobjectblock.tpl.php @@ -47,7 +47,7 @@ ?> trans("Ticket"); ?> - global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { + getNomUrl(0, '', 0, 1).'&action=selectlines" data-element="'.$objectlink->element.'" data-id="'.$objectlink->id.'" > diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 8123f89c2b139..3fdd83275dd41 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3686,7 +3686,7 @@ public function get_full_tree($deleteafterid = 0, $filter = '') } dol_syslog(get_class($this)."::get_full_tree dol_sort_array", LOG_DEBUG); - $this->users = dol_sort_array($this->users, 'fullname', 'asc', true, false); + $this->users = dol_sort_array($this->users, 'fullname', 'asc', true, false, 1); //var_dump($this->users); diff --git a/htdocs/user/group/list.php b/htdocs/user/group/list.php index d0998329fa0e6..33702c942bf4d 100644 --- a/htdocs/user/group/list.php +++ b/htdocs/user/group/list.php @@ -174,6 +174,9 @@ // Build and execute select // -------------------------------------------------------------------- $sql = "SELECT g.rowid, g.nom as name, g.note, g.entity, g.datec, g.tms, COUNT(DISTINCT ugu.fk_user) as nb, COUNT(DISTINCT ugr.fk_id) as nbpermissions"; + +$sqlfields = $sql; + $sql .= " FROM ".MAIN_DB_PREFIX."usergroup as g"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_usergroup = g.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_rights as ugr ON ugr.fk_usergroup = g.rowid"; @@ -190,11 +193,29 @@ } $sql .= " GROUP BY g.rowid, g.nom, g.note, g.entity, g.datec, g.tms"; +// Count total nb of records +$nbtotalofrecords = ''; +if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(DISTINCT g.rowid) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than paging size (filtering), goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + // Complete request and execute it with limit $sql .= $db->order($sortfield, $sortorder); -if ($limit) { - $sql .= $db->plimit($limit + 1, $offset); -} $resql = $db->query($sql); if (!$resql) { @@ -204,9 +225,6 @@ $num = $db->num_rows($resql); - -$nbtotalofrecords = $num; - $i = 0; diff --git a/htdocs/user/hierarchy.php b/htdocs/user/hierarchy.php index 5857c6257ac71..6706fce89648d 100644 --- a/htdocs/user/hierarchy.php +++ b/htdocs/user/hierarchy.php @@ -60,6 +60,7 @@ $search_statut = ""; } +$search_employee = -1; if ($contextpage == 'employeelist') { $search_employee = 1; } @@ -104,10 +105,24 @@ llxHeader('', $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss, '', 'bodyforlist'); - +$filters = []; +if (($search_statut != '' && $search_statut >= 0)) { + $filters[] = "statut = ".((int) $search_statut); +} +if (($search_employee != '' && $search_employee >= 0)) { + $filters[] = "employee = ".((int) $search_employee); +} +$sqlfilter= ''; +if (!empty($filters)) { + $sqlfilter = join(' AND ', $filters); +} // Load hierarchy of users -$user_arbo = $userstatic->get_full_tree(0, ($search_statut != '' && $search_statut >= 0) ? "statut = ".$search_statut : ''); - +$user_arbo_all = $userstatic->get_full_tree(0, ''); +if ($sqlfilter) { + $user_arbo = $userstatic->get_full_tree(0, $sqlfilter); +} else { + $user_arbo = $user_arbo_all; +} // Count total nb of records $nbtotalofrecords = count($user_arbo); @@ -121,7 +136,8 @@ //var_dump($fulltree); // Define data (format for treeview) $data = array(); - $data[] = array('rowid'=>0, 'fk_menu'=>-1, 'title'=>"racine", 'mainmenu'=>'', 'leftmenu'=>'', 'fk_mainmenu'=>'', 'fk_leftmenu'=>''); + $data[0] = array('rowid'=>0, 'fk_menu'=>-1, 'title'=>"racine", 'mainmenu'=>'', 'leftmenu'=>'', 'fk_mainmenu'=>'', 'fk_leftmenu'=>''); + foreach ($fulltree as $key => $val) { $userstatic->id = $val['id']; $userstatic->ref = $val['id']; @@ -159,15 +175,86 @@ $entry = '
    '.$li.''.$userstatic->getLibStatut(2).'
    '; - $data[] = array( + $data[$val['rowid']] = array( 'rowid'=>$val['rowid'], - 'fk_menu'=>$val['fk_user'], + 'fk_menu'=>$val['fk_user'], // TODO Replace fk_menu with fk_parent 'statut'=>$val['statut'], 'entry'=>$entry ); } - //var_dump($data); + // Loop on $data to link user linked to a parent that was excluded by the filter + foreach ($data as $key => $tmpdata) { + $idparent = $tmpdata['fk_menu']; + // Loop to check if parent exists + if ($idparent > 0) { + $parentfound = array_key_exists($idparent, $data) ? 1 : 0; + + $i = 0; + while (!$parentfound && $i < 50) { + // Parent was not found but we need it to show the child, so we reintroduce the parent + if (!empty($user_arbo_all[$idparent])) { + $val = $user_arbo_all[$idparent]; + $userstatic->id = $val['id']; + $userstatic->ref = $val['id']; + $userstatic->login = $val['login']; + $userstatic->firstname = $val['firstname']; + $userstatic->lastname = $val['lastname']; + $userstatic->statut = $val['statut']; + $userstatic->email = $val['email']; + $userstatic->gender = $val['gender']; + $userstatic->socid = $val['fk_soc']; + $userstatic->admin = $val['admin']; + $userstatic->entity = $val['entity']; + $userstatic->photo = $val['photo']; + + $li = ''; + $li .= $userstatic->getNomUrl(-1, '', 0, 1); + if (isModEnabled('multicompany') && $userstatic->admin && !$userstatic->entity) { + $li .= img_picto($langs->trans("SuperAdministrator"), 'redstar'); + } elseif ($userstatic->admin) { + $li .= img_picto($langs->trans("Administrator"), 'star'); + } + $li .= ' ('.$val['login'].($entitystring ? ' - '.$entitystring : '').')'; + $li .= ' - '.$langs->trans("ExcludedByFilter").''; + $li .= ''; + + $entry = '
    '.$li.''.$userstatic->getLibStatut(2).'
    '; + + $data[$idparent] = array( + 'rowid' => $idparent, + 'fk_menu' => $user_arbo_all[$idparent]['fk_user'], + 'statut' => $user_arbo_all[$idparent]['statut'], + 'entry' => $entry + ); + $idparent = $user_arbo_all[$idparent]['fk_user']; + if ($idparent > 0) { + $parentfound = array_key_exists($idparent, $data) ? 1 : 0; + } else { + $parentfound = 1; + } + //var_dump($data[$idparent]); + } else { + // We should not be here. If a record has a parent id, parent id should be into $user_arbo_all + $data[$key]['fk_menu'] = -2; + if (empty($data[-2])) { + $li = ''.$langs->trans("ParentIDDoesNotExistAnymore").''; + $entry = '
    '.$li.'
    '; + $data[-2] = array( + 'rowid'=>'-2', + 'fk_menu'=>null, + 'statut'=>'1', + 'entry'=>$entry + ); + } + $parentfound = 1; + } + + $i++; + } + } + } + //var_dump($data);exit; $param = "&search_statut=".urlencode($search_statut); $param = "&contextpage=".urlencode($contextpage); diff --git a/htdocs/user/list.php b/htdocs/user/list.php index c7a10b2c3cb45..e5ca8d9cf729e 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -1,9 +1,9 @@ - * Copyright (C) 2004-2021 Laurent Destailleur - * Copyright (C) 2005-2017 Regis Houssin - * Copyright (C) 2015 Alexandre Spangaro - * Copyright (C) 2016 Marcos García +/* Copyright (C) 2002-2005 Rodolphe Quiedeville + * Copyright (C) 2004-2021 Laurent Destailleur + * Copyright (C) 2005-2017 Regis Houssin + * Copyright (C) 2015-2024 Alexandre Spangaro + * Copyright (C) 2016 Marcos García * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -134,9 +134,9 @@ 'u.email'=>array('label'=>"EMail", 'checked'=>1, 'position'=>35), 'u.api_key'=>array('label'=>"ApiKey", 'checked'=>0, 'position'=>40, "enabled"=>(isModEnabled('api') && $user->admin)), 'u.fk_soc'=>array('label'=>"Company", 'checked'=>($contextpage == 'employeelist' ? 0 : 1), 'position'=>45), - 'u.ref_employee'=>array('label'=>"RefEmployee", 'checked'=>-1, 'position'=>60, 'enabled'=>(isModEnabled('hrm') && $permissiontoreadhr)), - 'u.national_registration_number'=>array('label'=>"NationalRegistrationNumber", 'checked'=>-1, 'position'=>61, 'enabled'=>(isModEnabled('hrm') && $permissiontoreadhr)), - 'u.job'=>array('label'=>"PostOrFunction", 'checked'=>-1, 'position'=>50), + 'u.ref_employee'=>array('label'=>"RefEmployee", 'checked'=>-1, 'position'=>50, 'enabled'=>(isModEnabled('hrm') && $permissiontoreadhr)), + 'u.national_registration_number'=>array('label'=>"NationalRegistrationNumber", 'checked'=>-1, 'position'=>51, 'enabled'=>(isModEnabled('hrm') && $permissiontoreadhr)), + 'u.job'=>array('label'=>"PostOrFunction", 'checked'=>-1, 'position'=>60), 'u.salary'=>array('label'=>"Salary", 'checked'=>-1, 'position'=>80, 'enabled'=>(isModEnabled('salaries') && $user->hasRight("salaries", "readall")), 'isameasure'=>1), 'u.datelastlogin'=>array('label'=>"LastConnexion", 'checked'=>1, 'position'=>100), 'u.datepreviouslogin'=>array('label'=>"PreviousConnexion", 'checked'=>0, 'position'=>110), @@ -897,10 +897,6 @@ print_liste_field_titre($arrayfields['u.entity']['label'], $_SERVER['PHP_SELF'], "u.entity", $param, "", "", $sortfield, $sortorder); $totalarray['nbfield']++; } -if (!empty($arrayfields['u.job']['checked'])) { - print_liste_field_titre($arrayfields['u.job']['label'], $_SERVER['PHP_SELF'], "u.job", $param, "", "", $sortfield, $sortorder); - $totalarray['nbfield']++; -} if (!empty($arrayfields['u.ref_employee']['checked'])) { print_liste_field_titre("RefEmployee", $_SERVER['PHP_SELF'], "u.ref_employee", $param, "", "", $sortfield, $sortorder); $totalarray['nbfield']++; @@ -909,6 +905,10 @@ print_liste_field_titre("NationalRegistrationNumber", $_SERVER['PHP_SELF'], "u.national_registration_number", $param, "", "", $sortfield, $sortorder); $totalarray['nbfield']++; } +if (!empty($arrayfields['u.job']['checked'])) { + print_liste_field_titre($arrayfields['u.job']['label'], $_SERVER['PHP_SELF'], "u.job", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; +} if (!empty($arrayfields['u.salary']['checked'])) { print_liste_field_titre("Salary", $_SERVER['PHP_SELF'], "u.salary", $param, "", "", $sortfield, $sortorder, 'right '); $totalarray['nbfield']++; diff --git a/htdocs/user/logout.php b/htdocs/user/logout.php index d71ee34d93f52..129ae24df06fd 100644 --- a/htdocs/user/logout.php +++ b/htdocs/user/logout.php @@ -72,7 +72,7 @@ } // Define url to go after disconnect -$urlfrom = empty($_SESSION["urlfrom"]) ? '' : $_SESSION["urlfrom"]; +$urlfrom = empty($_SESSION["urlfrom"]) ? GETPOST('urlfrom') : $_SESSION["urlfrom"]; // Define url to go $url = DOL_URL_ROOT."/index.php"; // By default go to login page diff --git a/htdocs/variants/admin/admin.php b/htdocs/variants/admin/admin.php index 6f7ec6b202c02..3b2b0ccf97497 100644 --- a/htdocs/variants/admin/admin.php +++ b/htdocs/variants/admin/admin.php @@ -50,6 +50,11 @@ $error++; } + if (!dolibarr_set_const($db, 'PRODUIT_ATTRIBUTES_PROPAGATE', GETPOST('PRODUIT_ATTRIBUTES_PROPAGATE'), 'chaine', 0, '', $conf->entity)) { + setEventMessages($langs->trans('CoreErrorMessage'), null, 'errors'); + $error++; + } + if (!$error) { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); } @@ -83,6 +88,10 @@ } print ''; + +print ''.$langs->trans('AlwaysPropagateToVariants').''; +print ''. $form->selectyesno("PRODUIT_ATTRIBUTES_PROPAGATE", getDolGlobalString('PRODUIT_ATTRIBUTES_PROPAGATE', '1'), 1).''; + print ''; print '
    '; diff --git a/test/phpunit/DoliDBTest.php b/test/phpunit/DoliDBTest.php index 999c3b3e54a26..2a380fa637e41 100644 --- a/test/phpunit/DoliDBTest.php +++ b/test/phpunit/DoliDBTest.php @@ -160,7 +160,7 @@ public function testDDLUpdateField() print __METHOD__." result=".$result."\n"; // TODO Use $savtype and $savnull instead of hard coded - $field_desc = array('type'=>'varchar', 'value'=>'16', 'null'=>'NOT NULL'); + $field_desc = array('type'=>'varchar', 'value'=>'16', 'null'=>'NOT NULL', 'default'=>'aaaabbbbccccdddd'); $result = $db->DDLUpdateField($db->prefix().'c_paper_format', 'code', $field_desc); $this->assertEquals(1, $result); diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 545306f57344e..fb3132a17ff55 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -960,6 +960,16 @@ public function testDolEval() print "result = ".$result."\n"; $this->assertEquals('Parent project not found', $result); + $s = 'new abc->invoke(\'whoami\')'; + $result=dol_eval($s, 1, 1, '2'); + print "result = ".$result."\n"; + $this->assertEquals('Bad string syntax to evaluate: new abc__forbiddenstring__(\'whoami\')', $result); + + $s = 'new ReflectionFunction(\'abc\')'; + $result=dol_eval($s, 1, 1, '2'); + print "result = ".$result."\n"; + $this->assertEquals('Bad string syntax to evaluate: new __forbiddenstring__(\'abc\')', $result); + $result=dol_eval('$a=function() { }; $a;', 1, 1, ''); print "result = ".$result."\n"; $this->assertContains('Bad string syntax to evaluate', $result);