├── locales ├── en_GB.mo ├── fr_FR.mo ├── en_GB.po ├── glpi.pot └── fr_FR.po ├── purchaserequest.png ├── README.md ├── tools ├── update_mo.pl └── extract_template.sh ├── .github └── workflows │ ├── updatepot.yml │ ├── generatemo.yml │ └── release.yml ├── index.php ├── ajax ├── index.php └── dropdownGroup.php ├── front ├── index.php ├── config.form.php ├── threshold.form.php ├── purchaserequest.php ├── validation.form.php └── purchaserequest.form.php ├── src ├── PurchaseRequestState.php ├── Config.php ├── Threshold.php ├── Servicecatalog.php ├── Profile.php ├── NotificationTargetPurchaseRequest.php └── Validation.php ├── purchaserequest.xml ├── setup.php ├── hook.php └── LICENSE /locales/en_GB.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/purchaserequest/main/locales/en_GB.mo -------------------------------------------------------------------------------- /locales/fr_FR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/purchaserequest/main/locales/fr_FR.mo -------------------------------------------------------------------------------- /purchaserequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InfotelGLPI/purchaserequest/main/purchaserequest.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # purchaserequest 2 | Plugin purchaserequest for GLPI 3 | 4 | Plugin extension for Order plugin (https://github.com/pluginsGLPI/order) 5 | -------------------------------------------------------------------------------- /tools/update_mo.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/bin/perl -w 3 | 4 | if (@ARGV!=0){ 5 | print "USAGE update_mo.pl\n\n"; 6 | 7 | exit(); 8 | } 9 | 10 | 11 | opendir(DIRHANDLE,'locales')||die "ERROR: can not read current directory\n"; 12 | foreach (readdir(DIRHANDLE)){ 13 | if ($_ ne '..' && $_ ne '.'){ 14 | 15 | if(!(-l "$dir/$_")){ 16 | if (index($_,".po",0)==length($_)-3) { 17 | $lang=$_; 18 | $lang=~s/\.po//; 19 | 20 | `msgfmt locales/$_ -o locales/$lang.mo`; 21 | } 22 | } 23 | 24 | } 25 | } 26 | closedir DIRHANDLE; 27 | 28 | # 29 | # 30 | -------------------------------------------------------------------------------- /tools/extract_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Recherche tous les fichiers PHP récursivement 4 | find . -name '*.php' > php_files.list 5 | 6 | # Extraction avec xgettext 7 | xgettext --files-from=php_files.list \ 8 | --copyright-holder='PurchaseRequest Development Team' \ 9 | --package-name='PurchaseRequest - Accounts plugin' \ 10 | -o locales/glpi.pot \ 11 | -L PHP \ 12 | --add-comments=TRANS \ 13 | --from-code=UTF-8 \ 14 | --force-po \ 15 | --keyword=_n:1,2,4t \ 16 | --keyword=__s:1,2t \ 17 | --keyword=__:1,2t \ 18 | --keyword=_e:1,2t \ 19 | --keyword=_x:1c,2,3t \ 20 | --keyword=_ex:1c,2,3t \ 21 | --keyword=_nx:1c,2,3,5t \ 22 | --keyword=_sx:1c,2,3t 23 | 24 | # Nettoyage 25 | rm php_files.list 26 | -------------------------------------------------------------------------------- /.github/workflows/updatepot.yml: -------------------------------------------------------------------------------- 1 | name: Update POT 2 | on: 3 | push: 4 | branches: [ master ] 5 | paths-ignore: 6 | - 'locales/**' 7 | 8 | env: 9 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 10 | jobs: 11 | run: 12 | 13 | name: Update POT 14 | 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repo 18 | uses: actions/checkout@v4 19 | 20 | - name: install xgettext 21 | 22 | run: sudo apt-get install gettext; 23 | - name: Update POT 24 | run: sh tools/extract_template.sh; 25 | 26 | - name: Commit changes 27 | uses: EndBug/add-and-commit@v9 28 | with: 29 | message: "Update POT" 30 | 31 | - name: Push changes 32 | uses: actions-go/push@master 33 | with: 34 | commit-message: '' 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/generatemo.yml: -------------------------------------------------------------------------------- 1 | name: Generate MO 2 | on: 3 | push: 4 | branches: [ master ] 5 | paths: 6 | - '**.po' 7 | env: 8 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 9 | jobs: 10 | run: 11 | 12 | name: Generate mo 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repo 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup Perl environment 19 | # You may pin to the exact commit or the version. 20 | # uses: shogo82148/actions-setup-perl@8d2e3d59a9516b785ed32169d48a4888eaa9b514 21 | uses: shogo82148/actions-setup-perl@v1 22 | - name: msgfmt 23 | # You may pin to the exact commit or the version. 24 | # uses: whtsky/msgfmt-action@6b2181f051b002182d01a1e1f1aff216230c5a4d 25 | uses: whtsky/msgfmt-action@20190305 26 | - name: Generate mo 27 | run: perl tools/update_mo.pl; 28 | 29 | - name: Commit changes 30 | uses: EndBug/add-and-commit@v9 31 | with: 32 | 33 | message: "Generate mo" 34 | - name: Push changes 35 | 36 | uses: actions-go/push@master 37 | with: 38 | commit-message: '' 39 | 40 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | -------------------------------------------------------------------------------- /ajax/index.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | -------------------------------------------------------------------------------- /front/index.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | -------------------------------------------------------------------------------- /ajax/dropdownGroup.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 31 | 32 | header("Content-Type: text/html; charset=UTF-8"); 33 | Html::header_nocache(); 34 | 35 | Session::checkLoginUser(); 36 | 37 | if (isset($_POST["users_id"])) { 38 | 39 | PurchaseRequest::displayGroup($_POST['users_id']); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /front/config.form.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\Config; 31 | 32 | Session::checkLoginUser(); 33 | 34 | if (Plugin::isPluginActive("purchaserequest")) { 35 | if (Session::haveRight("plugin_purchaserequest_config", READ)) { 36 | $config = new Config(); 37 | 38 | if (isset($_POST["update_config"])) { 39 | Session::checkRight("plugin_purchaserequest_config", READ); 40 | $config->update($_POST); 41 | Html::back(); 42 | 43 | } else { 44 | $_SESSION['glpi_js_toload']["tinymce"][] = 'lib/tiny_mce/lib/tinymce.js'; 45 | Html::header(__('Setup'), '', "config", Config::getType()); 46 | $config->GetFromDB(1); 47 | $config->display($_GET); 48 | // $config->showForm(); 49 | 50 | Html::footer(); 51 | } 52 | 53 | } else { 54 | Html::header(__('Setup'), '', "config", Plugin::getType()); 55 | echo "
"; 56 | echo "" . __("You don't have permission to perform this action.") . "
"; 57 | Html::footer(); 58 | } 59 | 60 | } else { 61 | Html::header(__('Setup'), '', "config", Plugin::getType()); 62 | echo "
"; 63 | echo "" . __('Please activate the plugin', 'purchaserequest') . "
"; 64 | Html::footer(); 65 | } 66 | -------------------------------------------------------------------------------- /front/threshold.form.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 31 | use GlpiPlugin\Purchaserequest\Threshold; 32 | 33 | if (!isset($_GET["id"])) { 34 | $_GET["id"] = ""; 35 | } 36 | 37 | $threshold = new Threshold(); 38 | 39 | if (isset($_POST["add"])) { 40 | $threshold->check(-1, CREATE, $_POST); 41 | $newID = $threshold->add($_POST); 42 | $url = Toolbox::getItemTypeFormURL(PurchaseRequest::class) . "?id=$newID"; 43 | Html::back(); 44 | 45 | } else if (isset($_POST["add_tickets"])) { 46 | $threshold->check(-1, CREATE, $_POST); 47 | $newID = $threshold->add($_POST); 48 | Html::back(); 49 | 50 | /* delete purchaserequest */ 51 | } else if (isset($_POST["delete"])) { 52 | 53 | $threshold->check($_POST['id'], DELETE); 54 | $threshold->delete($_POST); 55 | Html::back(); 56 | } else if (isset($_POST["restore"])) { 57 | 58 | $threshold->check($_POST['id'], DELETE); 59 | $threshold->restore($_POST); 60 | Html::back(); 61 | 62 | } else if (isset($_POST["purge"])) { 63 | $threshold->check($_POST['id'], PURGE); 64 | $threshold->delete($_POST, 1); 65 | Html::back(); 66 | 67 | /* update purchaserequest */ 68 | } else if (isset($_POST["update"]) || (isset($_POST['update_status']))) { 69 | 70 | $threshold->check($_POST['id'], UPDATE); 71 | $threshold->update($_POST); 72 | Html::back(); 73 | } 74 | 75 | 76 | Html::back(); 77 | -------------------------------------------------------------------------------- /src/PurchaseRequestState.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | namespace GlpiPlugin\Purchaserequest; 31 | 32 | use CommonDropdown; 33 | use DbUtils; 34 | use Migration; 35 | 36 | if (!defined('GLPI_ROOT')) { 37 | die("Sorry. You can't access directly to this file"); 38 | } 39 | 40 | class PurchaseRequestState extends CommonDropdown { 41 | 42 | public static function getTypeName($nb = 0) { 43 | return __("Purchase request status", "purchaserequest"); 44 | } 45 | 46 | public static function install(Migration $migration) { 47 | global $DB; 48 | 49 | $dbu = new DbUtils(); 50 | $table = $dbu->getTableForItemType(__CLASS__); 51 | if (!$DB->tableExists($table)) { 52 | $migration->displayMessage("Installing $table"); 53 | 54 | //Install 55 | $query = "CREATE TABLE `glpi_plugin_purchaserequest_purchaserequeststates` ( 56 | `id` int unsigned NOT NULL auto_increment, 57 | `name` varchar(255) collate utf8mb4_unicode_ci default NULL, 58 | `comment` text collate utf8mb4_unicode_ci, 59 | PRIMARY KEY (`id`), 60 | KEY `name` (`name`) 61 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;"; 62 | $DB->doQuery($query) or die($DB->error()); 63 | } 64 | } 65 | 66 | public static function uninstall() { 67 | global $DB; 68 | //New table 69 | $dbu = new DbUtils(); 70 | $DB->doQuery("DROP TABLE IF EXISTS `" . $dbu->getTableForItemType(__CLASS__) . "`") or die ($DB->error()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /front/purchaserequest.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 31 | use GlpiPlugin\Servicecatalog\Main; 32 | 33 | global $DB; 34 | 35 | if (Session::getCurrentInterface() == 'central') { 36 | Html::header( 37 | PurchaseRequest::getTypeName(2), 38 | $_SERVER['PHP_SELF'], 39 | "management", 40 | PurchaseRequest::class, 41 | "purchaserequest" 42 | ); 43 | } else { 44 | if (Plugin::isPluginActive('servicecatalog')) { 45 | Main::showDefaultHeaderHelpdesk(PurchaseRequest::getTypeName(2)); 46 | echo "
"; 47 | } else { 48 | Html::helpHeader(PurchaseRequest::getTypeName(2)); 49 | } 50 | } 51 | 52 | if (Plugin::isPluginActive("order") 53 | && $DB->tableExists("glpi_plugin_order_orders")) { 54 | $purchase = new PurchaseRequest(); 55 | 56 | if (PurchaseRequest::canView()) { 57 | Search::show(PurchaseRequest::class); 58 | } else { 59 | echo "
"; 60 | echo "" . __("Access denied") . "
"; 61 | } 62 | } else { 63 | Html::header(__('Setup'), '', "tools", PurchaseRequest::class); 64 | echo "
"; 65 | echo "" . __('Please activate the plugin order', 'purchaserequest') . "
"; 66 | } 67 | 68 | if (Session::getCurrentInterface() != 'central' 69 | && Plugin::isPluginActive('servicecatalog')) { 70 | Main::showNavBarFooter('purchaserequest'); 71 | } 72 | 73 | if (Session::getCurrentInterface() == 'central') { 74 | Html::footer(); 75 | } else { 76 | Html::helpFooter(); 77 | } 78 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | 2 | on: 3 | push: 4 | # Sequence of patterns matched against refs/tags 5 | tags: 6 | - '*.*.*' # Push events to matching ex:20.15.10 7 | 8 | name: Create release with tag 9 | env: 10 | TAG_VALUE: ${GITHUB_REF/refs\/tags\//} 11 | jobs: 12 | build: 13 | name: Upload Release Asset 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | - name: Build project # This would actually build your project, using zip for an example artifact 19 | id: build_ 20 | env: 21 | GITHUB_NAME: ${{ github.event.repository.name }} 22 | 23 | 24 | run: sudo apt-get install libxml-xpath-perl;echo $(xpath -e '/root/versions/version[num="'${GITHUB_REF/refs\/tags\//}'"]/compatibility/text()' $GITHUB_NAME.xml);echo ::set-output name=version_glpi::$(xpath -e '/root/versions/version[num="'${GITHUB_REF/refs\/tags\//}'"]/compatibility/text()' $GITHUB_NAME.xml); rm -rf $GITHUB_NAME.xml tools wiki screenshots test .git .github ISSUE_TEMPLATE.md TODO.txt $GITHUB_NAME.png;cd ..; tar jcvf glpi-$GITHUB_NAME-${GITHUB_REF/refs\/tags\//}.tar.bz2 $GITHUB_NAME;ls -al;echo ::set-output name=tag::${GITHUB_REF/refs\/tags\//};echo ${{ steps.getxml.outputs.info }}; 25 | # run: rm -rf $GITHUB_NAME.xml tools wiki screenshots test ISSUE_TEMPLATE.md TODO.txt $GITHUB_NAME.png; tar -zcvf glpi-$GITHUB_NAME-$GITHUB_TAG.tar.gz $GITHUB_NAME 26 | - name: Create Release 27 | id: create_release 28 | uses: actions/create-release@v1 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | with: 32 | tag_name: ${{ github.ref }} 33 | release_name: | 34 | GLPI ${{ steps.build_.outputs.version_glpi }} : Version ${{ github.ref }} disponible / available 35 | body : Version ${{ steps.build_.outputs.tag }} released for GLPI ${{ steps.build_.outputs.version_glpi }} 36 | draft: false 37 | prerelease: true 38 | - name: Upload Release Asset 39 | id: upload-release-asset 40 | uses: actions/upload-release-asset@v1 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | GITHUB_NAME: ${{ github.event.repository.name }} 44 | with: 45 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 46 | asset_path: /home/runner/work/${{ github.event.repository.name }}/glpi-${{ github.event.repository.name }}-${{ steps.build_.outputs.tag }}.tar.bz2 47 | asset_name: glpi-${{ github.event.repository.name }}-${{ steps.build_.outputs.tag }}.tar.bz2 48 | asset_content_type: application/zip 49 | 50 | -------------------------------------------------------------------------------- /front/validation.form.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 31 | use GlpiPlugin\Purchaserequest\Validation; 32 | 33 | if (!isset($_GET["id"])) { 34 | $_GET["id"] = ""; 35 | } 36 | 37 | global $DB; 38 | 39 | if (Plugin::isPluginActive("order") 40 | && $DB->tableExists("glpi_plugin_order_orders")) { 41 | $validation = new Validation(); 42 | 43 | if (isset($_POST["add"])) { 44 | $validation->check(-1, CREATE, $_POST); 45 | $newID = $validation->add($_POST); 46 | Html::back(); 47 | } elseif (isset($_POST["delete"])) { 48 | $validation->check($_POST['id'], DELETE); 49 | $validation->delete($_POST); 50 | $validation->redirectToList(); 51 | } elseif (isset($_POST["restore"])) { 52 | $validation->check($_POST['id'], DELETE); 53 | $validation->restore($_POST); 54 | $validation->redirectToList(); 55 | } elseif (isset($_POST["purge"])) { 56 | $validation->check($_POST['id'], PURGE); 57 | $validation->delete($_POST, 1); 58 | $validation->redirectToList(); 59 | 60 | /* update purchaserequest */ 61 | } elseif (isset($_POST["update"]) || (isset($_POST['update_status']))) { 62 | // $validation->check($_POST['id'], READ); 63 | $validation->update($_POST); 64 | Html::back(); 65 | } 66 | Html::back(); 67 | } else { 68 | Html::header(__('Setup'), '', "tools", PurchaseRequest::class, "config"); 69 | echo "
"; 70 | echo "" . __('Please activate the plugin order', 'purchaserequest') . "
"; 71 | } 72 | 73 | Html::footer(); 74 | -------------------------------------------------------------------------------- /purchaserequest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Purchaserequest 4 | purchaserequest 5 | stable 6 | https://raw.githubusercontent.com/InfotelGLPI/purchaserequest/master/purchaserequest.png 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | https://github.com/InfotelGLPI/purchaserequest 18 | https://github.com/InfotelGLPI/purchaserequest/releases 19 | https://github.com/InfotelGLPI/purchaserequest/issues 20 | https://raw.githubusercontent.com/InfotelGLPI/purchaserequest/master/README.md 21 | 22 | Infotel 23 | 24 | 25 | 26 | 3.1.5 27 | ~11.0 28 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.5/glpi-purchaserequest-3.1.5.tar.bz2 29 | 30 | 31 | 3.1.4 32 | ~11.0 33 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.4/glpi-purchaserequest-3.1.4.tar.bz2 34 | 35 | 36 | 3.1.3 37 | ~11.0 38 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.3/glpi-purchaserequest-3.1.3.tar.bz2 39 | 40 | 41 | 3.1.2 42 | ~11.0 43 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.2/glpi-purchaserequest-3.1.2.tar.bz2 44 | 45 | 46 | 3.1.1 47 | ~11.0 48 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.1/glpi-purchaserequest-3.1.1.tar.bz2 49 | 50 | 51 | 3.1.0 52 | ~11.0 53 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.1.0/glpi-purchaserequest-3.1.0.tar.bz2 54 | 55 | 56 | 3.0.2 57 | ~10.0 58 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.2/glpi-purchaserequest-3.0.2.tar.bz2 59 | 60 | 61 | 3.0.1 62 | ~10.0 63 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.1/glpi-purchaserequest-3.0.1.tar.bz2 64 | 65 | 66 | 3.0.0 67 | ~10.0 68 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.0/glpi-purchaserequest-3.0.0.tar.bz2 69 | 70 | 71 | 3.0.0-rc3 72 | ~10.0 73 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.0-rc3/glpi-purchaserequest-3.0.0-rc3.tar.bz2 74 | 75 | 76 | 3.0.0-rc2 77 | ~10.0 78 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.0-rc2/glpi-purchaserequest-3.0.0-rc2.tar.bz2 79 | 80 | 81 | 3.0.0-rc1 82 | ~10.0 83 | https://github.com/InfotelGLPI/purchaserequest/releases/download/3.0.0-rc1/glpi-purchaserequest-3.0.0-rc1.tar.bz2 84 | 85 | 86 | 87 | en_GB 88 | fr_FR 89 | 90 | 91 | 92 | 93 | gestion 94 | inventaire 95 | 96 | 97 | management 98 | inventory 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /front/purchaserequest.form.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 31 | use GlpiPlugin\Servicecatalog\Main; 32 | 33 | include("../../../inc/includes.php"); 34 | 35 | global $DB; 36 | 37 | if (!isset($_GET["id"])) { 38 | $_GET["id"] = ""; 39 | } 40 | 41 | if (Plugin::isPluginActive("order") 42 | && $DB->tableExists("glpi_plugin_order_orders")) { 43 | $purchase = new PurchaseRequest(); 44 | 45 | if (isset($_POST["add"])) { 46 | $purchase->check(-1, CREATE, $_POST); 47 | $newID = $purchase->add($_POST); 48 | $url = Toolbox::getItemTypeFormURL(PurchaseRequest::class) . "?id=$newID"; 49 | if ($_SESSION['glpibackcreated']) { 50 | Html::redirect($purchase->getFormURL() . "?id=" . $newID); 51 | } else { 52 | Html::redirect($url); 53 | } 54 | } elseif (isset($_POST["add_tickets"])) { 55 | $purchase->check(-1, CREATE, $_POST); 56 | $newID = $purchase->add($_POST); 57 | Html::back(); 58 | 59 | /* delete purchaserequest */ 60 | } elseif (isset($_POST["delete"])) { 61 | $purchase->check($_POST['id'], DELETE); 62 | $purchase->delete($_POST); 63 | $purchase->redirectToList(); 64 | } elseif (isset($_POST["restore"])) { 65 | $purchase->check($_POST['id'], DELETE); 66 | $purchase->restore($_POST); 67 | $purchase->redirectToList(); 68 | } elseif (isset($_POST["purge"])) { 69 | $purchase->check($_POST['id'], PURGE); 70 | $purchase->delete($_POST, 1); 71 | $purchase->redirectToList(); 72 | 73 | /* update purchaserequest */ 74 | } elseif (isset($_POST["update"]) || (isset($_POST['update_status']))) { 75 | $purchase->check($_POST['id'], UPDATE); 76 | $purchase->update($_POST); 77 | Html::back(); 78 | } 79 | 80 | if (isset($_POST['action'])) { 81 | // Retrieve configuration for generate assets feature 82 | 83 | $purchase_request = new PurchaseRequest(); 84 | switch ($_POST['chooseAction']) { 85 | case 'delete_link': 86 | if (isset($_POST["item"])) { 87 | foreach ($_POST["item"] as $key => $val) { 88 | if ($val == 1) { 89 | $tmp['id'] = $key; 90 | $tmp['plugin_order_orders_id'] = 0; 91 | $purchase_request->update($tmp); 92 | } 93 | } 94 | } 95 | break; 96 | } 97 | Html::back(); 98 | } 99 | 100 | if (Session::getCurrentInterface() == 'central') { 101 | Html::header( 102 | PurchaseRequest::getTypeName(2), 103 | $_SERVER['PHP_SELF'], 104 | "management", 105 | PurchaseRequest::class, 106 | "purchaserequest" 107 | ); 108 | } else { 109 | if (Plugin::isPluginActive('servicecatalog')) { 110 | Main::showDefaultHeaderHelpdesk(PurchaseRequest::getTypeName(2), true); 111 | echo "
"; 112 | } else { 113 | Html::helpHeader(PurchaseRequest::getTypeName(2)); 114 | } 115 | } 116 | 117 | Html::requireJs('tinymce'); 118 | $purchase->display($_GET); 119 | } else { 120 | Html::header(__('Setup'), '', "tools", PurchaseRequest::class); 121 | echo "
"; 122 | echo "" . __('Please activate the plugin order', 'purchaserequest') . "
"; 123 | } 124 | 125 | if (Session::getCurrentInterface() != 'central' 126 | && Plugin::isPluginActive('servicecatalog')) { 127 | Main::showNavBarFooter('purchaserequest'); 128 | } 129 | 130 | if (Session::getCurrentInterface() == 'central') { 131 | Html::footer(); 132 | } else { 133 | Html::helpFooter(); 134 | } 135 | -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | use GlpiPlugin\Purchaserequest\Servicecatalog; 31 | use GlpiPlugin\Purchaserequest\Profile; 32 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 33 | use GlpiPlugin\Purchaserequest\Threshold; 34 | 35 | global $CFG_GLPI; 36 | 37 | define('PLUGIN_PURCHASEREQUEST_VERSION', '3.1.5'); 38 | 39 | if (!defined("PLUGIN_PURCHASEREQUEST_DIR")) { 40 | define("PLUGIN_PURCHASEREQUEST_DIR", Plugin::getPhpDir("purchaserequest")); 41 | $root = $CFG_GLPI['root_doc'] . '/plugins/purchaserequest'; 42 | define("PLUGIN_PURCHASEREQUEST_WEBDIR", $root); 43 | } 44 | 45 | 46 | /** 47 | * Init hooks of the plugin. 48 | * REQUIRED 49 | * 50 | * @return void 51 | */ 52 | function plugin_init_purchaserequest() 53 | { 54 | global $PLUGIN_HOOKS, $CFG_GLPI; 55 | 56 | 57 | $PLUGIN_HOOKS['csrf_compliant']['purchaserequest'] = true; 58 | 59 | /* Init current profile */ 60 | $PLUGIN_HOOKS['change_profile']['purchaserequest'] = [Profile::class, 'initProfile']; 61 | 62 | if (Plugin::isPluginActive('purchaserequest')) { 63 | Plugin::registerClass(Profile::class, ['addtabon' => ['Profile']]); 64 | 65 | Plugin::registerClass(PurchaseRequest::class, ['addtabon' => [Threshold::class]]); 66 | $types = [ComputerType::getType(), 67 | MonitorType::getType(), 68 | PeripheralType::getType(), 69 | NetworkEquipmentType::getType(), 70 | PrinterType::getType(), 71 | PhoneType::getType(), 72 | ConsumableItemType::getType(), 73 | CartridgeItemType::getType(), 74 | ContractType::getType(), 75 | SoftwareLicenseType::getType(), 76 | CertificateType::getType(), 77 | RackType::getType(), 78 | PDUType::getType()]; 79 | 80 | if (Plugin::isPluginActive('order')) { 81 | array_push($types, "PluginOrderOtherType"); 82 | } 83 | Plugin::registerClass(Threshold::getType(), ['addtabon' => $types]); 84 | 85 | //TODO create right config 86 | if (Session::haveRight("plugin_purchaserequest_config", READ)) { 87 | $PLUGIN_HOOKS['config_page']['purchaserequest'] = 'front/config.form.php'; 88 | } 89 | 90 | if (Session::haveRight("plugin_purchaserequest_purchaserequest", READ) 91 | && !class_exists('GlpiPlugin\Servicecatalog\Main') 92 | ) { 93 | $PLUGIN_HOOKS['helpdesk_menu_entry']['purchaserequest'] = PLUGIN_PURCHASEREQUEST_WEBDIR.'/front/purchaserequest.php'; 94 | $PLUGIN_HOOKS['helpdesk_menu_entry_icon']['purchaserequest'] = PurchaseRequest::getIcon(); 95 | } 96 | 97 | if (PurchaseRequest::canView()) { 98 | Plugin::registerClass( 99 | PurchaseRequest::class, 100 | ['notificationtemplates_types' => true, 101 | 'addtabon' => ['Ticket', 102 | 'PluginOrderOrder']] 103 | ); 104 | $PLUGIN_HOOKS['menu_toadd']['purchaserequest']['management'] = PurchaseRequest::class; 105 | 106 | if (Plugin::isPluginActive('servicecatalog')) { 107 | $PLUGIN_HOOKS['servicecatalog']['purchaserequest'] = [Servicecatalog::class]; 108 | } 109 | } 110 | } 111 | } 112 | 113 | /** 114 | * Get the name and the version of the plugin 115 | * REQUIRED 116 | * 117 | * @return array 118 | */ 119 | function plugin_version_purchaserequest() 120 | { 121 | return ['name' => _n("Purchase request", "Purchase requests", 1, "purchaserequest"), 122 | 'version' => PLUGIN_PURCHASEREQUEST_VERSION, 123 | 'author' => "Infotel, Xavier CAILLAUD", 124 | 'license' => 'GPLv2+', 125 | 'requirements' => [ 126 | 'glpi' => [ 127 | 'min' => '11.0', 128 | 'max' => '12.0', 129 | 'dev' => false 130 | ] 131 | ] 132 | ]; 133 | } 134 | 135 | /** 136 | * Check pre-requisites before install 137 | * OPTIONNAL, but recommanded 138 | * 139 | * @return boolean 140 | */ 141 | function plugin_purchaserequest_check_prerequisites() 142 | { 143 | global $DB; 144 | 145 | if (Plugin::isPluginActive("order") 146 | && !$DB->tableExists("glpi_plugin_order_orders")) { 147 | return false; 148 | } 149 | return true; 150 | } 151 | -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | namespace GlpiPlugin\Purchaserequest; 31 | 32 | use CommonDBTM; 33 | use CommonGLPI; 34 | use DbUtils; 35 | use Html; 36 | use Migration; 37 | use Session; 38 | use Toolbox; 39 | use User; 40 | 41 | class Config extends CommonDBTM 42 | { 43 | public static $rightname = "plugin_purchaserequest_config"; 44 | public $can_be_translated = true; 45 | 46 | /** 47 | * Config constructor. 48 | */ 49 | public function __construct() {} 50 | 51 | public static function canView(): bool 52 | { 53 | 54 | return (Session::haveRight(self::$rightname, READ)); 55 | } 56 | 57 | public static function canCreate(): bool 58 | { 59 | 60 | return (Session::haveRight(self::$rightname, READ)); 61 | } 62 | 63 | public static function getTypeName($nb = 0) 64 | { 65 | 66 | return self::createTabEntry(__('Plugin setup', 'purchaserequest')); 67 | } 68 | 69 | public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) 70 | { 71 | return self::createTabEntry($this->getTypeName(1)); 72 | } 73 | 74 | public static function getIcon() 75 | { 76 | return "ti ti-basket"; 77 | } 78 | 79 | public static function getMenuContent() 80 | { 81 | 82 | $menu['title'] = self::getMenuName(2); 83 | $menu['page'] = self::getSearchURL(false); 84 | $menu['links']['search'] = self::getSearchURL(false); 85 | if (self::canCreate()) { 86 | $menu['links']['add'] = self::getFormURL(false); 87 | } 88 | 89 | return $menu; 90 | } 91 | 92 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) 93 | { 94 | 95 | 96 | $item->showForm($item->getID()); 97 | 98 | 99 | return true; 100 | } 101 | 102 | public function defineTabs($options = []) 103 | { 104 | 105 | $ong = []; 106 | $this->addDefaultFormTab($ong); 107 | // $this->addStandardTab(__CLASS__, $ong, $options); 108 | 109 | return $ong; 110 | } 111 | 112 | public function showForm($ID, $options = []) 113 | { 114 | 115 | echo "
"; 117 | echo Html::hidden('id', ['value' => $this->fields['id']]); 118 | echo "
"; 119 | echo ""; 120 | 121 | 122 | echo ""; 123 | echo ""; 130 | 131 | 132 | echo ""; 135 | 136 | echo "
" . __('Configuration purchase request', 'purchaserequest') . "
" . __('General Services Manager', 'purchaserequest') . ""; 124 | User::dropdown(['name' => "id_general_service_manager", 125 | 'value' => $this->fields["id_general_service_manager"], 126 | 'entity' => -1, 127 | 'right' => 'plugin_purchaserequest_validate']); 128 | 129 | echo "
"; 133 | echo Html::submit(_sx('button', 'Save'), ['name' => 'update_config', 'class' => 'btn btn-primary']); 134 | echo "
"; 137 | Html::closeForm(); 138 | } 139 | 140 | /** 141 | * @param Migration $migration 142 | */ 143 | public static function install(Migration $migration) 144 | { 145 | global $DB; 146 | 147 | $dbu = new DbUtils(); 148 | $table = $dbu->getTableForItemType(__CLASS__); 149 | 150 | if (!$DB->tableExists($table)) { 151 | $migration->displayMessage("Installing $table"); 152 | $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_purchaserequest_configs` ( 153 | `id` int unsigned NOT NULL AUTO_INCREMENT, 154 | `id_general_service_manager` int unsigned NOT NULL DEFAULT '0', 155 | PRIMARY KEY (`id`) 156 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;"; 157 | $DB->doQuery($query) or die($DB->error()); 158 | 159 | 160 | $queryInsert = "INSERT INTO glpi_plugin_purchaserequest_configs VALUES ('1','0')"; 161 | $DB->doQuery($queryInsert) or die($DB->error()); 162 | } else { 163 | } 164 | } 165 | 166 | public static function uninstall() 167 | { 168 | global $DB; 169 | 170 | $dbu = new DbUtils(); 171 | $table = $dbu->getTableForItemType(__CLASS__); 172 | $DB->doQuery("DROP TABLE IF EXISTS`" . $table . "`") or die($DB->error()); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /locales/en_GB.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Jérémy MOREAU , 2015 7 | # Johan Cwiklinski , 2016 8 | msgid "" 9 | msgstr "" 10 | "Project-Id-Version: GLPI Plugin - Order\n" 11 | "Report-Msgid-Bugs-To: \n" 12 | "POT-Creation-Date: 2020-07-20 14:43+0200\n" 13 | "PO-Revision-Date: 2020-07-20 14:51+0200\n" 14 | "Last-Translator: Walid Nouh\n" 15 | "Language-Team: English (United Kingdom) (http://www.transifex.com/teclib/" 16 | "glpi-plugin-order/language/en_GB/)\n" 17 | "Language: en_GB\n" 18 | "MIME-Version: 1.0\n" 19 | "Content-Type: text/plain; charset=UTF-8\n" 20 | "Content-Transfer-Encoding: 8bit\n" 21 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 22 | "X-Generator: Poedit 2.3\n" 23 | 24 | #: hook.php:45 25 | msgid "Plugin installation or upgrade" 26 | msgstr "Plugin installation or upgrade" 27 | 28 | #: hook.php:111 inc/purchaserequeststate.class.php:37 29 | msgid "Purchase request status" 30 | msgstr "Purchase request status" 31 | 32 | #: hook.php:198 33 | msgctxt "quantity" 34 | msgid "Number of purchase request" 35 | msgstr "Number of purchase request" 36 | 37 | #: setup.php:82 inc/menu.class.php:30 inc/profile.class.php:56 38 | #: inc/profile.class.php:144 inc/purchaserequest.class.php:46 39 | msgid "Purchase request" 40 | msgid_plural "Purchase requests" 41 | msgstr[0] "Purchase request" 42 | msgstr[1] "Purchase requests" 43 | 44 | #: front/purchaserequest.form.php:109 front/purchaserequest.php:51 45 | msgid "Please activate the plugin order" 46 | msgstr "Please activate the plugin order" 47 | 48 | #: inc/notificationtargetpurchaserequest.class.php:38 49 | msgid "Request for validation of the purchase request" 50 | msgstr "Request for validation of the purchase request" 51 | 52 | #: inc/notificationtargetpurchaserequest.class.php:39 53 | msgid "Refusal of validation request" 54 | msgstr "Refusal of validation request" 55 | 56 | #: inc/notificationtargetpurchaserequest.class.php:40 57 | #: inc/notificationtargetpurchaserequest.class.php:92 inc/profile.class.php:115 58 | #: inc/profile.class.php:150 59 | msgid "Purchase request validation" 60 | msgstr "Purchase request validation" 61 | 62 | #: inc/notificationtargetpurchaserequest.class.php:68 63 | #: inc/notificationtargetpurchaserequest.class.php:119 64 | #: inc/purchaserequest.class.php:352 inc/purchaserequest.class.php:663 65 | #: inc/purchaserequest.class.php:904 inc/purchaserequest.class.php:962 66 | #: inc/purchaserequest.class.php:1105 67 | msgid "Due date" 68 | msgstr "Due date" 69 | 70 | #: inc/notificationtargetpurchaserequest.class.php:96 71 | msgid "Purchase request is validated" 72 | msgstr "Purchase request is validated" 73 | 74 | #: inc/notificationtargetpurchaserequest.class.php:100 75 | msgid "Purchase request canceled" 76 | msgstr "Purchase request canceled" 77 | 78 | #: inc/notificationtargetpurchaserequest.class.php:123 79 | msgid "Editor of validation" 80 | msgstr "Editor of validation" 81 | 82 | #: inc/notificationtargetpurchaserequest.class.php:278 83 | msgid "Validator of the purchase request" 84 | msgstr "Validator of the purchase request" 85 | 86 | #: inc/notificationtargetpurchaserequest.class.php:279 87 | msgid "Author of the purchase request" 88 | msgstr "Author of the purchase request" 89 | 90 | #: inc/purchaserequest.class.php:262 inc/purchaserequest.class.php:668 91 | #: inc/purchaserequest.class.php:909 92 | msgid "To be validated by" 93 | msgstr "To be validated by" 94 | 95 | #: inc/purchaserequest.class.php:434 inc/purchaserequest.class.php:709 96 | #: inc/purchaserequest.class.php:963 inc/purchaserequest.class.php:1106 97 | msgid "Treated on" 98 | msgstr "Treated on" 99 | 100 | #: inc/purchaserequest.class.php:678 101 | msgid "Linked to the order" 102 | msgstr "Linked to the order" 103 | 104 | #: inc/purchaserequest.class.php:688 105 | msgid "Linked to ticket" 106 | msgstr "Linked to ticket" 107 | 108 | #: inc/purchaserequest.class.php:703 109 | msgid "Treated" 110 | msgstr "Treated" 111 | 112 | #: inc/purchaserequest.class.php:790 113 | msgid "Add a purchase request" 114 | msgstr "Add a purchase request" 115 | 116 | #: inc/purchaserequest.class.php:805 117 | msgid "Validated by" 118 | msgstr "Validated by" 119 | 120 | #: inc/purchaserequest.class.php:1189 121 | msgid "Delete link with order" 122 | msgstr "Delete link with order" 123 | 124 | #: inc/purchaserequest.class.php:1206 125 | msgid "Do you approve this purchase request ?" 126 | msgstr "Do you approve this purchase request ?" 127 | 128 | #: inc/purchaserequest.class.php:1232 129 | msgid "Accept purchase request" 130 | msgstr "Accept purchase request" 131 | 132 | #: inc/purchaserequest.class.php:1237 133 | msgid "Refuse purchase request" 134 | msgstr "Refuse purchase request" 135 | 136 | #: inc/purchaserequest.class.php:1332 137 | msgid "Link to an order" 138 | msgstr "Link to an order" 139 | 140 | #: inc/purchaserequest.class.php:1333 141 | msgid "Delete link to order" 142 | msgstr "Delete link to order" 143 | 144 | #: inc/purchaserequest.class.php:1335 145 | msgid "Validate purchasing requests" 146 | msgstr "Validate purchasing requests" 147 | 148 | #: inc/purchaserequest.class.php:1436 149 | msgid "No groups for this user" 150 | msgstr "No groups for this user" 151 | 152 | #: inc/servicecatalog.class.php:62 153 | msgid "Validate your purchase requests" 154 | msgstr "Validate your purchase requests" 155 | 156 | #: inc/servicecatalog.class.php:140 157 | msgid "See your purchase requests to validate" 158 | msgstr "See your purchase requests to validate" 159 | 160 | #: inc/servicecatalog.class.php:143 161 | #, php-format 162 | msgid "You have %d purchase request to validate !" 163 | msgid_plural "You have %d purchase requests to validate !" 164 | msgstr[0] "You have %d purchase request to validate !" 165 | msgstr[1] "You have %d purchase requests to validate !" 166 | 167 | #~ msgid "This plugin requires GLPI 9.1 or higher" 168 | #~ msgstr "This plugin requires GLPI 9.1 or higher" 169 | -------------------------------------------------------------------------------- /locales/glpi.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR PurchaseRequest Development Team 3 | # This file is distributed under the same license as the GLPI - PurchaseRequest plugin package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: GLPI - PurchaseRequest plugin 2.1.1\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2025-09-21 14:55+0000\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 20 | 21 | #: hook.php:49 22 | msgid "Plugin installation or upgrade" 23 | msgstr "" 24 | 25 | #: hook.php:109 src/Purchaserequeststate.php:43 26 | msgid "Purchase request status" 27 | msgstr "" 28 | 29 | #: hook.php:199 30 | msgctxt "quantity" 31 | msgid "Number of purchase request" 32 | msgstr "" 33 | 34 | #: setup.php:121 src/Profile.php:63 src/Profile.php:174 35 | #: src/Purchaserequest.php:81 36 | msgid "Purchase request" 37 | msgid_plural "Purchase requests" 38 | msgstr[0] "" 39 | msgstr[1] "" 40 | 41 | #: front/config.form.php:63 42 | msgid "Please activate the plugin" 43 | msgstr "" 44 | 45 | #: front/purchaserequest.form.php:122 front/purchaserequest.php:65 46 | #: front/validation.form.php:70 src/Purchaserequest.php:168 47 | msgid "Please activate the plugin order" 48 | msgstr "" 49 | 50 | #: src/Config.php:66 51 | msgid "Plugin setup" 52 | msgstr "" 53 | 54 | #: src/Config.php:119 55 | msgid "Configuration purchase request" 56 | msgstr "" 57 | 58 | #: src/Config.php:122 59 | msgid "General Services Manager" 60 | msgstr "" 61 | 62 | #: src/Notificationtargetpurchaserequest.php:56 63 | msgid "Request for validation of the purchase request" 64 | msgstr "" 65 | 66 | #: src/Notificationtargetpurchaserequest.php:57 67 | msgid "Refusal of validation request" 68 | msgstr "" 69 | 70 | #: src/Notificationtargetpurchaserequest.php:58 71 | #: src/Notificationtargetpurchaserequest.php:117 src/Profile.php:136 72 | #: src/Profile.php:180 73 | msgid "Purchase request validation" 74 | msgstr "" 75 | 76 | #: src/Notificationtargetpurchaserequest.php:79 77 | #: src/Notificationtargetpurchaserequest.php:182 src/Purchaserequest.php:388 78 | #: src/Purchaserequest.php:585 src/Purchaserequest.php:879 79 | #: src/Purchaserequest.php:1179 src/Purchaserequest.php:1251 80 | #: src/Validation.php:460 81 | msgid "Amount" 82 | msgstr "" 83 | 84 | #: src/Notificationtargetpurchaserequest.php:82 85 | #: src/Notificationtargetpurchaserequest.php:183 src/Purchaserequest.php:594 86 | #: src/Purchaserequest.php:892 src/Purchaserequest.php:1191 87 | #: src/Purchaserequest.php:1252 src/Validation.php:469 88 | msgid "To be rebilled to the customer" 89 | msgstr "" 90 | 91 | #: src/Notificationtargetpurchaserequest.php:92 92 | #: src/Notificationtargetpurchaserequest.php:178 src/Purchaserequest.php:484 93 | #: src/Purchaserequest.php:864 src/Purchaserequest.php:1162 94 | #: src/Purchaserequest.php:1249 src/Purchaserequest.php:1409 95 | #: src/Validation.php:448 src/Validation.php:577 96 | msgid "Due date" 97 | msgstr "" 98 | 99 | #: src/Notificationtargetpurchaserequest.php:121 100 | msgid "Purchase request is validated" 101 | msgstr "" 102 | 103 | #: src/Notificationtargetpurchaserequest.php:125 104 | msgid "Purchase request canceled" 105 | msgstr "" 106 | 107 | #: src/Notificationtargetpurchaserequest.php:184 108 | msgid "Editor of validation" 109 | msgstr "" 110 | 111 | #: src/Notificationtargetpurchaserequest.php:355 112 | msgid "Validator of the purchase request" 113 | msgstr "" 114 | 115 | #: src/Notificationtargetpurchaserequest.php:356 116 | msgid "Author of the purchase request" 117 | msgstr "" 118 | 119 | #: src/Purchaserequest.php:389 src/Purchaserequest.php:869 120 | #: src/Purchaserequest.php:1167 src/Validation.php:453 121 | msgid "To be validated by" 122 | msgstr "" 123 | 124 | #: src/Purchaserequest.php:567 src/Purchaserequest.php:941 125 | #: src/Purchaserequest.php:1250 src/Purchaserequest.php:1410 126 | #: src/Validation.php:510 src/Validation.php:578 127 | msgid "Treated on" 128 | msgstr "" 129 | 130 | #: src/Purchaserequest.php:907 src/Validation.php:479 131 | msgid "Linked to the order" 132 | msgstr "" 133 | 134 | #: src/Purchaserequest.php:917 src/Validation.php:489 135 | msgid "Linked to ticket" 136 | msgstr "" 137 | 138 | #: src/Purchaserequest.php:935 src/Validation.php:504 139 | msgid "Treated" 140 | msgstr "" 141 | 142 | #: src/Purchaserequest.php:1027 143 | msgid "Add a purchase request" 144 | msgstr "" 145 | 146 | #: src/Purchaserequest.php:1044 147 | msgid "Validated by" 148 | msgstr "" 149 | 150 | #: src/Purchaserequest.php:1497 src/Validation.php:663 151 | msgid "Delete link with order" 152 | msgstr "" 153 | 154 | #: src/Purchaserequest.php:1515 155 | msgid "Do you approve this purchase request ?" 156 | msgstr "" 157 | 158 | #: src/Purchaserequest.php:1541 src/Validation.php:696 159 | msgid "Accept purchase request" 160 | msgstr "" 161 | 162 | #: src/Purchaserequest.php:1546 src/Validation.php:701 163 | msgid "Refuse purchase request" 164 | msgstr "" 165 | 166 | #: src/Purchaserequest.php:1645 167 | msgid "Link to an order" 168 | msgstr "" 169 | 170 | #: src/Purchaserequest.php:1646 171 | msgid "Delete link to order" 172 | msgstr "" 173 | 174 | #: src/Purchaserequest.php:1649 175 | msgid "Validate purchasing requests" 176 | msgstr "" 177 | 178 | #: src/Purchaserequest.php:1754 179 | msgid "No groups for this user" 180 | msgstr "" 181 | 182 | #: src/Servicecatalog.php:70 src/Servicecatalog.php:81 183 | msgid "Validate your purchase requests" 184 | msgstr "" 185 | 186 | #: src/Servicecatalog.php:204 187 | msgid "See your purchase requests to validate" 188 | msgstr "" 189 | 190 | #: src/Servicecatalog.php:207 191 | #, php-format 192 | msgid "You have %d purchase request to validate !" 193 | msgid_plural "You have %d purchase requests to validate !" 194 | msgstr[0] "" 195 | msgstr[1] "" 196 | 197 | #: src/Threshold.php:64 198 | msgid "Purchase threshold" 199 | msgid_plural "Purchase thresholds" 200 | msgstr[0] "" 201 | msgstr[1] "" 202 | 203 | #: src/Validation.php:74 204 | msgid "Validation" 205 | msgid_plural "Validations" 206 | msgstr[0] "" 207 | msgstr[1] "" 208 | 209 | #: src/Validation.php:786 210 | msgid "Approvals for the purchase request" 211 | msgstr "" 212 | -------------------------------------------------------------------------------- /src/Threshold.php: -------------------------------------------------------------------------------- 1 | . 20 | -------------------------------------------------------------------------- 21 | @package purchaserequest 22 | @author the purchaserequest plugin team 23 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 24 | @license GPLv2+ 25 | http://www.gnu.org/licenses/gpl.txt 26 | @link https://github.com/InfotelGLPI/purchaserequest 27 | @link http://www.glpi-project.org/ 28 | @since 2009 29 | ---------------------------------------------------------------------- */ 30 | 31 | namespace GlpiPlugin\Purchaserequest; 32 | 33 | use CommonDBTM; 34 | use CommonGLPI; 35 | use DbUtils; 36 | use Html; 37 | use Migration; 38 | 39 | if (!defined('GLPI_ROOT')) { 40 | die("Sorry. You can't access directly to this file"); 41 | } 42 | 43 | /** 44 | * Class Threshold 45 | */ 46 | class Threshold extends CommonDBTM 47 | { 48 | public static $rightname = 'plugin_purchaserequest_purchaserequest'; 49 | public $dohistory = true; 50 | 51 | 52 | public static $list_type_allowed = ["ComputerType", "MonitorType", "PeripheralType", "NetworkEquipmentType", "PrinterType", 53 | "PhoneType", "ConsumableItemType", "CartridgeItemType", "ContractType", "PluginOrderOtherType", 54 | "SoftwareLicenseType", "CertificateType", "RackType", "PduType",]; 55 | 56 | 57 | /** 58 | * @param int $nb 59 | * 60 | * @return string|\translated 61 | */ 62 | public static function getTypeName($nb = 0) 63 | { 64 | return _n("Purchase threshold", "Purchase thresholds", $nb, "purchaserequest"); 65 | } 66 | 67 | 68 | /** 69 | * @param array $options 70 | * 71 | * @return array 72 | */ 73 | public function defineTabs($options = []) 74 | { 75 | $ong = []; 76 | $this->addDefaultFormTab($ong); 77 | 78 | return $ong; 79 | } 80 | 81 | /** 82 | * @param CommonGLPI $item 83 | * @param int $withtemplate 84 | * 85 | * @return string|\translated 86 | */ 87 | public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) 88 | { 89 | 90 | return self::createTabEntry($this->getTypeName(1)); 91 | 92 | } 93 | 94 | public static function getIcon() 95 | { 96 | return "ti ti-basket"; 97 | } 98 | 99 | 100 | /** 101 | * @param CommonGLPI $item 102 | * @param int $tabnum 103 | * @param int $withtemplate 104 | * 105 | * @return bool 106 | */ 107 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) 108 | { 109 | $type = $item->getType(); 110 | 111 | if (in_array($item->getType(), self::$list_type_allowed)) { 112 | $threshold = new self(); 113 | $threshold->getEmpty(); 114 | $threshold->getFromDBByCrit(["itemtype" => $item->getType(), 115 | "items_id" => $item->getID()]); 116 | $threshold->showThresholdForm($threshold->getID(), $item); 117 | } 118 | 119 | return true; 120 | } 121 | 122 | 123 | /** 124 | * @param $ID 125 | * @param array $options 126 | * @param item $item 127 | * 128 | * @return bool 129 | */ 130 | public function showThresholdForm($ID, $item, $options = []) 131 | { 132 | 133 | $this->initForm($ID, $options); 134 | $this->showFormHeader($options); 135 | 136 | $canedit = $this->can($ID, UPDATE); 137 | $options['canedit'] = $canedit; 138 | 139 | // Data saved in session 140 | if (isset($_SESSION['glpi_plugin_thresholds_fields'])) { 141 | foreach ($_SESSION['glpi_plugin_thresholds_fields'] as $key => $value) { 142 | $this->fields[$key] = $value; 143 | } 144 | unset($_SESSION['glpi_plugin_thresholds_fields']); 145 | } 146 | 147 | /* title */ 148 | echo ""; 149 | echo "" . $this->getTypeName(1) . ""; 150 | if ($canedit) { 151 | echo Html::input('thresholds', ['value' => $this->fields['thresholds'], 'size' => 40]); 152 | } else { 153 | echo $this->fields["thresholds"]; 154 | } 155 | echo ""; 156 | 157 | echo Html::hidden('itemtype', ['value' => $item->getType()]); 158 | echo Html::hidden('items_id', ['value' => $item->getID()]); 159 | echo Html::hidden('id', ['value' => $ID]); 160 | 161 | if ($canedit) { 162 | $this->showFormButtons($options); 163 | } else { 164 | echo ""; 165 | Html::closeForm(); 166 | } 167 | 168 | return true; 169 | } 170 | 171 | 172 | /** 173 | * @param Migration $migration 174 | */ 175 | public static function install(Migration $migration) 176 | { 177 | global $DB; 178 | 179 | $dbu = new DbUtils(); 180 | $table = $dbu->getTableForItemType(__CLASS__); 181 | 182 | if (!$DB->tableExists($table)) { 183 | $migration->displayMessage("Installing $table"); 184 | $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_purchaserequest_thresholds` ( 185 | `id` int unsigned NOT NULL AUTO_INCREMENT, 186 | `itemtype` VARCHAR(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 187 | `items_id` int unsigned NOT NULL DEFAULT '0', 188 | `thresholds` int unsigned NOT NULL DEFAULT '0', 189 | PRIMARY KEY (`id`) 190 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;"; 191 | $DB->doQuery($query) or die($DB->error()); 192 | 193 | } else { 194 | 195 | } 196 | 197 | } 198 | 199 | public static function uninstall() 200 | { 201 | global $DB; 202 | 203 | $dbu = new DbUtils(); 204 | $table = $dbu->getTableForItemType(__CLASS__); 205 | $DB->doQuery("DROP TABLE IF EXISTS`" . $table . "`") or die($DB->error()); 206 | } 207 | 208 | 209 | public static function getObject($type) 210 | { 211 | return $type . "Type"; 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/Servicecatalog.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | namespace GlpiPlugin\Purchaserequest; 31 | 32 | use CommonGLPI; 33 | use CommonITILValidation; 34 | use DbUtils; 35 | use Session; 36 | use Toolbox; 37 | 38 | if (!defined('GLPI_ROOT')) { 39 | die("Sorry. You can't access directly to this file"); 40 | } 41 | 42 | 43 | /** 44 | * Class Servicecatalog 45 | */ 46 | class Servicecatalog extends CommonGLPI { 47 | 48 | static $rightname = 'plugin_purchaserequest_purchaserequest'; 49 | 50 | var $dohistory = false; 51 | 52 | /** 53 | * @return bool 54 | */ 55 | static function canUse() { 56 | return Session::haveRight(self::$rightname, UPDATE); 57 | } 58 | 59 | /** 60 | * @return string|\translated 61 | */ 62 | static function getMenuTitle() { 63 | 64 | $btstyle = ""; 65 | $nb = self::countPurchasesToValidate(); 66 | if ($nb > 0) { 67 | $btstyle = "style='color: firebrick;'"; 68 | } 69 | // if (Session::getCurrentInterface() == 'central') { 70 | return "" . __('Validate your purchase requests', 'purchaserequest') . ""; 71 | // } else { 72 | // return __('Validate your purchase requests', 'purchaserequest'); 73 | // } 74 | } 75 | 76 | /** 77 | * @return string|\translated 78 | */ 79 | static function getAhrefTitle() { 80 | 81 | return __('Validate your purchase requests', 'purchaserequest'); 82 | } 83 | 84 | /** 85 | * @return string 86 | * @throws \GlpitestSQLError 87 | */ 88 | static function getLeftMenuLogoCss() { 89 | 90 | $addstyle = ""; 91 | $nb = self::countPurchasesToValidate(); 92 | if ($nb > 0) { 93 | $addstyle = "color:firebrick;"; 94 | } 95 | return $addstyle; 96 | 97 | } 98 | 99 | /** 100 | * @return string 101 | */ 102 | static function getMenuLink() { 103 | global $CFG_GLPI; 104 | 105 | $options['reset'] = 'reset'; 106 | $options['criteria'][0]['field'] = 8; // status 107 | $options['criteria'][0]['searchtype'] = 'equals'; 108 | $options['criteria'][0]['value'] = CommonITILValidation::WAITING; 109 | $options['criteria'][0]['link'] = 'AND'; 110 | 111 | $options['criteria'][1]['field'] = 5; // users_id_validate 112 | $options['criteria'][1]['searchtype'] = 'equals'; 113 | $options['criteria'][1]['value'] = Session::getLoginUserID(); 114 | $options['criteria'][1]['link'] = 'AND'; 115 | 116 | return PLUGIN_PURCHASEREQUEST_WEBDIR . "/front/purchaserequest.php?" . Toolbox::append_params($options, '&'); 117 | } 118 | 119 | /** 120 | * @return string 121 | */ 122 | static function getNavBarLink() { 123 | global $CFG_GLPI; 124 | 125 | $options['reset'] = 'reset'; 126 | $options['criteria'][0]['field'] = 8; // status 127 | $options['criteria'][0]['searchtype'] = 'equals'; 128 | $options['criteria'][0]['value'] = CommonITILValidation::WAITING; 129 | $options['criteria'][0]['link'] = 'AND'; 130 | 131 | $options['criteria'][1]['field'] = 5; // users_id_validate 132 | $options['criteria'][1]['searchtype'] = 'equals'; 133 | $options['criteria'][1]['value'] = Session::getLoginUserID(); 134 | $options['criteria'][1]['link'] = 'AND'; 135 | 136 | return PLUGIN_PURCHASEREQUEST_WEBDIR . "/front/purchaserequest.php?" . Toolbox::append_params($options, '&'); 137 | } 138 | 139 | /** 140 | * @return string 141 | * @throws \GlpitestSQLError 142 | */ 143 | static function countPurchasesToValidate() { 144 | global $DB; 145 | 146 | $dbu = new DbUtils(); 147 | $nb = 0; 148 | 149 | $criteria = [ 150 | 'SELECT' => 'glpi_plugin_purchaserequest_purchaserequests.id', 151 | 'DISTINCT' => true, 152 | 'FROM' => 'glpi_plugin_purchaserequest_purchaserequests', 153 | 'WHERE' => [ 154 | 'users_id_validate' => Session::getLoginUserID(), 155 | 'status' => CommonITILValidation::WAITING, 156 | ] 157 | ]; 158 | $criteria['WHERE'] = $criteria['WHERE'] + getEntitiesRestrictCriteria( 159 | 'glpi_plugin_purchaserequest_purchaserequests' 160 | ); 161 | 162 | $iterator = $DB->request($criteria); 163 | 164 | if (count($iterator) > 0) { 165 | $nb = count($iterator); 166 | } 167 | 168 | 169 | return $nb; 170 | 171 | } 172 | 173 | /** 174 | * @return string 175 | * @throws \GlpitestSQLError 176 | */ 177 | static function getMenuLogoCss() { 178 | 179 | $addstyle = ""; 180 | $nb = self::countPurchasesToValidate(); 181 | if ($nb > 0) { 182 | $addstyle = "style='color:firebrick;'"; 183 | } 184 | return $addstyle; 185 | 186 | } 187 | 188 | /** 189 | * @return string 190 | * @throws \GlpitestSQLError 191 | */ 192 | static function getMenuLogo() { 193 | 194 | return PurchaseRequest::getIcon(); 195 | 196 | } 197 | 198 | /** 199 | * @return string|\translated 200 | */ 201 | static function getMenuComment() { 202 | 203 | $nb = self::countPurchasesToValidate(); 204 | $comments = __('See your purchase requests to validate', 'purchaserequest'); 205 | if ($nb > 0) { 206 | $comments = ""; 207 | $comments .= sprintf(_n('You have %d purchase request to validate !', 'You have %d purchase requests to validate !', $nb, 'servicecatalog'), $nb); 208 | $comments .= ""; 209 | } 210 | 211 | 212 | return $comments; 213 | 214 | } 215 | 216 | /** 217 | * @return string 218 | */ 219 | static function getLinkList() { 220 | return ""; 221 | } 222 | 223 | /** 224 | * @return string 225 | */ 226 | static function getList() { 227 | return ""; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /locales/fr_FR.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR PurchaseRequest Development Team 3 | # This file is distributed under the same license as the GLPI - PurchaseRequest plugin package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | # Translators: 7 | # Xavier CAILLAUD , 2021 8 | # 9 | #, fuzzy 10 | msgid "" 11 | msgstr "" 12 | "Project-Id-Version: GLPI - PurchaseRequest plugin 2.1.1\n" 13 | "Report-Msgid-Bugs-To: \n" 14 | "POT-Creation-Date: 2021-12-21 08:18+0000\n" 15 | "PO-Revision-Date: 2021-05-27 08:40+0000\n" 16 | "Last-Translator: Xavier CAILLAUD , 2021\n" 17 | "Language-Team: French (France) (https://www.transifex.com/infotelGLPI/teams/121073/fr_FR/)\n" 18 | "MIME-Version: 1.0\n" 19 | "Content-Type: text/plain; charset=UTF-8\n" 20 | "Content-Transfer-Encoding: 8bit\n" 21 | "Language: fr_FR\n" 22 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 23 | 24 | #: hook.php:45 25 | msgid "Plugin installation or upgrade" 26 | msgstr "Installation ou mise à jour du plugin" 27 | 28 | #: hook.php:114 inc/purchaserequeststate.class.php:37 29 | msgid "Purchase request status" 30 | msgstr "Statut de la demande d'achat" 31 | 32 | #: hook.php:195 33 | msgctxt "quantity" 34 | msgid "Number of purchase request" 35 | msgstr "Nombre de demande d'achats" 36 | 37 | #: setup.php:112 inc/menu.class.php:33 inc/profile.class.php:63 38 | #: inc/profile.class.php:163 inc/purchaserequest.class.php:50 39 | msgid "Purchase request" 40 | msgid_plural "Purchase requests" 41 | msgstr[0] "Demande d'achat" 42 | msgstr[1] "Demande d'achats" 43 | 44 | #: front/config.form.php:64 45 | msgid "Please activate the plugin" 46 | msgstr "S’il vous plaît activer le plugin" 47 | 48 | #: front/purchaserequest.form.php:125 front/purchaserequest.php:64 49 | #: front/validation.form.php:73 inc/purchaserequest.class.php:133 50 | msgid "Please activate the plugin order" 51 | msgstr "Merci d'activer le plugin gestion de commandes" 52 | 53 | #: inc/config.class.php:53 54 | msgid "Plugin setup" 55 | msgstr "Configuration du plugin" 56 | 57 | #: inc/config.class.php:97 58 | msgid "Configuration purchase request" 59 | msgstr "Configurer la demande d'achat" 60 | 61 | #: inc/config.class.php:100 62 | msgid "General Services Manager" 63 | msgstr "Responsable des services généraux" 64 | 65 | #: inc/notificationtargetpurchaserequest.class.php:42 66 | msgid "Request for validation of the purchase request" 67 | msgstr "Demande de validation de la demande d’achat" 68 | 69 | #: inc/notificationtargetpurchaserequest.class.php:43 70 | msgid "Refusal of validation request" 71 | msgstr "Refus de la demande de validation" 72 | 73 | #: inc/notificationtargetpurchaserequest.class.php:44 74 | #: inc/notificationtargetpurchaserequest.class.php:103 75 | #: inc/profile.class.php:126 inc/profile.class.php:169 76 | msgid "Purchase request validation" 77 | msgstr "Validation de la demande d'achat" 78 | 79 | #: inc/notificationtargetpurchaserequest.class.php:65 80 | #: inc/notificationtargetpurchaserequest.class.php:168 81 | #: inc/purchaserequest.class.php:330 inc/purchaserequest.class.php:523 82 | #: inc/purchaserequest.class.php:792 inc/purchaserequest.class.php:1057 83 | #: inc/purchaserequest.class.php:1118 inc/validation.class.php:405 84 | msgid "Amount" 85 | msgstr "Montant" 86 | 87 | #: inc/notificationtargetpurchaserequest.class.php:68 88 | #: inc/notificationtargetpurchaserequest.class.php:169 89 | #: inc/purchaserequest.class.php:532 inc/purchaserequest.class.php:797 90 | #: inc/purchaserequest.class.php:1062 inc/purchaserequest.class.php:1119 91 | #: inc/validation.class.php:410 92 | msgid "To be rebilled to the customer" 93 | msgstr "A refacturer au client" 94 | 95 | #: inc/notificationtargetpurchaserequest.class.php:78 96 | #: inc/notificationtargetpurchaserequest.class.php:164 97 | #: inc/purchaserequest.class.php:422 inc/purchaserequest.class.php:780 98 | #: inc/purchaserequest.class.php:1043 inc/purchaserequest.class.php:1116 99 | #: inc/purchaserequest.class.php:1265 inc/validation.class.php:393 100 | #: inc/validation.class.php:518 101 | msgid "Due date" 102 | msgstr "Date d'échéance" 103 | 104 | #: inc/notificationtargetpurchaserequest.class.php:107 105 | msgid "Purchase request is validated" 106 | msgstr "La demande d’achat est validée" 107 | 108 | #: inc/notificationtargetpurchaserequest.class.php:111 109 | msgid "Purchase request canceled" 110 | msgstr "Demande d'achat annulée" 111 | 112 | #: inc/notificationtargetpurchaserequest.class.php:170 113 | msgid "Editor of validation" 114 | msgstr "Editeur de la validation" 115 | 116 | #: inc/notificationtargetpurchaserequest.class.php:340 117 | msgid "Validator of the purchase request" 118 | msgstr "Valideur de la demande d'achat" 119 | 120 | #: inc/notificationtargetpurchaserequest.class.php:341 121 | msgid "Author of the purchase request" 122 | msgstr "Auteur de la demande d'achat" 123 | 124 | #: inc/purchaserequest.class.php:331 inc/purchaserequest.class.php:785 125 | #: inc/purchaserequest.class.php:1048 inc/validation.class.php:398 126 | msgid "To be validated by" 127 | msgstr "A valider par" 128 | 129 | #: inc/purchaserequest.class.php:505 inc/purchaserequest.class.php:845 130 | #: inc/purchaserequest.class.php:1117 inc/purchaserequest.class.php:1266 131 | #: inc/validation.class.php:451 inc/validation.class.php:519 132 | msgid "Treated on" 133 | msgstr "Traité le" 134 | 135 | #: inc/purchaserequest.class.php:811 inc/validation.class.php:420 136 | msgid "Linked to the order" 137 | msgstr "Liée à la commande" 138 | 139 | #: inc/purchaserequest.class.php:821 inc/validation.class.php:430 140 | msgid "Linked to ticket" 141 | msgstr "Liée au ticket" 142 | 143 | #: inc/purchaserequest.class.php:839 inc/validation.class.php:445 144 | msgid "Treated" 145 | msgstr "Traité" 146 | 147 | #: inc/purchaserequest.class.php:927 148 | msgid "Add a purchase request" 149 | msgstr "Ajouter une demande d'achat" 150 | 151 | #: inc/purchaserequest.class.php:942 152 | msgid "Validated by" 153 | msgstr "Validé par" 154 | 155 | #: inc/purchaserequest.class.php:1349 inc/validation.class.php:602 156 | msgid "Delete link with order" 157 | msgstr "Supprimer le lien avec la commande" 158 | 159 | #: inc/purchaserequest.class.php:1366 160 | msgid "Do you approve this purchase request ?" 161 | msgstr "Validez-vous la demande d'achat ?" 162 | 163 | #: inc/purchaserequest.class.php:1392 inc/validation.class.php:635 164 | msgid "Accept purchase request" 165 | msgstr "Valider la demande d'achat" 166 | 167 | #: inc/purchaserequest.class.php:1397 inc/validation.class.php:640 168 | msgid "Refuse purchase request" 169 | msgstr "Refuser la demande d'achat" 170 | 171 | #: inc/purchaserequest.class.php:1492 172 | msgid "Link to an order" 173 | msgstr "Lier à une commande" 174 | 175 | #: inc/purchaserequest.class.php:1493 176 | msgid "Delete link to order" 177 | msgstr "Supprimer le lien à la commande" 178 | 179 | #: inc/purchaserequest.class.php:1495 180 | msgid "Validate purchasing requests" 181 | msgstr "Valider les demandes d'achats" 182 | 183 | #: inc/purchaserequest.class.php:1597 184 | msgid "No groups for this user" 185 | msgstr "Pas de groupes pour cet utilisateur" 186 | 187 | #: inc/servicecatalog.class.php:62 inc/servicecatalog.class.php:73 188 | msgid "Validate your purchase requests" 189 | msgstr "Valider vos demandes d’achat" 190 | 191 | #: inc/servicecatalog.class.php:186 192 | msgid "See your purchase requests to validate" 193 | msgstr "Voir les demandes d’achat à valider" 194 | 195 | #: inc/servicecatalog.class.php:189 196 | #, php-format 197 | msgid "You have %d purchase request to validate !" 198 | msgid_plural "You have %d purchase requests to validate !" 199 | msgstr[0] "Vous avez %d demande d'achat à valider !" 200 | msgstr[1] "Vous avez %d demandes d'achats à valider !" 201 | 202 | #: inc/threshold.class.php:53 203 | msgid "Purchase threshold" 204 | msgid_plural "Purchase thresholds" 205 | msgstr[0] "Seuil d'achat" 206 | msgstr[1] "Seuils d'achat" 207 | 208 | #: inc/validation.class.php:50 209 | msgid "Validation" 210 | msgid_plural "Validations" 211 | msgstr[0] "Validation" 212 | msgstr[1] "Validations" 213 | 214 | #: inc/validation.class.php:724 215 | msgid "Approvals for the purchase request" 216 | msgstr "Validations de la demande d'achat" 217 | -------------------------------------------------------------------------------- /hook.php: -------------------------------------------------------------------------------- 1 | . 20 | -------------------------------------------------------------------------- 21 | @package purchaserequest 22 | @author the purchaserequest plugin team 23 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 24 | @license GPLv2+ 25 | http://www.gnu.org/licenses/gpl.txt 26 | @link https://github.com/InfotelGLPI/purchaserequest 27 | @link http://www.glpi-project.org/ 28 | @since 2009 29 | ---------------------------------------------------------------------- */ 30 | 31 | use GlpiPlugin\Purchaserequest\Config; 32 | use GlpiPlugin\Purchaserequest\NotificationTargetPurchaseRequest; 33 | use GlpiPlugin\Purchaserequest\Profile; 34 | use GlpiPlugin\Purchaserequest\PurchaseRequest; 35 | use GlpiPlugin\Purchaserequest\PurchaseRequestState; 36 | use GlpiPlugin\Purchaserequest\Threshold; 37 | use GlpiPlugin\Purchaserequest\Validation; 38 | 39 | /** 40 | * Plugin install process 41 | * 42 | * @return boolean 43 | */ 44 | function plugin_purchaserequest_install() 45 | { 46 | global $DB; 47 | 48 | echo "
"; 49 | echo ""; 50 | echo ""; 51 | 52 | echo ""; 53 | echo ""; 68 | echo ""; 69 | echo "
" . __("Plugin installation or upgrade", "purchaserequest") . "
"; 54 | 55 | $migration = new Migration(PLUGIN_PURCHASEREQUEST_VERSION); 56 | $classes = [NotificationTargetPurchaseRequest::class, 57 | PurchaseRequest::class, 58 | Config::class, 59 | Threshold::class, 60 | Validation::class, 61 | PurchaseRequestState::class]; 62 | 63 | foreach ($classes as $class) { 64 | call_user_func([$class, 'install'], $migration); 65 | } 66 | 67 | echo "
"; 70 | 71 | //DisplayPreferences Migration 72 | $classes = ['PluginPurchaserequestPurchaserequest' => Purchaserequest::class]; 73 | 74 | foreach ($classes as $old => $new) { 75 | $displayusers = $DB->request([ 76 | 'SELECT' => [ 77 | 'users_id' 78 | ], 79 | 'DISTINCT' => true, 80 | 'FROM' => 'glpi_displaypreferences', 81 | 'WHERE' => [ 82 | 'itemtype' => $old, 83 | ], 84 | ]); 85 | 86 | if (count($displayusers) > 0) { 87 | foreach ($displayusers as $displayuser) { 88 | $iterator = $DB->request([ 89 | 'SELECT' => [ 90 | 'num', 91 | 'id' 92 | ], 93 | 'FROM' => 'glpi_displaypreferences', 94 | 'WHERE' => [ 95 | 'itemtype' => $old, 96 | 'users_id' => $displayuser['users_id'], 97 | 'interface' => 'central' 98 | ], 99 | ]); 100 | 101 | if (count($iterator) > 0) { 102 | foreach ($iterator as $data) { 103 | $iterator2 = $DB->request([ 104 | 'SELECT' => [ 105 | 'id' 106 | ], 107 | 'FROM' => 'glpi_displaypreferences', 108 | 'WHERE' => [ 109 | 'itemtype' => $new, 110 | 'users_id' => $displayuser['users_id'], 111 | 'num' => $data['num'], 112 | 'interface' => 'central' 113 | ], 114 | ]); 115 | if (count($iterator2) > 0) { 116 | foreach ($iterator2 as $dataid) { 117 | $query = $DB->buildDelete( 118 | 'glpi_displaypreferences', 119 | [ 120 | 'id' => $dataid['id'], 121 | ] 122 | ); 123 | $DB->doQuery($query); 124 | } 125 | } else { 126 | $query = $DB->buildUpdate( 127 | 'glpi_displaypreferences', 128 | [ 129 | 'itemtype' => $new, 130 | ], 131 | [ 132 | 'id' => $data['id'], 133 | ] 134 | ); 135 | $DB->doQuery($query); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | Profile::initProfile(); 144 | Profile::createFirstAccess($_SESSION['glpiactiveprofile']['id']); 145 | 146 | return true; 147 | } 148 | 149 | /** 150 | * Plugin uninstall process 151 | * 152 | * @return boolean 153 | */ 154 | function plugin_purchaserequest_uninstall() 155 | { 156 | 157 | 158 | $classes = [NotificationTargetPurchaseRequest::class, 159 | PurchaseRequest::class, 160 | Config::class, 161 | Threshold::class, 162 | Validation::class, 163 | PurchaseRequestState::class]; 164 | foreach ($classes as $class) { 165 | call_user_func([$class, 'uninstall']); 166 | } 167 | 168 | //Delete rights associated with the plugin 169 | $profileRight = new ProfileRight(); 170 | foreach (Profile::getAllRights() as $right) { 171 | $profileRight->deleteByCriteria(['name' => $right['field']]); 172 | } 173 | 174 | return true; 175 | } 176 | 177 | /* define dropdown tables to be manage in GLPI : */ 178 | function plugin_purchaserequest_getDropdown() 179 | { 180 | /* table => name */ 181 | if (Plugin::isPluginActive("purchaserequest")) { 182 | return [PurchaseRequestState::class => __("Purchase request status", "purchaserequest")]; 183 | } else { 184 | return []; 185 | } 186 | } 187 | 188 | /* define dropdown relations */ 189 | function plugin_purchaserequest_getDatabaseRelations() 190 | { 191 | 192 | if (Plugin::isPluginActive("purchaserequest")) { 193 | return ["glpi_entities" => ["glpi_plugin_purchaserequest_purchaserequests" => "entities_id"], 194 | "glpi_profiles" => ["glpi_plugin_purchaserequest_profiles" => "profiles_id"], 195 | "glpi_users" => ["glpi_plugin_purchaserequest_purchaserequests" => "users_id", 196 | "glpi_plugin_purchaserequest_purchaserequests" => "users_id_validate", 197 | "glpi_plugin_purchaserequest_purchaserequests" => "users_id_creator"], 198 | "glpi_groups" => ["glpi_plugin_purchaserequest_purchaserequests" => "groups_id"], 199 | "glpi_tickets" => ["glpi_plugin_purchaserequest_purchaserequests" => "tickets_id"], 200 | // "glpi_plugin_purchaserequest_purchaserequeststates" => [ 201 | // "glpi_plugin_purchaserequest_purchaserequests" => "plugin_purchaserequest_purchaserequeststates_id"] 202 | ]; 203 | } else { 204 | return []; 205 | } 206 | } 207 | 208 | function plugin_purchaserequest_addSelect($type, $ID, $num) 209 | { 210 | 211 | $searchopt = Search::getOptions($type); 212 | $table = $searchopt[$ID]["table"]; 213 | $field = $searchopt[$ID]["field"]; 214 | 215 | if ($table == "glpi_plugin_purchaserequest_purchaserequests" 216 | && $field == "types_id") { 217 | return "`$table`.`itemtype`, `$table`.`$field` AS `ITEM_$num`, "; 218 | } else { 219 | return ""; 220 | } 221 | } 222 | 223 | /* display custom fields in the search */ 224 | function plugin_purchaserequest_giveItem($type, $ID, $data, $num) 225 | { 226 | global $CFG_GLPI; 227 | 228 | $searchopt = Search::getOptions($type); 229 | $table = $searchopt[$ID]["table"]; 230 | $field = $searchopt[$ID]["field"]; 231 | $dbu = new DbUtils(); 232 | switch ($table . '.' . $field) { 233 | /* display associated items with order */ 234 | case "glpi_plugin_purchaserequest_purchaserequests.types_id": 235 | $file = ""; 236 | if (isset($data['raw']["itemtype"]) && $data['raw']["itemtype"] == 'PluginOrderOther') { 237 | $file = $CFG_GLPI['root_doc'] . "/plugins/order/inc/othertype.class.php"; 238 | } elseif (isset($data['raw']["itemtype"])) { 239 | $file = GLPI_ROOT . "/src/" . $data['raw']["itemtype"] . "Type.php"; 240 | } 241 | if (file_exists($file)) { 242 | return Dropdown::getDropdownName( 243 | $dbu->getTableForItemType($data["itemtype"] . "Type"), 244 | $data['raw']["ITEM_" . $num] 245 | ); 246 | } else { 247 | return " "; 248 | } 249 | break; 250 | case "glpi_plugin_purchaserequest_purchaserequests.plugin_order_orders_id": 251 | $order = new PluginOrderOrder(); 252 | if ($order->getFromDB($data['raw']["ITEM_" . $num])) { 253 | return $order->getLink(); 254 | } else { 255 | return " "; 256 | } 257 | 258 | break; 259 | } 260 | } 261 | 262 | 263 | function plugin_purchaserequest_getAddSearchOptions($itemtype) 264 | { 265 | 266 | $sopt = []; 267 | 268 | if ($itemtype == 'Ticket') { 269 | if (Session::haveRight('plugin_purchaserequest_purchaserequest', READ)) { 270 | $sopt[22227]['table'] = 'glpi_plugin_purchaserequest_purchaserequests'; 271 | $sopt[22227]['field'] = 'id'; 272 | $sopt[22227]['name'] = _x('quantity', 'Number of purchase request', 'purchaserequest'); 273 | $sopt[22227]['forcegroupby'] = true; 274 | $sopt[22227]['usehaving'] = true; 275 | $sopt[22227]['datatype'] = 'count'; 276 | $sopt[22227]['massiveaction'] = false; 277 | $sopt[22227]['joinparams'] = ['jointype' => 'child']; 278 | } 279 | } 280 | return $sopt; 281 | } 282 | 283 | /** 284 | * @param $type 285 | * @param $ID 286 | * @param $data 287 | * @param $num 288 | * 289 | * @return string 290 | */ 291 | function plugin_purchaserequest_displayConfigItem($type, $ID, $data, $num) 292 | { 293 | 294 | $searchopt = Search::getOptions($type); 295 | $table = $searchopt[$ID]["table"]; 296 | $field = $searchopt[$ID]["field"]; 297 | 298 | switch ($table . '.' . $field) { 299 | case "glpi_plugin_purchaserequest_purchaserequests.status": 300 | $status_color = CommonITILValidation::getStatusColor($data[$num][0]['name']); 301 | return " class=\"shadow-none\" style=\"background-color:" . $status_color . ";\" "; 302 | break; 303 | } 304 | return ""; 305 | } 306 | -------------------------------------------------------------------------------- /src/Profile.php: -------------------------------------------------------------------------------- 1 | . 20 | -------------------------------------------------------------------------- 21 | @package purchaserequest 22 | @author the purchaserequest plugin team 23 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 24 | @license GPLv2+ 25 | http://www.gnu.org/licenses/gpl.txt 26 | @link https://github.com/InfotelGLPI/purchaserequest 27 | @link http://www.glpi-project.org/ 28 | @since 2009 29 | ---------------------------------------------------------------------- */ 30 | 31 | namespace GlpiPlugin\Purchaserequest; 32 | 33 | use CommonGLPI; 34 | use DbUtils; 35 | use Html; 36 | use ProfileRight; 37 | use Session; 38 | 39 | if (!defined('GLPI_ROOT')) { 40 | die("Sorry. You can't access directly to this file"); 41 | } 42 | 43 | /** 44 | * Class Profile 45 | * 46 | * This class manages the profile rights of the plugin 47 | */ 48 | class Profile extends \Profile 49 | { 50 | /** 51 | * @param int $nb 52 | * 53 | * @return string 54 | */ 55 | public static function getTypeName($nb = 0) 56 | { 57 | return self::createTabEntry(__('Rights management')); 58 | } 59 | 60 | public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) 61 | { 62 | if ($item->getType() == 'Profile') { 63 | return self::createTabEntry(_n("Purchase request", "Purchase requests", 2, "purchaserequest")); 64 | } 65 | return ''; 66 | } 67 | 68 | public static function getIcon() 69 | { 70 | return "ti ti-basket"; 71 | } 72 | 73 | 74 | /** 75 | * display tab content for item 76 | * 77 | * @param CommonGLPI $item 78 | * @param type $tabnum 79 | * @param type $withtemplate 80 | * 81 | * @return boolean 82 | * @global type $CFG_GLPI 83 | */ 84 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) 85 | { 86 | 87 | if ($item->getType() == 'Profile') { 88 | $ID = $item->getID(); 89 | $prof = new self(); 90 | 91 | self::addDefaultProfileInfos( 92 | $ID, 93 | ['plugin_purchaserequest_purchaserequest' => 0, 94 | 'plugin_purchaserequest_validate' => 0, 95 | 'plugin_purchaserequest_config' => 0, 96 | ] 97 | ); 98 | $prof->showForm($ID); 99 | 100 | } 101 | 102 | return true; 103 | } 104 | 105 | /** 106 | * show profile form 107 | * 108 | * @param type $ID 109 | * @param type $options 110 | * 111 | * @return boolean 112 | */ 113 | public function showForm($profiles_id = 0, $openform = true, $closeform = true) 114 | { 115 | 116 | echo "
"; 117 | if (($canedit = Session::haveRightsOr(self::$rightname, [UPDATE, PURGE])) 118 | && $openform) { 119 | $profile = new \Profile(); 120 | echo ""; 121 | } 122 | 123 | $profile = new \Profile(); 124 | $profile->getFromDB($profiles_id); 125 | 126 | $rights = $this->getAllRights(); 127 | $profile->displayRightsChoiceMatrix($rights, ['canedit' => $canedit, 128 | 'default_class' => 'tab_bg_2', 129 | 'title' => __('General')]); 130 | 131 | echo ""; 132 | echo "\n"; 133 | 134 | $effective_rights = ProfileRight::getProfileRights($profiles_id, ['plugin_purchaserequest_validate']); 135 | echo ""; 136 | echo ""; 137 | echo "\n"; 141 | $effective_rights = ProfileRight::getProfileRights($profiles_id, ['plugin_purchaserequest_config']); 142 | echo ""; 143 | echo ""; 144 | echo "\n"; 148 | echo "
" . __('Helpdesk') . "
" . __("Purchase request validation", "purchaserequest") . ""; 138 | Html::showCheckbox(['name' => '_plugin_purchaserequest_validate', 139 | 'checked' => $effective_rights['plugin_purchaserequest_validate']]); 140 | echo "
" . __("Setup") . ""; 145 | Html::showCheckbox(['name' => '_plugin_purchaserequest_config', 146 | 'checked' => $effective_rights['plugin_purchaserequest_config']]); 147 | echo "
"; 149 | if ($canedit 150 | && $closeform) { 151 | echo "
"; 152 | echo Html::hidden('id', ['value' => $profiles_id]); 153 | echo Html::submit(_sx('button', 'Save'), ['name' => 'update', 'class' => 'btn btn-primary']); 154 | echo "
\n"; 155 | Html::closeForm(); 156 | } 157 | echo "
"; 158 | 159 | $this->showLegend(); 160 | } 161 | 162 | /** 163 | * Get all rights 164 | * 165 | * @param type $all 166 | * 167 | * @return array 168 | */ 169 | public static function getAllRights($all = false) 170 | { 171 | 172 | $rights = [ 173 | ['itemtype' => Purchaserequest::class, 174 | 'label' => __('Purchase request', 'purchaserequest'), 175 | 'field' => 'plugin_purchaserequest_purchaserequest', 176 | ], 177 | ]; 178 | if ($all) { 179 | $rights[] = ['itemtype' => Purchaserequest::class, 180 | 'label' => __("Purchase request validation", "purchaserequest"), 181 | 'field' => 'plugin_purchaserequest_validate']; 182 | $rights[] = ['itemtype' => Config::class, 183 | 'label' => __("Setup"), 184 | 'field' => 'plugin_purchaserequest_config']; 185 | } 186 | 187 | return $rights; 188 | } 189 | 190 | /** 191 | * Init profiles 192 | * 193 | **/ 194 | 195 | public static function translateARight($old_right) 196 | { 197 | switch ($old_right) { 198 | case '': 199 | return 0; 200 | case 'r': 201 | return READ; 202 | case 'w': 203 | return UPDATE + PURGE; 204 | case '0': 205 | case '1': 206 | return $old_right; 207 | 208 | default: 209 | return 0; 210 | } 211 | } 212 | 213 | 214 | /** 215 | * @param $profiles_id the profile ID 216 | * 217 | * @return bool 218 | * @since 0.85 219 | * Migration rights from old system to the new one for one profile 220 | */ 221 | public static function migrateOneProfile($profiles_id) 222 | { 223 | global $DB; 224 | //Cannot launch migration if there's nothing to migrate... 225 | if (!$DB->tableExists('glpi_plugin_purchaserequest_profiles')) { 226 | return true; 227 | } 228 | 229 | $it = $DB->request([ 230 | 'FROM' => 'glpi_plugin_purchaserequest_profiles', 231 | 'WHERE' => ['profiles_id' => $profiles_id], 232 | ]); 233 | foreach ($it as $profile_data) { 234 | $matching = ['show_purchaserequest_tab' => 'plugin_purchaserequest_purchaserequest', 235 | 'validation' => 'plugin_purchaserequest_validate']; 236 | $current_rights = ProfileRight::getProfileRights($profiles_id, array_values($matching)); 237 | foreach ($matching as $old => $new) { 238 | if (!isset($current_rights[$old])) { 239 | $DB->update('glpi_profilerights', ['rights' => self::translateARight($profile_data[$old])], [ 240 | 'name' => $new, 241 | 'profiles_id' => $profiles_id, 242 | ]); 243 | } 244 | } 245 | } 246 | } 247 | 248 | /** 249 | * Initialize profiles, and migrate it necessary 250 | */ 251 | public static function initProfile() 252 | { 253 | global $DB; 254 | $profile = new self(); 255 | $dbu = new DbUtils(); 256 | //Add new rights in glpi_profilerights table 257 | foreach ($profile->getAllRights(true) as $data) { 258 | if ($dbu->countElementsInTable( 259 | "glpi_profilerights", 260 | ["name" => $data['field']] 261 | ) == 0) { 262 | ProfileRight::addProfileRights([$data['field']]); 263 | } 264 | } 265 | 266 | //Migration old rights in new ones 267 | $it = $DB->request([ 268 | 'SELECT' => ['id'], 269 | 'FROM' => 'glpi_profiles', 270 | ]); 271 | foreach ($it as $prof) { 272 | self::migrateOneProfile($prof['id']); 273 | } 274 | $it = $DB->request([ 275 | 'FROM' => 'glpi_profilerights', 276 | 'WHERE' => [ 277 | 'profiles_id' => $_SESSION['glpiactiveprofile']['id'], 278 | 'name' => ['LIKE', '%plugin_purchaserequest%'], 279 | ], 280 | ]); 281 | foreach ($it as $prof) { 282 | $_SESSION['glpiactiveprofile'][$prof['name']] = $prof['rights']; 283 | } 284 | } 285 | 286 | /** 287 | * Initialize profiles, and migrate it necessary 288 | */ 289 | public static function changeProfile() 290 | { 291 | global $DB; 292 | 293 | foreach ($DB->request("SELECT * 294 | FROM `glpi_profilerights` 295 | WHERE `profiles_id`='" . $_SESSION['glpiactiveprofile']['id'] . "' 296 | AND `name` LIKE '%plugin_purchaserequest_purchaserequest%'") as $prof) { 297 | $_SESSION['glpiactiveprofile'][$prof['name']] = $prof['rights']; 298 | } 299 | 300 | } 301 | 302 | /** 303 | * @param $profiles_id 304 | */ 305 | public static function createFirstAccess($profiles_id) 306 | { 307 | 308 | $rights = ['plugin_purchaserequest_purchaserequest' => 127, 309 | 'plugin_purchaserequest_validate' => 1, 310 | 'plugin_purchaserequest_config' => 1, 311 | ]; 312 | 313 | self::addDefaultProfileInfos( 314 | $profiles_id, 315 | $rights, 316 | true 317 | ); 318 | 319 | } 320 | 321 | /** 322 | * @param $profile 323 | **/ 324 | public static function addDefaultProfileInfos($profiles_id, $rights, $drop_existing = false) 325 | { 326 | $dbu = new DbUtils(); 327 | $profileRight = new ProfileRight(); 328 | foreach ($rights as $right => $value) { 329 | if ($dbu->countElementsInTable( 330 | 'glpi_profilerights', 331 | ["profiles_id" => $profiles_id, 332 | "name" => $right] 333 | ) && $drop_existing) { 334 | $profileRight->deleteByCriteria(['profiles_id' => $profiles_id, 'name' => $right]); 335 | } 336 | if (!$dbu->countElementsInTable( 337 | 'glpi_profilerights', 338 | ["profiles_id" => $profiles_id, 339 | "name" => $right] 340 | )) { 341 | $myright['profiles_id'] = $profiles_id; 342 | $myright['name'] = $right; 343 | $myright['rights'] = $value; 344 | $profileRight->add($myright); 345 | 346 | //Add right to the current session 347 | $_SESSION['glpiactiveprofile'][$right] = $value; 348 | } 349 | } 350 | } 351 | 352 | public static function removeRightsFromSession() 353 | { 354 | foreach (self::getAllRights(true) as $right) { 355 | if (isset($_SESSION['glpiactiveprofile'][$right['field']])) { 356 | unset($_SESSION['glpiactiveprofile'][$right['field']]); 357 | } 358 | } 359 | } 360 | 361 | } 362 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/NotificationTargetPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | . 19 | -------------------------------------------------------------------------- 20 | @package purchaserequest 21 | @author the purchaserequest plugin team 22 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 23 | @license GPLv2+ 24 | http://www.gnu.org/licenses/gpl.txt 25 | @link https://github.com/InfotelGLPI/purchaserequest 26 | @link http://www.glpi-project.org/ 27 | @since 2009 28 | ---------------------------------------------------------------------- */ 29 | 30 | namespace GlpiPlugin\Purchaserequest; 31 | 32 | use CommonITILValidation; 33 | use DbUtils; 34 | use Dropdown; 35 | use Html; 36 | use Migration; 37 | use Notification; 38 | use Notification_NotificationTemplate; 39 | use NotificationTarget; 40 | use NotificationTemplate; 41 | use NotificationTemplateTranslation; 42 | use User; 43 | 44 | if (!defined('GLPI_ROOT')) { 45 | die("Sorry. You can't access directly to this file"); 46 | } 47 | 48 | // Class NotificationTargetPurchaseRequest 49 | class NotificationTargetPurchaseRequest extends NotificationTarget { 50 | const PURCHASE_VALIDATOR = 30; 51 | const PURCHASE_AUTHOR = 31; 52 | 53 | 54 | public function getEvents() { 55 | return [ 56 | 'ask_purchaserequest' => __("Request for validation of the purchase request", "purchaserequest"), 57 | 'no_validation_purchaserequest' => __("Refusal of validation request", "purchaserequest"), 58 | 'validation_purchaserequest' => __("Purchase request validation", "purchaserequest"), 59 | ]; 60 | } 61 | 62 | public function addDataForTemplate($event, $options = []) { 63 | global $CFG_GLPI; 64 | 65 | $dbu = new DbUtils(); 66 | $events = $this->getAllEvents(); 67 | 68 | $this->data['##purchaserequest.action##'] = $events[$event]; 69 | 70 | $this->data['##lang.purchaserequest.title##'] = $events[$event]; 71 | 72 | $this->data['##lang.purchaserequest.entity##'] = __("Entity"); 73 | $this->data['##purchaserequest.entity##'] = Dropdown::getDropdownName('glpi_entities', 74 | $this->obj->getField('entities_id')); 75 | 76 | $this->data['##lang.purchaserequest.name##'] = __("Name"); 77 | $this->data['##purchaserequest.name##'] = $this->obj->getField("name"); 78 | 79 | $this->data['##lang.purchaserequest.amount##'] = __("Amount", "purchaserequest"); 80 | $this->data['##purchaserequest.amount##'] = Dropdown::getValueWithUnit($this->obj->getField("amount"), "€"); 81 | 82 | $this->data['##lang.purchaserequest.rebill##'] = __("To be rebilled to the customer", "purchaserequest"); 83 | $this->data['##purchaserequest.rebill##'] = Dropdown::getYesNo($this->obj->getField("invoice_customer")); 84 | 85 | $this->data['##lang.purchaserequest.requester##'] = __("Requester"); 86 | $this->data['##purchaserequest.requester##'] = getUserName($this->obj->getField('users_id')); 87 | 88 | $this->data['##lang.purchaserequest.group##'] = __("Requester group"); 89 | $this->data['##purchaserequest.group##'] = Dropdown::getDropdownName('glpi_groups', 90 | $this->obj->getField('groups_id')); 91 | 92 | $this->data['##lang.purchaserequest.duedate##'] = __("Due date", "purchaserequest"); 93 | $this->data['##purchaserequest.duedate##'] = Html::convDate($this->obj->getField("due_date")); 94 | 95 | $this->data['##lang.purchaserequest.comment##'] = __("Description"); 96 | 97 | // $comment = Toolbox::stripslashes_deep(str_replace(['\r\n', '\n', '\r'], "
", $this->obj->getField('comment'))); 98 | // $comment = html_entity_decode(stripslashes($this->obj->fields['comment'])); 99 | $this->data['##purchaserequest.comment##'] = $this->obj->fields['comment']; 100 | 101 | $itemtype = $this->obj->getField("itemtype"); 102 | 103 | $this->data['##lang.purchaserequest.itemtype##'] = __("Item type"); 104 | if (file_exists(GLPI_ROOT . "/src/" . $itemtype . "Type.php")) { 105 | $this->data['##purchaserequest.itemtype##'] = Dropdown::getDropdownName($dbu->getTableForItemType($itemtype . "Type"), 106 | $this->obj->getField("types_id")); 107 | } else if ($itemtype == "PluginOrderOther") { 108 | $this->data['##purchaserequest.itemtype##'] = $this->obj->getField('othertypename'); 109 | } 110 | 111 | $this->data['##lang.purchaserequest.type##'] = __("Type"); 112 | $item = new $itemtype(); 113 | $this->data['##purchaserequest.type##'] = $item->getTypeName(); 114 | 115 | switch ($event) { 116 | case "ask_purchaserequest" : 117 | $this->data['##lang.purchaserequest.users_validation##'] = __("Purchase request validation", "purchaserequest") 118 | . " " . __("By"); 119 | break; 120 | case "validation_purchaserequest" : 121 | $this->data['##lang.purchaserequest.users_validation##'] = __("Purchase request is validated", "purchaserequest") 122 | . " " . __("By"); 123 | break; 124 | case "no_validation_purchaserequest" : 125 | $this->data['##lang.purchaserequest.users_validation##'] = __("Purchase request canceled", "purchaserequest") 126 | . " " . __("By"); 127 | break; 128 | 129 | } 130 | $this->data['##purchaserequest.users_validation##'] = getUserName($this->obj->getField('users_id_validation')); 131 | 132 | $restrict = ['plugin_purchaserequest_purchaserequests_id' => $this->obj->getField("id")]; 133 | $dbu = new DbUtils(); 134 | $validations = $dbu->getAllDataFromTable('glpi_plugin_purchaserequest_validations', $restrict); 135 | $data['validations'] = []; 136 | if (count($validations)) { 137 | $this->data['##lang.validation.state##'] = _x('item', 'State'); 138 | $this->data['##lang.validation.datesubmit##'] = __('Request date'); 139 | $this->data['##lang.validation.requester##'] = __('Approval requester'); 140 | $this->data['##lang.validation.approver##'] = __('Approver'); 141 | $this->data['##lang.validation.comment##'] = __('Approval comments'); 142 | $this->data['##lang.validation.datevalidation##'] = __('Approval date'); 143 | 144 | $validation = new Validation(); 145 | foreach ($validations as $row) { 146 | 147 | $tmp = []; 148 | 149 | $tmp['##validation.state##'] 150 | = CommonITILValidation::getStatus($row['status']); 151 | $tmp['##validation.datesubmit##'] 152 | = Html::convDateTime($row["submission_date"]); 153 | $tmp['##validation.requester##'] 154 | = getUserName($row["users_id"]); 155 | $tmp['##validation.approver##'] 156 | = getUserName($row["users_id_validate"]); 157 | $tmp['##validation.comment##'] 158 | = $row["comment_validation"]; 159 | $tmp['##validation.datevalidation##'] 160 | = Html::convDateTime($row["validation_date"]); 161 | $data['validations'][] = $tmp; 162 | 163 | } 164 | $this->data["validations"] = $data["validations"]; 165 | } 166 | $this->data['##lang.purchaserequest.url##'] = "URL"; 167 | 168 | $url = $CFG_GLPI["url_base"] . "/index.php?redirect=GlpiPlugin\Purchaserequest\Purchaserequest_" . $this->obj->getField("id"); 169 | $this->data['##purchaserequest.url##'] = urldecode($url); 170 | 171 | } 172 | 173 | public function getTags() { 174 | $tags = [ 175 | 'purchaserequest.name' => __("Name"), 176 | 'purchaserequest.requester' => __("Requester"), 177 | 'purchaserequest.group' => __("Requester group"), 178 | 'purchaserequest.duedate' => __("Due date", "purchaserequest"), 179 | 'purchaserequest.comment' => __("Description"), 180 | 'purchaserequest.itemtype' => __("Item type"), 181 | 'purchaserequest.type' => __("Type"), 182 | 'purchaserequest.amount' => __("Amount", "purchaserequest"), 183 | 'purchaserequest.rebill' => __("To be rebilled to the customer", "purchaserequest"), 184 | 'purchaserequest.users_validation' => __("Editor of validation", "purchaserequest"), 185 | 'validation.state' => _x('item', 'State'), 186 | 'validation.datesubmit' => __('Request date'), 187 | 'validation.requester' => __('Approval requester'), 188 | 'validation.approver' => __('Approver'), 189 | 'validation.comment' => __('Approval comments'), 190 | 'validation.datevalidation' => __('Approval date'), 191 | 192 | ]; 193 | 194 | foreach ($tags as $tag => $label) { 195 | $this->addTagToList([ 196 | 'tag' => $tag, 197 | 'label' => $label, 198 | 'value' => true, 199 | ]); 200 | } 201 | 202 | //Foreach global tags 203 | $tags = ['validations' => __('Approval')]; 204 | 205 | foreach ($tags as $tag => $label) { 206 | $this->addTagToList(['tag' => $tag, 207 | 'label' => $label, 208 | 'value' => false, 209 | 'foreach' => true]); 210 | } 211 | asort($this->tag_descriptions); 212 | } 213 | 214 | public static function install(Migration $migration) { 215 | global $DB; 216 | 217 | $migration->displayMessage("Migrate Purchaserequest notifications"); 218 | 219 | $template = new NotificationTemplate(); 220 | $templates_id = false; 221 | $query_id = "SELECT `id` 222 | FROM `glpi_notificationtemplates` 223 | WHERE `itemtype`='GlpiPlugin\\Purchaserequest\\PurchaseRequest' 224 | AND `name` = 'Purchase Request Validation'"; 225 | $result = $DB->doQuery($query_id) or die ($DB->error()); 226 | 227 | if ($DB->numrows($result) > 0) { 228 | $templates_id = $DB->result($result, 0, 'id'); 229 | } else { 230 | $tmp = [ 231 | 'name' => 'Purchase Request Validation', 232 | 'itemtype' => PurchaseRequest::class, 233 | 'date_mod' => $_SESSION['glpi_currenttime'], 234 | 'comment' => '', 235 | 'css' => '', 236 | ]; 237 | $templates_id = $template->add($tmp); 238 | } 239 | 240 | if ($templates_id) { 241 | $translation = new NotificationTemplateTranslation(); 242 | $dbu = new DbUtils(); 243 | if (!$dbu->countElementsInTable($translation->getTable(), ["notificationtemplates_id" => $templates_id])) { 244 | $tmp['notificationtemplates_id'] = $templates_id; 245 | $tmp['language'] = ''; 246 | $tmp['subject'] = '##lang.purchaserequest.title##'; 247 | $tmp['content_text'] = '##lang.purchaserequest.url## : ##purchaserequest.url## 248 | ##lang.purchaserequest.entity## : ##purchaserequest.entity## 249 | ##IFpurchaserequest.name####lang.purchaserequest.name## : ##purchaserequest.name## 250 | ##ENDIFpurchaserequest.name## 251 | ##IFpurchaserequest.requester####lang.purchaserequest.requester## : ##purchaserequest.requester## 252 | ##ENDIFpurchaserequest.requester## 253 | ##IFpurchaserequest.group####lang.purchaserequest.group## : ##purchaserequest.group## 254 | ##ENDIFpurchaserequest.group## 255 | ##IFpurchaserequest.due_date####lang.purchaserequest.due_date## : ##purchaserequest.due_date####ENDIFpurchaserequest.due_date## 256 | ##IFpurchaserequest.itemtype####lang.purchaserequest.itemtype## : ##purchaserequest.itemtype####ENDIFpurchaserequest.itemtype## 257 | ##IFpurchaserequest.type####lang.purchaserequest.type## : ##purchaserequest.type####ENDIFpurchaserequest.type## 258 | 259 | ##IFpurchaserequest.comment####lang.purchaserequest.comment## : ##purchaserequest.comment####ENDIFpurchaserequest.comment##'; 260 | 261 | $tmp['content_html'] = '<p><strong>##lang.purchaserequest.url##</strong> : ' . 262 | '<a href=\"##purchaserequest.url##\">##purchaserequest.url##</a><br />' . 263 | '<br /><strong>##lang.purchaserequest.entity##</strong> : ##purchaserequest.entity##<br />' . 264 | ' ##IFpurchaserequest.name##<strong>##lang.purchaserequest.name##</strong>' . 265 | ' : ##purchaserequest.name####ENDIFpurchaserequest.name##<br />' . 266 | '##IFpurchaserequest.requester##<strong>##lang.purchaserequest.requester##</strong>' . 267 | ' : ##purchaserequest.requester####ENDIFpurchaserequest.requester##<br />' . 268 | '##IFpurchaserequest.group##<strong>##lang.purchaserequest.group##</strong>' . 269 | ' : ##purchaserequest.group####ENDIFpurchaserequest.group##<br />' . 270 | '##IFpurchaserequest.due_date##<strong>##lang.purchaserequest.due_date##</strong>' . 271 | ' : ##purchaserequest.due_date####ENDIFpurchaserequest.due_date##<br />' . 272 | '##IFpurchaserequest.itemtype##<strong>##lang.purchaserequest.itemtype##</strong>' . 273 | ' : ##purchaserequest.itemtype####ENDIFpurchaserequest.itemtype##<br />' . 274 | '##IFpurchaserequest.type##<strong>##lang.purchaserequest.type##</strong>' . 275 | ' : ##purchaserequest.type####ENDIFpurchaserequest.type##<br /><br />' . 276 | '##IFpurchaserequest.comment##<strong>##lang.purchaserequest.comment##</strong> :' . 277 | '##purchaserequest.comment####ENDIFpurchaserequest.comment##</p>'; 278 | $translation->add($tmp); 279 | } 280 | 281 | $notifs = [ 282 | 'New Purchase Request Validation' => 'ask_purchaserequest', 283 | 'Confirm Purchase Request Validation' => 'validation_purchaserequest', 284 | 'Cancel Purchase Request Validation' => 'no_validation_purchaserequest', 285 | ]; 286 | $notification = new Notification(); 287 | $notificationtemplate = new Notification_NotificationTemplate(); 288 | foreach ($notifs as $label => $name) { 289 | if (!$dbu->countElementsInTable("glpi_notifications", 290 | ["itemtype" => Purchaserequest::class, 291 | "event" => $name])) { 292 | $tmp = [ 293 | 'name' => $label, 294 | 'entities_id' => 0, 295 | 'itemtype' => PurchaseRequest::class, 296 | 'event' => $name, 297 | 'comment' => '', 298 | 'is_recursive' => 1, 299 | 'is_active' => 1, 300 | 'date_mod' => $_SESSION['glpi_currenttime'], 301 | ]; 302 | $notification_id = $notification->add($tmp); 303 | 304 | $notificationtemplate->add(['notificationtemplates_id' => $templates_id, 305 | 'mode' => 'mailing', 306 | 'notifications_id' => $notification_id]); 307 | } 308 | } 309 | } 310 | 311 | } 312 | 313 | public static function uninstall() { 314 | global $DB; 315 | 316 | $notif = new Notification(); 317 | $options = ['itemtype' => PurchaseRequest::class]; 318 | foreach ($DB->request([ 319 | 'FROM' => 'glpi_notifications', 320 | 'WHERE' => $options]) as $data) { 321 | $notif->delete($data); 322 | } 323 | 324 | //templates 325 | $template = new NotificationTemplate(); 326 | $translation = new NotificationTemplateTranslation(); 327 | $notif_template = new Notification_NotificationTemplate(); 328 | $options = ['itemtype' => PurchaseRequest::class]; 329 | foreach ($DB->request([ 330 | 'FROM' => 'glpi_notificationtemplates', 331 | 'WHERE' => $options]) as $data) { 332 | $options_template = [ 333 | 'notificationtemplates_id' => $data['id'] 334 | ]; 335 | 336 | foreach ($DB->request([ 337 | 'FROM' => 'glpi_notificationtemplatetranslations', 338 | 'WHERE' => $options_template]) as $data_template) { 339 | $translation->delete($data_template); 340 | } 341 | $template->delete($data); 342 | 343 | foreach ($DB->request([ 344 | 'FROM' => 'glpi_notifications_notificationtemplates', 345 | 'WHERE' => $options_template]) as $data_template) { 346 | $notif_template->delete($data_template); 347 | } 348 | } 349 | } 350 | 351 | /** 352 | * Get additionnals targets for Tickets 353 | **/ 354 | public function addAdditionalTargets($event = '') { 355 | $this->addTarget(self::PURCHASE_VALIDATOR, __("Validator of the purchase request", "purchaserequest")); 356 | $this->addTarget(self::PURCHASE_AUTHOR, __("Author of the purchase request", "purchaserequest")); 357 | 358 | } 359 | 360 | public function addSpecificTargets($data, $options) { 361 | switch ($data['items_id']) { 362 | case self::PURCHASE_VALIDATOR: 363 | // $this->addUserByField ("users_id_validate"); 364 | $this->addValidationApprover($options); 365 | break; 366 | case self::PURCHASE_AUTHOR: 367 | $this->addUserByField("users_id_creator"); 368 | break; 369 | 370 | } 371 | } 372 | 373 | 374 | /** 375 | * Add approver related to the ITIL object validation 376 | * 377 | * @param $options array 378 | * 379 | * @return void 380 | */ 381 | function addValidationApprover($options = []) { 382 | global $DB; 383 | 384 | if (isset($options['validation_id'])) { 385 | $validationtable = getTableForItemType(Validation::class); 386 | 387 | $criteria = ['LEFT JOIN' => [ 388 | User::getTable() => [ 389 | 'ON' => [ 390 | $validationtable => 'users_id_validate', 391 | User::getTable() => 'id' 392 | ] 393 | ] 394 | ]] + $this->getDistinctUserCriteria() + $this->getProfileJoinCriteria(); 395 | $criteria['FROM'] = $validationtable; 396 | $criteria['WHERE']["$validationtable.id"] = $options['validation_id']; 397 | 398 | $iterator = $DB->request($criteria); 399 | foreach ($iterator as $data) { 400 | $this->addToRecipientsList($data); 401 | $iterator->next(); 402 | } 403 | } 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /src/Validation.php: -------------------------------------------------------------------------------- 1 | . 20 | -------------------------------------------------------------------------- 21 | @package purchaserequest 22 | @author the purchaserequest plugin team 23 | @copyright Copyright (c) 2015-2022 Purchaserequest plugin team 24 | @license GPLv2+ 25 | http://www.gnu.org/licenses/gpl.txt 26 | @link https://github.com/InfotelGLPI/purchaserequest 27 | @link http://www.glpi-project.org/ 28 | @since 2009 29 | ---------------------------------------------------------------------- */ 30 | 31 | namespace GlpiPlugin\Purchaserequest; 32 | 33 | use Ajax; 34 | use CommonDBTM; 35 | use CommonGLPI; 36 | use CommonITILValidation; 37 | use DbUtils; 38 | use Dropdown; 39 | use Glpi\RichText\RichText; 40 | use Html; 41 | use Log; 42 | use Migration; 43 | use NotificationEvent; 44 | use Plugin; 45 | use PluginOrderOrder; 46 | use PluginOrderReference; 47 | use Session; 48 | use Ticket; 49 | use Toolbox; 50 | use User; 51 | 52 | if (!defined('GLPI_ROOT')) { 53 | die("Sorry. You can't access directly to this file"); 54 | } 55 | 56 | /** 57 | * Class Validation 58 | */ 59 | class Validation extends CommonDBTM 60 | { 61 | public static $rightname = 'plugin_purchaserequest_validate'; 62 | public $dohistory = true; 63 | 64 | public const HISTORY_ADDLINK = 50; 65 | public const HISTORY_DELLINK = 51; 66 | 67 | /** 68 | * @param int $nb 69 | * 70 | * @return string|\translated 71 | */ 72 | public static function getTypeName($nb = 0) 73 | { 74 | return _n("Validation", "Validations", $nb, "purchaserequest"); 75 | } 76 | 77 | /** 78 | * @return bool 79 | */ 80 | public static function canValidation() 81 | { 82 | return Session::haveRight("plugin_purchaserequest_validate", 1); 83 | } 84 | 85 | /** 86 | * @param array $options 87 | * 88 | * @return array 89 | */ 90 | public function defineTabs($options = []) 91 | { 92 | $ong = []; 93 | $this->addDefaultFormTab($ong); 94 | return $ong; 95 | } 96 | 97 | /** 98 | * @param CommonGLPI $item 99 | * @param int $withtemplate 100 | * 101 | * @return string|\translated 102 | */ 103 | public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) 104 | { 105 | 106 | if ($item->getType() == PurchaseRequest::class) { 107 | return self::createTabEntry(__('Approval')); 108 | } 109 | 110 | return ''; 111 | } 112 | 113 | public static function getIcon() 114 | { 115 | return "ti ti-check"; 116 | } 117 | 118 | 119 | /** 120 | * @param CommonGLPI $item 121 | * @param int $tabnum 122 | * @param int $withtemplate 123 | * 124 | * @return bool 125 | */ 126 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) 127 | { 128 | 129 | if ($item->getType() == PurchaseRequest::class) { 130 | self::showValidation($item); 131 | } 132 | 133 | return true; 134 | } 135 | 136 | /** 137 | * @param array|\datas $input 138 | * 139 | * @return array|bool|\datas 140 | */ 141 | public function prepareInputForAdd($input) 142 | { 143 | 144 | 145 | $input['status'] = CommonITILValidation::WAITING; 146 | 147 | return $input; 148 | } 149 | 150 | /** 151 | * Prepare input datas for updating the item 152 | * 153 | * @param $input datas used to update the item 154 | * 155 | * @return the modified $input array 156 | **/ 157 | public function prepareInputForUpdate($input) 158 | { 159 | global $CFG_GLPI; 160 | 161 | if (isset($input['refuse_purchaserequest']) && $input['refuse_purchaserequest'] == 1) { 162 | $input['status'] = CommonITILValidation::REFUSED; 163 | } 164 | 165 | if (isset($input['accept_purchaserequest']) && $input['accept_purchaserequest'] == 1) { 166 | $input['status'] = CommonITILValidation::ACCEPTED; 167 | } 168 | 169 | if (isset($input['update_status'])) { 170 | $input['validation_date'] = $_SESSION["glpi_currenttime"]; 171 | } 172 | 173 | return $input; 174 | } 175 | 176 | /** 177 | * Actions done after the ADD of the item in the database 178 | * 179 | * @return nothing 180 | **/ 181 | public function post_addItem() 182 | { 183 | global $CFG_GLPI; 184 | 185 | if ($CFG_GLPI["notifications_mailing"]) { 186 | if (isset($this->input["first"]) 187 | && $this->input["first"] == true) { 188 | $purchase_request = new PurchaseRequest(); 189 | $purchase_request->getFromDB($this->fields["plugin_purchaserequest_purchaserequests_id"]); 190 | $options = ['validation_id' => $this->fields["id"], 191 | 'validation_status' => $this->fields["status"]]; 192 | NotificationEvent::raiseEvent('ask_purchaserequest', $purchase_request, $options); 193 | } 194 | } 195 | 196 | if (isset($this->fields['tickets_id'])) { 197 | $changes[0] = 0; 198 | $changes[1] = ''; 199 | $changes[2] = $this->fields["id"]; 200 | Log::history( 201 | $this->input['tickets_id'], 202 | 'Ticket', 203 | $changes, 204 | __CLASS__, 205 | Log::HISTORY_PLUGIN + self::HISTORY_ADDLINK 206 | ); 207 | } 208 | } 209 | 210 | /** 211 | * Actions done after the UPDATE of the item in the database 212 | * 213 | * @return nothing 214 | **/ 215 | public function post_updateItem($history = 1) 216 | { 217 | global $CFG_GLPI; 218 | if (isset($this->oldvalues['tickets_id'])) { 219 | if ($this->oldvalues['tickets_id'] != 0) { 220 | $changes[0] = 0; 221 | $changes[1] = $this->input['id']; 222 | $changes[2] = ''; 223 | Log::history( 224 | $this->oldvalues['tickets_id'], 225 | 'Ticket', 226 | $changes, 227 | __CLASS__, 228 | Log::HISTORY_PLUGIN + self::HISTORY_DELLINK 229 | ); 230 | } 231 | if (!empty($this->fields['tickets_id'])) { 232 | { 233 | $changes[0] = 0; 234 | $changes[1] = ''; 235 | $changes[2] = $this->fields["id"]; 236 | Log::history( 237 | $this->fields['tickets_id'], 238 | 'Ticket', 239 | $changes, 240 | __CLASS__, 241 | Log::HISTORY_PLUGIN + self::HISTORY_ADDLINK 242 | ); 243 | } 244 | } 245 | } 246 | if (isset($this->input["update_status"])) { 247 | $purchase_request = new PurchaseRequest(); 248 | if (isset($this->input['status']) 249 | && $this->input['status'] == CommonITILValidation::REFUSED) { 250 | $input["status"] = CommonITILValidation::REFUSED; 251 | $input["id"] = $this->fields["plugin_purchaserequest_purchaserequests_id"]; 252 | $purchase_request->update($input); 253 | } elseif (isset($this->input['status']) 254 | && $this->input['status'] == CommonITILValidation::ACCEPTED) { 255 | $input["id"] = $this->fields["plugin_purchaserequest_purchaserequests_id"]; 256 | $items = $this->find(["plugin_purchaserequest_purchaserequests_id" => $this->fields["plugin_purchaserequest_purchaserequests_id"]]); 257 | $validation = true; 258 | foreach ($items as $item) { 259 | if ($item["status"] != CommonITILValidation::ACCEPTED) { 260 | $validation = false; 261 | } 262 | } 263 | 264 | if ($validation == true) { 265 | $input["status"] = CommonITILValidation::ACCEPTED; 266 | $purchase_request->update($input); 267 | } 268 | } 269 | if ($CFG_GLPI["notifications_mailing"]) { 270 | $purchase_request->getFromDB($this->fields["plugin_purchaserequest_purchaserequests_id"]); 271 | 272 | if (count($this->updates)) { 273 | $options = ['validation_id' => $this->fields["id"], 274 | 'validation_status' => $this->fields["status"]]; 275 | // NotificationEvent::raiseEvent('validation_answer', $purchase_request, $options); 276 | if (isset($this->input['status']) 277 | && $this->input['status'] == CommonITILValidation::ACCEPTED) { 278 | if ($validation == true && $purchase_request->fields["status"] == CommonITILValidation::ACCEPTED) { 279 | NotificationEvent::raiseEvent('validation_purchaserequest', $purchase_request, $options); 280 | } elseif ($purchase_request->fields["status"] == CommonITILValidation::WAITING) { 281 | $items = $this->find(["plugin_purchaserequest_purchaserequests_id" => $this->fields["plugin_purchaserequest_purchaserequests_id"]]); 282 | 283 | foreach ($items as $item) { 284 | if ($item["status"] == CommonITILValidation::WAITING) { 285 | $options = ['validation_id' => $item["id"], 286 | 'validation_status' => $item["status"]]; 287 | NotificationEvent::raiseEvent('ask_purchaserequest', $purchase_request, $options); 288 | } 289 | } 290 | } 291 | } elseif (isset($this->input['status']) 292 | && $this->input['status'] == CommonITILValidation::REFUSED) { 293 | NotificationEvent::raiseEvent('no_validation_purchaserequest', $purchase_request, $options); 294 | } 295 | } 296 | } 297 | } 298 | } 299 | 300 | 301 | /** 302 | * @param $ID 303 | * @param array $options 304 | * 305 | * @return bool 306 | */ 307 | public function showForm($ID, $options = []) 308 | { 309 | global $CFG_GLPI; 310 | 311 | $dbu = new DbUtils(); 312 | $this->initForm($ID, $options); 313 | $this->showFormHeader($options); 314 | 315 | $canedit = $this->can($ID, UPDATE); 316 | $options['canedit'] = $canedit; 317 | 318 | // Data saved in session 319 | if (isset($_SESSION['glpi_plugin_purchaserequests_fields'])) { 320 | foreach ($_SESSION['glpi_plugin_purchaserequests_fields'] as $key => $value) { 321 | if ($key == "comment") { 322 | $this->fields[$key] = RichText::getEnhancedHtml($value); 323 | } else { 324 | $this->fields[$key] = $value; 325 | } 326 | } 327 | unset($_SESSION['glpi_plugin_purchaserequests_fields']); 328 | } 329 | 330 | /* title */ 331 | echo ""; 332 | echo "" . __("Name") . ""; 333 | if ($canedit) { 334 | echo Html::input('name', ['value' => $this->fields['name'], 'size' => 40]); 335 | } else { 336 | echo $this->fields["name"]; 337 | } 338 | echo ""; 339 | 340 | echo ""; 341 | /* requester */ 342 | echo "" . __("Requester") . " *"; 343 | if ($canedit) { 344 | $rand_user = User::dropdown(['name' => "users_id", 345 | 'value' => $this->fields["users_id"], 346 | 'entity' => $this->fields["entities_id"], 347 | 'on_change' => "PurchaserequestLoadGroups();", 348 | 'right' => 'all']); 349 | } else { 350 | echo Dropdown::getDropdownName($dbu->getTableForItemType('User'), $this->fields["users_id"]); 351 | } 352 | echo ""; 353 | 354 | /* requester group */ 355 | echo "" . __("Requester group"); 356 | echo ""; 357 | 358 | if ($canedit) { 359 | if ($this->fields['users_id']) { 360 | PurchaseRequest::displayGroup($this->fields['users_id']); 361 | } 362 | 363 | $JS = "function PurchaserequestLoadGroups(){"; 364 | $params = ['users_id' => '__VALUE__', 365 | 'entity' => $this->fields["entities_id"]]; 366 | $JS .= Ajax::updateItemJsCode( 367 | "plugin_purchaserequest_group", 368 | PLUGIN_PURCHASEREQUEST_WEBDIR . "/ajax/dropdownGroup.php", 369 | $params, 370 | 'dropdown_users_id' . $rand_user, 371 | false 372 | ); 373 | $JS .= "}"; 374 | echo Html::scriptBlock($JS); 375 | } else { 376 | echo Dropdown::getDropdownName($dbu->getTableForItemType('Group'), $this->fields["groups_id"]); 377 | } 378 | echo ""; 379 | 380 | /* location */ 381 | echo "" . __("Location") . " "; 382 | echo ""; 383 | Dropdown::show('Location', ['value' => $this->fields["locations_id"], 384 | 'entity' => $this->fields["entities_id"]]); 385 | echo ""; 386 | echo "" . __("Status") . " "; 387 | echo ""; 388 | Dropdown::show( 389 | PurchaseRequestState::class, 390 | ['value' => $this->fields["plugin_purchaserequest_purchaserequeststates_id"], 391 | 'entity' => $this->fields["entities_id"]] 392 | ); 393 | echo ""; 394 | 395 | /* description */ 396 | echo "" . __("Description") . " *"; 397 | echo ""; 398 | Html::textarea(['name' => 'comment', 399 | 'value' => stripslashes($this->fields['comment']), 400 | 'enable_richtext' => false, 401 | 'cols' => '100', 402 | 'rows' => '4']); 403 | echo ""; 404 | 405 | /* type */ 406 | $reference = new PluginOrderReference(); 407 | echo "" . __("Item type"); 408 | echo " *"; 409 | echo ""; 410 | $params = [ 411 | 'myname' => 'itemtype', 412 | 'value' => $this->fields["itemtype"], 413 | 'entity' => $_SESSION["glpiactive_entity"], 414 | 'ajax_page' => $CFG_GLPI['root_doc'] . '/plugins/order/ajax/referencespecifications.php', 415 | 'class' => __CLASS__, 416 | ]; 417 | 418 | $reference->dropdownAllItems($params); 419 | echo ""; 420 | 421 | echo "" . __("Type") . " *"; 422 | echo ""; 423 | echo ""; 424 | if ($this->fields['itemtype']) { 425 | if ($this->fields['itemtype'] == 'PluginOrderOther') { 426 | $file = 'other'; 427 | } else { 428 | $file = $this->fields['itemtype']; 429 | } 430 | $core_typefilename = GLPI_ROOT . "/src/" . $file . "Type.php"; 431 | $plugin_typefilename = $CFG_GLPI['root_doc'] . "/plugins/order/inc/" . strtolower($file) . "type.class.php"; 432 | $itemtypeclass = $this->fields['itemtype'] . "Type"; 433 | 434 | if (file_exists($core_typefilename) 435 | || file_exists($plugin_typefilename)) { 436 | Dropdown::show( 437 | $itemtypeclass, 438 | [ 439 | 'name' => "types_id", 440 | 'value' => $this->fields["types_id"], 441 | ] 442 | ); 443 | } 444 | } 445 | echo ""; 446 | echo ""; 447 | 448 | echo "" . __("Due date", "purchaserequest") . ""; 449 | echo ""; 450 | Html::showDateField("due_date", ['value' => $this->fields["due_date"]]); 451 | echo ""; 452 | 453 | echo "" . __("To be validated by", "purchaserequest") . " *"; 454 | echo ""; 455 | User::dropdown(['name' => "users_id_validate", 456 | 'value' => $this->fields["users_id_validate"], 457 | 'entity' => $this->fields["entities_id"], 458 | 'right' => 'plugin_purchaserequest_validate']); 459 | echo ""; 460 | echo "" . __("Amount", "purchaserequest") . ""; 461 | echo ""; 462 | $params = [ 463 | 'type' => 'text', 464 | 'value' => number_format($this->fields['amount'], 2, '.', ' '), 465 | ]; 466 | echo Html::input('amount', $params); 467 | echo ""; 468 | 469 | echo "" . __("To be rebilled to the customer", "purchaserequest") . " "; 470 | echo ""; 471 | Html::showCheckbox(['name' => "invoice_customer", 472 | 'checked' => $this->fields["invoice_customer"], 473 | ]); 474 | 475 | echo ""; 476 | echo ""; 477 | echo ""; 478 | $order = new PluginOrderOrder(); 479 | echo "" . __("Linked to the order", "purchaserequest") . ""; 480 | echo ""; 481 | 482 | $options = []; 483 | if ($order->getFromDB($this->fields['plugin_order_orders_id'])) { 484 | $options['value'] = $this->fields['plugin_order_orders_id']; 485 | } 486 | PluginOrderOrder::dropdown($options); 487 | echo ""; 488 | $ticket = new Ticket(); 489 | echo "" . __("Linked to ticket", "purchaserequest") . ""; 490 | echo ""; 491 | $options = []; 492 | if ($ticket->getFromDB($this->fields['tickets_id'])) { 493 | $options['value'] = $this->fields['tickets_id']; 494 | } 495 | $options['entity'] = $this->fields["entities_id"]; 496 | Ticket::dropdown($options); 497 | echo ""; 498 | echo ""; 499 | 500 | if ($ID > 0) { 501 | echo ""; 502 | 503 | if ($this->fields['processing_date'] == null) { 504 | echo "" . __("Treated", "purchaserequest") . ""; 505 | echo ""; 506 | Html::showCheckbox(['name' => 'is_process']); 507 | echo ""; 508 | echo ""; 509 | } else { 510 | echo "" . __("Treated on", "purchaserequest"); 511 | echo " " . Html::convDateTime($this->fields['processing_date']); 512 | echo ""; 513 | } 514 | echo ""; 515 | } 516 | 517 | echo Html::hidden('users_id_creator', ['value' => $_SESSION['glpiID']]); 518 | 519 | if ($canedit) { 520 | $this->showFormButtons($options); 521 | } else { 522 | echo ""; 523 | Html::closeForm(); 524 | } 525 | 526 | return true; 527 | } 528 | 529 | 530 | /** 531 | * Display list of purchase request linked to the order 532 | * 533 | * @param $item 534 | */ 535 | public static function showForOrder($item) 536 | { 537 | global $CFG_GLPI; 538 | 539 | $dbu = new DbUtils(); 540 | if (isset($_REQUEST["start"])) { 541 | $start = $_REQUEST["start"]; 542 | } else { 543 | $start = 0; 544 | } 545 | 546 | $purchase_request = new PurchaseRequest(); 547 | $data = $purchase_request->find(['plugin_order_orders_id' => $item->fields['id']]); 548 | 549 | $rows = count($data); 550 | 551 | $canread = Session::haveRight(self::$rightname, READ); 552 | 553 | if (!$rows || !$canread) { 554 | echo __('No item to display'); 555 | } else { 556 | $canedit = Session::haveRightsOr(self::$rightname, [CREATE, UPDATE, PURGE]); 557 | $rand = mt_rand(); 558 | 559 | echo "
"; 560 | 561 | Html::printAjaxPager(PurchaseRequest::getTypeName(2), $start, $rows); 562 | echo ""; 564 | 565 | echo ""; 566 | echo ""; 567 | if ($canedit) { 568 | echo ""; 569 | } 570 | echo ""; 571 | echo ""; 572 | echo ""; 573 | echo ""; 574 | echo ""; 575 | echo ""; 576 | echo ""; 577 | echo ""; 578 | echo ""; 579 | echo ""; 580 | echo ""; 581 | echo ""; 582 | echo ""; 583 | 584 | foreach ($data as $field) { 585 | echo ""; 586 | if ($canedit) { 587 | echo ""; 595 | } 596 | // Name 597 | $purchase_request = new PurchaseRequest(); 598 | $purchase_request->getFromDB($field['id']); 599 | echo ""; 600 | // requester 601 | echo ""; 602 | // requester group 603 | echo ""; 604 | // location 605 | echo ""; 606 | // state 607 | echo ""; 611 | // item type 612 | $item = new $field["itemtype"](); 613 | echo ""; 614 | // Model name 615 | $itemtypeclass = $field['itemtype'] . "Type"; 616 | echo ""; 617 | //due date 618 | echo ""; 619 | //traited 620 | echo ""; 621 | // validation 622 | echo ""; 623 | //status 624 | echo ""; 625 | //link with order 626 | $order = new PluginOrderOrder(); 627 | $order->getFromDB($field['plugin_order_orders_id']); 628 | echo ""; 629 | echo ""; 630 | } 631 | 632 | echo "
" . __('Name') . "" . __('Requester') . "" . __('Requester group') . "" . __('Location') . "" . __('Status') . "" . __('Item type') . "" . __('Type') . "" . __('Due date', 'purchaserequest') . "" . __('Treated on', 'purchaserequest') . "" . __('Approver') . "" . __('Approval status') . "" . PluginOrderOrder::getTypeName() . "
"; 588 | $sel = ""; 589 | if (isset($_GET["select"]) && $_GET["select"] == "all") { 590 | $sel = "checked"; 591 | } 592 | echo ""; 593 | echo Html::hidden('plugin_order_orders_id', ['value' => $item->getID()]); 594 | echo "" . $purchase_request->getLink() . "" . $dbu->getUserName($field['users_id']) . "" . Dropdown::getDropdownName('glpi_groups', $field['groups_id']) . "" . Dropdown::getDropdownName('glpi_locations', $field['locations_id']) . "" . Dropdown::getDropdownName( 608 | 'glpi_plugin_purchaserequest_purchaserequeststates', 609 | $field['plugin_purchaserequest_purchaserequeststates_id'] 610 | ) . "" . $item->getTypeName() . "" . Dropdown::getDropdownName($dbu->getTableForItemType($itemtypeclass), $field["types_id"]) . "" . Html::convDate($field['due_date']) . "" . Html::convDate($field['processing_date']) . "" . $dbu->getUserName($field['users_id_validate']) . "" . CommonITILValidation::getStatus($field['status']) . "" . $order->getLink() . "
"; 633 | if ($canedit) { 634 | echo "
"; 635 | echo ""; 636 | echo ""; 640 | 641 | echo ""; 650 | echo "
"; 638 | echo "" . __("Check all") . "/"; 642 | echo "" . __("Uncheck all") . ""; 644 | echo ""; 645 | echo Html::hidden('plugin_order_orders_id', ['value' => $item->getID()]); 646 | $purchase_request->dropdownPurchaseRequestItemsActions(); 647 | echo " "; 648 | echo Html::submit(_sx('button', 'Post'), ['name' => 'action', 'class' => 'btn btn-primary']); 649 | echo "
"; 651 | } 652 | Html::closeForm(); 653 | echo "
"; 654 | } 655 | } 656 | 657 | /** 658 | * 659 | */ 660 | public function dropdownPurchaseRequestItemsActions() 661 | { 662 | 663 | $action['delete_link'] = __("Delete link with order", "purchaserequest"); 664 | Dropdown::showFromArray('chooseAction', $action); 665 | } 666 | 667 | /** 668 | * @param $item 669 | */ 670 | public static function showValidation($item) 671 | { 672 | 673 | $dbu = new DbUtils(); 674 | $validation = new self(); 675 | echo ""; 676 | 677 | echo "
"; 678 | // echo ""; 679 | // echo ""; 680 | // echo ""; 681 | // 682 | // echo ""; 683 | // echo ""; 684 | // echo ""; 685 | // 686 | // echo ""; 687 | // echo ""; 688 | // echo ""; 689 | if ($validation->getFromDBByCrit(["status" => CommonITILValidation::WAITING, 690 | "users_id_validate" => Session::getLoginUserID(), 691 | "plugin_purchaserequest_purchaserequests_id" => $item->getID()])) { 692 | echo ""; 693 | echo ""; 694 | echo ""; 699 | echo ""; 704 | echo ""; 705 | 706 | echo Html::scriptBlock('$( "#accept_purchaserequest" ).click(function() { 707 | $( "#formvalidation" ).append(""); 708 | $( "#formvalidation" ).append(""); 709 | $( "#formvalidation" ).submit(); 710 | }); 711 | $( "#refuse_purchaserequest" ).click(function() { 712 | $( "#formvalidation" ).append(""); 713 | $( "#formvalidation" ).append(""); 714 | $( "#formvalidation" ).submit(); 715 | });'); 716 | echo ""; 717 | echo ""; 718 | 719 | echo ""; 720 | echo ""; 721 | echo ""; 730 | } 731 | 732 | $validator = ($item->fields["users_id_validate"] == Session::getLoginUserID()); 733 | 734 | 735 | echo "
" . __('Do you approve this purchase request ?', 'purchaserequest') . "
" . __('Approval requester') . "" . $dbu->getUserName($item->fields["users_id"]) . "
" . __('Approver') . "" . $dbu->getUserName($item->fields["users_id_validate"]) . "
" . __('Status of the approval request') . ""; 695 | echo "
"; 696 | echo "
" . __('Accept purchase request', 'purchaserequest') . "
"; 697 | echo Html::hidden('accept_purchaserequest', ['value' => 0]); 698 | echo "
"; 700 | echo "
"; 701 | echo "
" . __('Refuse purchase request', 'purchaserequest') . "
"; 702 | echo Html::hidden('refuse_purchaserequest', ['value' => 0]); 703 | echo "
" . __('Approval comments') . ""; 722 | Html::textarea(['name' => 'comment_validation', 723 | 'enable_richtext' => false, 724 | 'cols' => '90', 725 | 'rows' => '3']); 726 | echo Html::hidden('id', ['value' => $validation->fields['id']]); 727 | echo Html::hidden('users_id_validate', ['value' => Session::getLoginUserID()]); 728 | echo Html::hidden('plugin_purchaserequest_purchaserequests_id', ['value' => $item->fields['id']]); 729 | echo "
"; 736 | Html::closeForm(); 737 | 738 | $self = new self(); 739 | $self->showSummary($item); 740 | } 741 | 742 | 743 | /** 744 | * Print the validation list into item 745 | * 746 | * @param CommonDBTM $item 747 | **/ 748 | public function showSummary(CommonDBTM $item) 749 | { 750 | global $DB, $CFG_GLPI; 751 | 752 | // if (!Session::haveRightsOr(static::$rightname, 753 | // array_merge(static::getCreateRights(), 754 | // static::getValidateRights(), 755 | // static::getPurgeRights()))) { 756 | // return false; 757 | // } 758 | 759 | $tID = $item->fields['id']; 760 | 761 | $tmp = ["plugin_purchaserequest_purchaserequests_id" => $tID]; 762 | $canadd = $this->can(-1, CREATE, $tmp); 763 | $rand = mt_rand(); 764 | 765 | 766 | echo "
\n"; 767 | 768 | 769 | $iterator = $DB->Request([ 770 | 'FROM' => $this->getTable(), 771 | 'WHERE' => ["plugin_purchaserequest_purchaserequests_id" => $item->getField('id')], 772 | 'ORDER' => 'submission_date DESC', 773 | ]); 774 | 775 | $colonnes = [_x('item', 'State'), 776 | __('Request date'), 777 | __('Approval requester'), 778 | __('Approval status'), 779 | __('Approver'), 780 | __('Approval comments')]; 781 | $nb_colonnes = count($colonnes); 782 | 783 | echo ""; 784 | echo ""; 785 | echo ""; 788 | 789 | // if ($canadd) { 790 | // if (!in_array($item->fields['status'], array_merge($item->getSolvedStatusArray(), 791 | // $item->getClosedStatusArray()))) { 792 | // echo "\n"; 795 | // } 796 | // } 797 | if (count($iterator)) { 798 | $header = ""; 799 | foreach ($colonnes as $colonne) { 800 | $header .= ""; 801 | } 802 | $header .= ""; 803 | echo $header; 804 | 805 | Session::initNavigateListItems( 806 | $this->getType(), 807 | //TRANS : %1$s is the itemtype name, %2$s is the name of the item (used for headings of a list) 808 | sprintf( 809 | __('%1$s = %2$s'), 810 | $item->getTypeName(1), 811 | $item->fields["name"] 812 | ) 813 | ); 814 | 815 | foreach ($iterator as $row) { 816 | $canedit = $this->canEdit($row["id"]); 817 | Session::addToNavigateListItems($this->getType(), $row["id"]); 818 | $bgcolor = CommonITILValidation::getStatusColor($row['status']); 819 | $status = CommonITILValidation::getStatus($row['status']); 820 | 821 | echo ""; 822 | echo ""; 838 | 839 | echo ""; 840 | echo ""; 841 | 842 | echo ""; 843 | echo ""; 844 | echo ""; 845 | echo ""; 846 | $iterator->next(); 847 | } 848 | echo $header; 849 | } else { 850 | //echo "
".__('No results found')."
"; 851 | echo "\n"; 853 | } 854 | echo "
" ; 786 | echo __('Approvals for the purchase request', 'purchaserequest'); 787 | echo "
"; 793 | // echo ""; 794 | // echo __('Send an approval request')."
" . $colonne . "
"; 823 | // if ($canedit) { 824 | // echo "\n\n"; 835 | // } 836 | 837 | echo "
" . $status . "
" . Html::convDateTime($row["submission_date"]) . "" . getUserName($row["users_id"]) . "" . Html::convDateTime($row["validation_date"]) . "" . getUserName($row["users_id_validate"]) . "" . $row["comment_validation"] . "
"; 852 | echo __('No results found') . "
"; 855 | } 856 | 857 | 858 | /** 859 | * @param Migration $migration 860 | */ 861 | public static function install(Migration $migration) 862 | { 863 | global $DB; 864 | 865 | $dbu = new DbUtils(); 866 | $table = $dbu->getTableForItemType(__CLASS__); 867 | 868 | if (!$DB->tableExists($table)) { 869 | $migration->displayMessage("Installing $table"); 870 | $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_purchaserequest_validations` ( 871 | `id` int unsigned NOT NULL AUTO_INCREMENT, 872 | `entities_id` int unsigned NOT NULL DEFAULT '0', 873 | `users_id` int unsigned NOT NULL DEFAULT '0', 874 | `plugin_purchaserequest_purchaserequests_id` int unsigned NOT NULL DEFAULT '0', 875 | `users_id_validate` int unsigned NOT NULL DEFAULT '0', 876 | `status` int unsigned NOT NULL DEFAULT '0', 877 | `comment_validation` TEXT COLLATE utf8mb4_unicode_ci, 878 | `submission_date` timestamp NULL DEFAULT NULL, 879 | `validation_date` timestamp NULL DEFAULT NULL, 880 | PRIMARY KEY (`id`) 881 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;"; 882 | $DB->doQuery($query) or die($DB->error()); 883 | } else { 884 | } 885 | } 886 | 887 | public static function uninstall() 888 | { 889 | global $DB; 890 | 891 | $dbu = new DbUtils(); 892 | $table = $dbu->getTableForItemType(__CLASS__); 893 | $DB->doQuery("DROP TABLE IF EXISTS`" . $table . "`") or die($DB->error()); 894 | } 895 | } 896 | --------------------------------------------------------------------------------