mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-02-07 16:41:48 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b3ae6c2d7 | ||
|
|
da0ece345f | ||
|
|
173c6865cb | ||
|
|
07a3d0e4b7 | ||
|
|
72ed29a599 | ||
|
|
70b3be5e7f | ||
|
|
07ff579416 | ||
|
|
53dbc754f6 | ||
|
|
a9dcecbc2f | ||
|
|
5d524f7973 | ||
|
|
1b2f16b01a |
82
.github/workflows/pr-18-testldr.yaml
vendored
Normal file
82
.github/workflows/pr-18-testldr.yaml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
# Action to prepare the github action
|
||||
# Go on Dolibarr - Settings - Developer settings - Enter a name + webhook to disable + Permissions (see app test) + Can install by any account
|
||||
# Click on generate the private keys
|
||||
# Click on Install application - choose user of the Organization
|
||||
# Go on Organisation - Secret and variables and create a secret PR18_SECRET_KEY and copy the content of received private key. Choose the repository access to "Repository Dolibarr".
|
||||
# Go on Organisation - Secret and variables and create a variable PR18_APP_ID and copy the ID of the previously create ID. Choose the repository access to "Repository Dolibarr".
|
||||
#
|
||||
|
||||
name: Set reviewer and label for v18 (test ldr)
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- "18.0"
|
||||
push:
|
||||
branches:
|
||||
- "18.0"
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
assign-and-label-v18:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
#- name: Install GitHub CLI
|
||||
# run: sudo apt-get install gh
|
||||
|
||||
- name: Debug GitHub Event
|
||||
run: cat $GITHUB_EVENT_PATH
|
||||
|
||||
- name: Generate a token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ vars.PR18_APP_ID }}
|
||||
private-key: ${{ secrets.PR18_SECRET_KEY }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Assign Tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
prid: ${{ github.event.pull_request.number }}
|
||||
prid2: ${{ github.event.pull_request_target.number }}
|
||||
url: ${{ github.event.pull_request.html_url }}
|
||||
url2: ${{ github.event.pull_request_target.html_url }}
|
||||
run: |
|
||||
echo "env.prid=${{env.prid}}"
|
||||
echo "env.prid=${{env.prid2}}"
|
||||
echo "env.url=${{env.url}}"
|
||||
echo "env.url2=${{env.url2}}"
|
||||
gh pr edit "${{env.prid}}" --add-label "Issue for v18 maintenance Team"
|
||||
|
||||
- name: Set reviewers except PR author
|
||||
id: set-reviewers
|
||||
run: |
|
||||
# Liste des reviewers à ajuster selon équipe
|
||||
REVIEWERS=("lvessiller-opendsi" "rycks")
|
||||
AUTHOR="${{ github.event.pull_request.user.login }}"
|
||||
FINAL_REVIEWERS=()
|
||||
for reviewer in "${REVIEWERS[@]}"; do
|
||||
if [ "$reviewer" != "$AUTHOR" ]; then
|
||||
FINAL_REVIEWERS+=("$reviewer")
|
||||
fi
|
||||
done
|
||||
echo "AUTHOR=$AUTHOR"
|
||||
echo "reviewers=$(IFS=, ; echo "${FINAL_REVIEWERS[*]}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Assign reviewers
|
||||
if: steps.set-reviewers.outputs.reviewers != ''
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
prid: ${{ github.event.pull_request.number }}
|
||||
url: ${{ github.event.pull_request.html_url }}
|
||||
reviewers: ${{ steps.set-reviewers.outputs.reviewers }}
|
||||
run: |
|
||||
echo "Assigning reviewers: ${{env.reviewers}}"
|
||||
gh pr edit "${{env.prid}}" --add-reviewer "${{env.reviewers}}"
|
||||
191
.github/workflows/pr-18.yaml
vendored
191
.github/workflows/pr-18.yaml
vendored
@@ -1,11 +1,17 @@
|
||||
# Action to prepare the github action
|
||||
# Go on Dolibarr - Settings - Developer settings - Enter a name + webhook to disable + Permissions (see app test) + Can install by any account
|
||||
# Click on generate the private keys
|
||||
# Click on Install application - choose user of the Organization
|
||||
# Go on Organisation - Secret and variables and create a secret PR18_SECRET_KEY and copy the content of received private key. Choose the repository access to "Repository Dolibarr".
|
||||
# Go on Organisation - Secret and variables and create a variable PR18_APP_ID and copy the ID of the previously create ID. Choose the repository access to "Repository Dolibarr".
|
||||
# Action to prepare the GitHub Action
|
||||
# Prerequisites (create in the organization / repo):
|
||||
# - Secret: PR18_SECRET_KEY (private key generated for the GitHub App)
|
||||
# - Variable: PR18_APP_ID (GitHub App ID)
|
||||
#
|
||||
# Behavior:
|
||||
# - On pull_request_target (opened, synchronize, reopened) against branch 18.0:
|
||||
# - Generate a GitHub App token
|
||||
# - Add the label "Issue for v18 maintenance Team" to the PR (error-tolerant)
|
||||
# - Assign the reviewers listed below, excluding the PR author
|
||||
# -> attempt per reviewer (if a reviewer fails, log and continue)
|
||||
# -> the step fails only if no reviewer could be added
|
||||
# - On push to 18.0: workflow runs but PR-specific actions are skipped
|
||||
#
|
||||
|
||||
name: Set reviewer and label for v18
|
||||
on:
|
||||
pull_request_target:
|
||||
@@ -24,54 +30,137 @@ jobs:
|
||||
assign-and-label-v18:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Mergeers / reviewers list: edit here as needed (comma-separated)
|
||||
env:
|
||||
REVIEWERS: "lvessiller-opendsi,rycks"
|
||||
# Label name to apply
|
||||
V18_LABEL: "Issue for v18 maintenance Team"
|
||||
|
||||
steps:
|
||||
#- name: Install GitHub CLI
|
||||
# run: sudo apt-get install gh
|
||||
# 1) Generate a GitHub App token (via actions/create-github-app-token)
|
||||
- name: Generate GitHub App token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ vars.PR18_APP_ID }}
|
||||
private-key: ${{ secrets.PR18_SECRET_KEY }}
|
||||
|
||||
- name: Generate a token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ vars.PR18_APP_ID }}
|
||||
private-key: ${{ secrets.PR18_SECRET_KEY }}
|
||||
# 2) Checkout repository (useful if repo content is needed later)
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
# 3) Install / configure GitHub CLI (gh) on the runner
|
||||
#- name: Setup GitHub CLI (gh)
|
||||
# uses: cli/gh-action@v3
|
||||
# -> Error: Unable to resolve action cli/gh-action, repository not found
|
||||
- name: Setup GitHub CLI (gh) (install locally)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gh || {
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gh
|
||||
}
|
||||
gh --version
|
||||
|
||||
- name: Assign Tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
prid: ${{ github.event.pull_request.number }}
|
||||
url: ${{ github.event.pull_request.html_url }}
|
||||
url2: ${{ github.event.pull_request_target.html_url }}
|
||||
run: |
|
||||
echo "env.prid=${{env.prid}}"
|
||||
echo "env.url=${{env.url}}"
|
||||
echo "env.url2=${{env.url2}}"
|
||||
gh pr edit "${{env.prid}}" --add-label "Issue for v18 maintenance Team"
|
||||
# Debug information (useful for diagnostics)
|
||||
- name: Debug info
|
||||
run: |
|
||||
echo "Event: $GITHUB_EVENT_NAME"
|
||||
echo "Ref: $GITHUB_REF"
|
||||
echo "Run id: $GITHUB_RUN_ID"
|
||||
echo "Reviewers configured: $REVIEWERS"
|
||||
|
||||
- name: Set reviewers except PR author
|
||||
id: set-reviewers
|
||||
run: |
|
||||
# Liste des reviewers à ajuster selon équipe
|
||||
REVIEWERS=("lvessiller-opendsi" "rycks")
|
||||
AUTHOR="${{ github.event.pull_request.user.login }}"
|
||||
FINAL_REVIEWERS=()
|
||||
for reviewer in "${REVIEWERS[@]}"; do
|
||||
if [ "$reviewer" != "$AUTHOR" ]; then
|
||||
FINAL_REVIEWERS+=("$reviewer")
|
||||
# 4) Add the label to the PR (PR events only)
|
||||
# -> tolerant to errors: log on failure but do not fail the job
|
||||
- name: Add label to PR (pull_request events only)
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
V18_LABEL: ${{ env.V18_LABEL }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "Adding label '$V18_LABEL' to PR #${PR_NUMBER}"
|
||||
if gh pr edit "$PR_NUMBER" --add-label "$V18_LABEL"; then
|
||||
echo "Label added successfully."
|
||||
else
|
||||
echo "Warning: failed to add label '$V18_LABEL' to PR #${PR_NUMBER}. Continuing."
|
||||
fi
|
||||
done
|
||||
echo "AUTHOR=$AUTHOR"
|
||||
echo "reviewers=$(IFS=, ; echo "${FINAL_REVIEWERS[*]}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Assign reviewers
|
||||
if: steps.set-reviewers.outputs.reviewers != ''
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
prid: ${{ github.event.pull_request.number }}
|
||||
url: ${{ github.event.pull_request.html_url }}
|
||||
reviewers: ${{ steps.set-reviewers.outputs.reviewers }}
|
||||
run: |
|
||||
echo "Assigning reviewers: ${{env.reviewers}}"
|
||||
gh pr edit "${{env.prid}}" --add-reviewer "${{env.reviewers}}"
|
||||
# 5) Compute final reviewers list excluding the PR author
|
||||
- name: Compute reviewers (exclude PR author)
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
id: set-reviewers
|
||||
run: |
|
||||
set -euo pipefail
|
||||
IFS=',' read -ra ALL_REVIEWERS <<< "${REVIEWERS}"
|
||||
AUTHOR="${{ github.event.pull_request.user.login }}"
|
||||
FINAL=()
|
||||
for r in "${ALL_REVIEWERS[@]}"; do
|
||||
r_trimmed="$(echo "$r" | xargs)"
|
||||
if [ -z "$r_trimmed" ]; then
|
||||
continue
|
||||
fi
|
||||
if [ "$r_trimmed" != "$AUTHOR" ]; then
|
||||
FINAL+=("$r_trimmed")
|
||||
fi
|
||||
done
|
||||
if [ ${#FINAL[@]} -eq 0 ]; then
|
||||
echo "reviewers=" >> $GITHUB_OUTPUT
|
||||
else
|
||||
reviewers_csv="$(IFS=, ; echo "${FINAL[*]}")"
|
||||
echo "reviewers=${reviewers_csv}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "author=$AUTHOR" >> $GITHUB_OUTPUT
|
||||
echo "Computed reviewers: ${reviewers_csv:-<none>}"
|
||||
|
||||
# 6) Assign reviewers one-by-one with fine-grained error handling
|
||||
# - try each reviewer, track successes and failures
|
||||
# - fail the step only if none could be added
|
||||
# - succeed if at least one was added (but log failures)
|
||||
- name: Assign reviewers on PR (per-reviewer, tolerant errors)
|
||||
if: ${{ github.event_name == 'pull_request' && steps.set-reviewers.outputs.reviewers != '' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
REVIEWERS_CSV: ${{ steps.set-reviewers.outputs.reviewers }}
|
||||
run: |
|
||||
# Note: avoid 'set -e' to handle per-reviewer failures manually
|
||||
set -uo pipefail
|
||||
IFS=',' read -ra TO_ADD <<< "${REVIEWERS_CSV}"
|
||||
SUCCESS=0
|
||||
FAILED=()
|
||||
for r in "${TO_ADD[@]}"; do
|
||||
r_trimmed="$(echo "$r" | xargs)"
|
||||
if [ -z "$r_trimmed" ]; then
|
||||
continue
|
||||
fi
|
||||
echo "Attempting to add reviewer: $r_trimmed"
|
||||
if gh pr edit "$PR_NUMBER" --add-reviewer "$r_trimmed"; then
|
||||
echo "Added reviewer: $r_trimmed"
|
||||
SUCCESS=$((SUCCESS+1))
|
||||
else
|
||||
echo "Warning: failed to add reviewer: $r_trimmed"
|
||||
echo "Debug: PR view:"
|
||||
gh pr view "$PR_NUMBER" --json number,title,author,reviewRequests || true
|
||||
FAILED+=("$r_trimmed")
|
||||
fi
|
||||
done
|
||||
if [ $SUCCESS -eq 0 ]; then
|
||||
echo "Error: none of the configured reviewers could be added: ${FAILED[*]:-<none>}"
|
||||
# Fail the step because no reviewer was added
|
||||
exit 1
|
||||
else
|
||||
echo "Reviewers added: ${SUCCESS}. Failed to add: ${FAILED[*]:-none}"
|
||||
# Step succeeds even if some reviewers failed
|
||||
fi
|
||||
|
||||
# 7) Push event notice (no PR-specific actions performed)
|
||||
- name: Push event notice
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
run: |
|
||||
echo "Triggered by push on branch 18.0. No PR-specific actions performed."
|
||||
|
||||
@@ -916,8 +916,8 @@ class modProduct extends DolibarrModules
|
||||
$this->import_regex_array[$r] = array(
|
||||
'pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$',
|
||||
'pr.recuperableonly'=>'^[0|1]$'
|
||||
);
|
||||
$this->import_convertvalue_array[$r] = array(
|
||||
);
|
||||
$this->import_convertvalue_array[$r] = array(
|
||||
'pr.fk_product'=>array('rule'=>'fetchidfromref', 'classfile'=>'/product/class/product.class.php', 'class'=>'Product', 'method'=>'fetch', 'element'=>'Product')
|
||||
);
|
||||
$this->import_examplevalues_array[$r] = array('pr.fk_product'=>"ref:PRODUCT_REF or id:123456",
|
||||
|
||||
@@ -616,7 +616,7 @@ class CommandeFournisseur extends CommonOrder
|
||||
$objsearchpackage = $this->db->fetch_object($resqlsearchpackage);
|
||||
if ($objsearchpackage) {
|
||||
$line->fk_fournprice = $objsearchpackage->rowid;
|
||||
$line->packaging = $objsearchpackage->packaging;
|
||||
$line->packaging = (float) $objsearchpackage->packaging;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
@@ -1979,16 +1979,16 @@ class CommandeFournisseur extends CommonOrder
|
||||
}
|
||||
|
||||
// Predefine quantity according to packaging
|
||||
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
|
||||
if (getDolGlobalString('PRODUCT_USE_SUPPLIER_PACKAGING')) {
|
||||
$prod = new Product($this->db);
|
||||
$prod->get_buyprice($fk_prod_fourn_price, $qty, $fk_product, 'none', (empty($this->fk_soc) ? $this->socid : $this->fk_soc));
|
||||
$prod->get_buyprice($fk_prod_fourn_price, (float) $qty, $fk_product, 'none', (empty($this->fk_soc) ? $this->socid : $this->fk_soc));
|
||||
|
||||
if ($qty < $prod->packaging) {
|
||||
$qty = $prod->packaging;
|
||||
$qty = (float) $prod->packaging;
|
||||
} else {
|
||||
if (!empty($prod->packaging) && ($qty % $prod->packaging) > 0) {
|
||||
$coeff = intval($qty / $prod->packaging) + 1;
|
||||
$qty = $prod->packaging * $coeff;
|
||||
if (!empty($prod->packaging) && (fmod((float) $qty, (float) $prod->packaging) > 0.000001)) {
|
||||
$coeff = intval((float) $qty / $prod->packaging) + 1;
|
||||
$qty = (float) $prod->packaging * $coeff;
|
||||
setEventMessages($langs->trans('QtyRecalculatedWithPackaging'), null, 'mesgs');
|
||||
}
|
||||
}
|
||||
@@ -2962,11 +2962,11 @@ class CommandeFournisseur extends CommonOrder
|
||||
$this->line->desc = $desc;
|
||||
|
||||
// redefine quantity according to packaging
|
||||
if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
|
||||
if (getDolGlobalString('PRODUCT_USE_SUPPLIER_PACKAGING')) {
|
||||
if ($qty < $this->line->packaging) {
|
||||
$qty = $this->line->packaging;
|
||||
} else {
|
||||
if (!empty($this->line->packaging) && ($qty % $this->line->packaging) > 0) {
|
||||
if (!empty($this->line->packaging) && is_numeric($this->line->packaging) && (float) $this->line->packaging > 0 && (fmod((float) $qty, $this->line->packaging) > 0)) {
|
||||
$coeff = intval($qty / $this->line->packaging) + 1;
|
||||
$qty = $this->line->packaging * $coeff;
|
||||
setEventMessage($langs->trans('QtyRecalculatedWithPackaging'), 'mesgs');
|
||||
@@ -3869,7 +3869,7 @@ class CommandeFournisseurLigne extends CommonOrderLine
|
||||
$objsearchpackage = $this->db->fetch_object($resqlsearchpackage);
|
||||
if ($objsearchpackage) {
|
||||
$this->fk_fournprice = $objsearchpackage->rowid;
|
||||
$this->packaging = $objsearchpackage->packaging;
|
||||
$this->packaging = (float) $objsearchpackage->packaging;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2018 Pierre Chéné <pierre.chene44@gmail.com>
|
||||
* Copyright (C) 2019 Cedric Ancelin <icedo.anc@gmail.com>
|
||||
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
|
||||
* Copyright (C) 2018 Pierre Chéné <pierre.chene44@gmail.com>
|
||||
* Copyright (C) 2019 Cedric Ancelin <icedo.anc@gmail.com>
|
||||
* Copyright (C) 2020-2021 Frédéric France <frederic.france@netlogic.fr>
|
||||
* Copyright (C) 2026 Benjamin Falière <benjamin@faliere.com>
|
||||
*
|
||||
* 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
|
||||
@@ -1052,8 +1053,9 @@ class Thirdparties extends DolibarrApi
|
||||
|
||||
|
||||
$sql = "SELECT f.ref, f.type as factype, re.fk_facture_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_facture, re.fk_facture_line";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f";
|
||||
$sql .= " WHERE f.rowid = re.fk_facture_source AND re.fk_soc = ".((int) $id);
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as f ON f.rowid = re.fk_facture_source";
|
||||
$sql .= " WHERE re.fk_soc = ".((int) $id);
|
||||
if ($filter == "available") {
|
||||
$sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user