This commit is contained in:
2024-12-19 11:04:51 +01:00
parent a3f54b2f11
commit f0e5d00970
104 changed files with 6578 additions and 6301 deletions

4
.cpkgrc Executable file
View File

@@ -0,0 +1,4 @@
REPO=stable
DISTRIB=eole
VERSION=2.7.2
pversion=''

View File

@@ -1,35 +1,10 @@
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
###> symfony/framework-bundle ###
APP_SECRET=52c1cb88ee822cd2643abe29e16a68a6
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
#TRUSTED_HOSTS='^(localhost|example\.com)$'
###< symfony/framework-bundle ###
###> symfony/mailer ###
# MAILER_DSN=smtp://localhost
###< symfony/mailer ###
###< doctrine/doctrine-bundle ###
# Basic
APP_ENV=PROD
APP_SECRET=changeme
APP_ALIAS=schedule
APP_AUTH=MYSQL
APP_NAME=Schedule
APP_ENV=PROD
APP_CRON=true
# Office hours
@@ -41,12 +16,13 @@ MAILER_METHOD=sendmail
MAILER_URL=
MAILER_NOREPLY=noreply@noreply.fr
MAILER_DEFAULT_NOTIF=
MAILER_URL=null://localhost
# BDD
DATABASE_NAME=
DATABASE_USER=
DATABASE_PASSWORD=
DATABASE_HOST=
DATABASE_HOST=mariadb
DATABASE_NAME=schedule
DATABASE_USER=user
DATABASE_PASSWORD=changeme
# If APP_AUTH = CAS
CAS_HOST=
@@ -64,14 +40,3 @@ SENTRY_DSN=
DOLIBARR_ACTIVE=false
DOLIBARR_API_KEY=
DOLIBARR_URI=
###> sentry/sentry-symfony ###
SENTRY_DSN=
###< sentry/sentry-symfony ###
###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###

View File

@@ -74,16 +74,11 @@
"symfony/polyfill-php70": "*",
"symfony/polyfill-php56": "*"
},
"scripts": {
"pre-install-cmd": [
"php scripts/checkcomposer.php"
],
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"cache:clear --env=prod": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"make:migration": "symfony-cmd",
"doctrine:migrations:migrate --no-interaction --allow-no-migration": "symfony-cmd"
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"

View File

@@ -11,3 +11,5 @@ twig:
appAuth: '%appAuth%'
appName: '%appName%'
appCron: '%appCron%'
doliActive: '%doliActive%'
doliUri: '%doliUri%'

View File

@@ -266,13 +266,13 @@ app_offer_viewservice:
path: /master/offer/viewservice
defaults: { _controller: App\Controller\OfferController:viewservice }
app_offer_getorders:
path: /master/offer/getorders
defaults: { _controller: App\Controller\OfferController:getorders }
app_offer_dolibarr:
path: /master/offer/dolibarr
defaults: { _controller: App\Controller\OfferController:dolibarr }
app_offer_convert:
path: /master/offer/convert/{type}/{id}
defaults: { _controller: App\Controller\OfferController:convert }
app_offer_getdolibarr:
path: /master/offer/getdolibarr
defaults: { _controller: App\Controller\OfferController:getdolibarr }
#== Task ====================================================================================================
app_task:

View File

@@ -0,0 +1,42 @@
version: '3'
services:
mariadb:
image: mariadb
container_name: schedule-mariadb
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: changeme
MYSQL_DATABASE: schedule
MYSQL_USER: user
MYSQL_PASSWORD: changeme
volumes:
- mariadb-data:/var/lib/mysql
adminer:
image: adminer
container_name: schedule-adminer
restart: always
ports:
- 6081:8080
schedule:
build:
context: .
dockerfile: ./misc/docker/Dockerfile
container_name: schedule-app
image: reg.cadoles.com/envole/schedule
#entrypoint: /bin/bash # Spécifiez le point d'entrée souhaité (dans cet exemple, /bin/bash)
#tty: true
#stdin_open: true
volumes:
- .:/app
ports:
- "8000:80"
environment:
APP_ENV: DEV
volumes:
mariadb-data:

View File

@@ -0,0 +1,14 @@
FROM reg.cadoles.com/envole/nineapache:7.4
COPY ./misc/docker/apache.conf /etc/apache2/conf.d/zapp.conf
RUN touch ~/.bashrc
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
RUN composer self-update --1
RUN echo "* * * * * /app/bin/console app:Cron --env=prod" >> /var/spool/cron/crontabs/root
WORKDIR /app
COPY . .
CMD /app/misc/script/reconfigure.sh && /etc/apache2/apache2.sh

View File

@@ -0,0 +1,19 @@
LoadModule rewrite_module modules/mod_rewrite.so
ServerName nineapache.local
DocumentRoot "/app/public"
Alias /schedule /app/public
<Directory "/app/public">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
RewriteEngine On
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]
</Directory>

View File

@@ -0,0 +1,22 @@
#!/bin/bash
set -eo pipefail
# Se positionner sur la racine du projet
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
cd ${DIR}
cd ../..
DIR=$(pwd)
# Installation des dépendances composer
composer install
bin/console d:s:u --force --complete
php bin/console app:AppInit --env=prod
php bin/console app:CronInit --env=prod
php bin/console app:Script --env=prod
crond -b
echo
exec $@

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5
src/schedule-2.0/src/Command/AppInitCommand.php Normal file → Executable file
View File

@@ -21,7 +21,6 @@ use App\Entity\Domaine;
class AppInitCommand extends Command
{
private $container;
private $em;
private $output;
@@ -68,7 +67,9 @@ class AppInitCommand extends Command
$output->writeln('');
return $this->em->flush();
$this->em->flush();
return 0;
}
protected function insertNature($id,$name,$isvacation) {

13
src/schedule-2.0/src/Command/CronCommand.php Normal file → Executable file
View File

@@ -103,7 +103,7 @@ class CronCommand extends Command
$parameter = new ArrayInput($jsonparameter);
// Executer la commande
$returnCode=false;
$returnCode==1;
try{
$returnCode = $command->run($parameter, $output);
@@ -132,12 +132,9 @@ class CronCommand extends Command
}
// Statut OK/KO/Retry
if($returnCode!="retry"||!$returnCode) {
$cron->setStatut(2);
if($returnCode!=1) {
$cron->setStatut(3);
if($cron->getRepeatcall()>0) $cron->setRepeatexec($cron->getRepeatexec()+1);
}
if($returnCode==1) {
$cron->setStatut(3);
if($cron->getRepeatcall()>0) $cron->setRepeatexec($cron->getRepeatexec()+1);
}
$this->em->persist($cron);
@@ -151,7 +148,7 @@ class CronCommand extends Command
$this->writelnred("");
}
return 1;
return 0;
}
private function writelnred($string) {

7
src/schedule-2.0/src/Command/CronInitCommand.php Normal file → Executable file
View File

@@ -44,8 +44,7 @@ class CronInitCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output)
{
$appCron = $this->container->getParameter('appCron');
if(!$appCron)
return false;
if(!$appCron) return 0;
$output->writeln('CRON = Default Data');
@@ -53,7 +52,9 @@ class CronInitCommand extends Command
$output->writeln('');
return $this->em->flush();
$this->em->flush();
return 0;
}
protected function insertCron() {

2
src/schedule-2.0/src/Command/DumpBddCommand.php Normal file → Executable file
View File

@@ -68,7 +68,7 @@ class DumpBddCommand extends Command
}
$this->writeln('');
return 1;
return 0;
}
protected function runCommand($command)

13
src/schedule-2.0/src/Command/ScriptCommand.php Normal file → Executable file
View File

@@ -46,10 +46,11 @@ class ScriptCommand extends Command
$output->writeln('APP = Scripts');
$this->callscript("initdomaine");
$this->callscript("initofferservice");
$output->writeln('');
return 1;
return 0;
}
@@ -77,6 +78,16 @@ class ScriptCommand extends Command
}
}
private function initofferservice() {
$offers=$this->em->getRepository("App:Offer")->findBy(["service"=>null]);
foreach($offers as $offer) {
$offer->setService($offer->getProject()->getService());
$this->em->persist($offer);
$this->em->flush();
}
}
private function writelnred($string) {
$this->output->writeln('<fg=red>'.$string.'</>');
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");

4
src/schedule-2.0/src/Command/SendMailCommand.php Normal file → Executable file
View File

@@ -67,11 +67,11 @@ class SendMailCommand extends Command
$this->writeln("");
$this->writelnred("Impossible d'envoyer des mails");
$this->writeln("");
return 0;
return 1;
}
$this->writeln("");
return 1;
return 0;
}

2
src/schedule-2.0/src/Command/SetPasswordCommand.php Normal file → Executable file
View File

@@ -65,7 +65,7 @@ class SetPasswordCommand extends Command
}
$this->writeln('');
return 1;
return 0;
}
private function writelnred($string) {

2
src/schedule-2.0/src/Command/SetRolesCommand.php Normal file → Executable file
View File

@@ -66,7 +66,7 @@ class SetRolesCommand extends Command
}
$this->writeln('');
return 1;
return 0;
}
private function writelnred($string) {

0
src/schedule-2.0/src/Controller/.gitignore vendored Normal file → Executable file
View File

0
src/schedule-2.0/src/Controller/CronController.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Controller/CropController.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Controller/ExportController.php Normal file → Executable file
View File

View File

@@ -5,11 +5,15 @@ namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Form\FormError;
use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
use App\Entity\Offer as Entity;
use App\Form\OfferType as Form;
use App\Form\OfferdolibarrType as Formdollibar;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class OfferController extends AbstractController
{
@@ -89,52 +93,7 @@ class OfferController extends AbstractController
'form' => $form->createView()
]);
}
public function convert($type, $id, Request $request)
{
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$data = new Entity();
$order = $this->dolibarrapi->getOrder($id, $type);
if (isset($order["ref_customer"]) && $order["ref_customer"]!= ""){
$data->setRef($order["ref_customer"]);
}
if (isset($order["ref"]) && $order["ref"]!= ""){
$data->setRef($order["ref"]);
}
$data->setName($order["customer_name"]);
$data->setQuantity($order["total_qty"]);
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"submit"));
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur erreur
$this->getErrorForm(null,$form,$request,$data,"submit");
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
$data->setIddolibarr($order["id"]);
$data->setTypedolibarr($type);
$em->persist($data);
$em->flush();
// Retour à la liste
return $this->redirectToRoute($this->route);
}
// Affichage du formulaire
return $this->render($this->render.'edit.html.twig', [
'useheader' => true,
'usesidebar' => true,
$this->data => $data,
'mode' => 'submit',
'form' => $form->createView()
]);
}
public function update($id,Request $request)
{
// Initialisation de l'enregistrement
@@ -228,66 +187,85 @@ class OfferController extends AbstractController
return $this->redirectToRoute($this->route);
}
public function getorders(){
public function dolibarr(Request $request) {
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$orders = $this->dolibarrapi->getOrders();
$propals = $this->dolibarrapi->getPropals();
$data = new Entity();
$tborders = [];
foreach($orders as $order){
if (intval($order["statut"]> 0)){
$exist1 = $em->getRepository($this->entity)->findOneBy(['ref' => $order["ref"]]);
$exist2 = $em->getRepository($this->entity)->findOneBy(['ref' => $order["ref_client"]]);
// Création du formulaire
$form = $this->createForm(Formdollibar::class,$data,array("mode"=>"submit"));
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur erreur
$this->getErrorForm(null,$form,$request,$data,"submit");
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
$tasks=json_decode($form->get("tasks")->getData());
foreach($tasks as $key=>$value) {
dump($value);
$iddolibarr=$value->idoffer."|".$value->idline;
// Recherche offer sur cet id
$offer=$em->getRepository($this->entity)->findOneBy(["iddolibarr" => $iddolibarr]);
if(!$offer) {
$offer=new Entity();
$offer->setName($data->getName()." = ".$value->label);
$offer->setRef($value->idoffer);
$offer->setIddolibarr($iddolibarr);
$offer->setProject($data->getProject());
$offer->setValidate(0);
$offer->setCost(0);
$offer->setActive(true);
// Déterminer le service
$services=$em->getRepository("App\Entity\Service")->findAll();
$myservice=$data->getProject()->getService();
foreach($services as $service) {
if($service->getDolibarrcode()) {
if(stripos($value->ref,$service->getDolibarrcode())===1)
$myservice=$service;
}
}
$offer->setService($service);
}
$offer->setQuantity($value->qty);
$offer->setPu($value->price);
if (!$exist1 && !$exist2) {
$torder["id"]=$order["id"];
$torder["customer_name"]=$order["customer_name"];
$torder["ref"]=$order["ref"];
$torder["ref_client"]=$order["ref_client"];
$torder["statut"]=$order["statut"];
$torder["total_ht"]=$order["total_ht"];
$torder["total_tva"]=$order["total_tva"];
$torder["total_ttc"]=$order["total_ttc"];
$torder["type"] = "commande";
array_push($tborders, $torder);
}
$em->persist($offer);
$em->flush();
}
/*
$em->persist($data);
$em->flush();
// Retour à la liste
return $this->redirectToRoute($this->route);
*/
}
foreach($propals as $propal){
if (intval($propal["statut"]> 1)){
$exist1 = false;
$exist2 = false;
if ($propal["ref"] != ""){
$exist1 = $em->getRepository($this->entity)->findOneBy(['ref' => $propal["ref"]]);
}
if ($propal["ref_client"] != ""){
$exist2 = $em->getRepository($this->entity)->findOneBy(['ref' => $propal["ref_client"]]);
}
if (!$exist1 && !$exist2) {
$tpropal["id"]=$propal["id"];
$tpropal["customer_name"]=$propal["customer_name"];
$tpropal["ref"]=$propal["ref"];
$tpropal["ref_client"]=$propal["ref_client"];
$tpropal["statut"]=$propal["statut"];
$tpropal["total_ht"]=$propal["total_ht"];
$tpropal["total_tva"]=$propal["total_tva"];
$tpropal["total_ttc"]=$propal["total_ttc"];
$tpropal["type"] = "propal";
array_push($tborders, $tpropal);
}
}
}
return $this->render($this->render.'getorders.html.twig', [
return $this->render($this->render.'dolibarr.html.twig', [
'useheader' => true,
'usesidebar' => true,
'orders' => $tborders
'usesidebar' => true,
'form' => $form->createView()
]);
}
public function getDolibarr(Request $request){
$ref = $request->request->get('ref');
$order = $this->dolibarrapi->getOrder($ref);
return new JsonResponse($order);
}
protected function getErrorForm($id,$form,$request,$data,$mode) {
if ($form->get('submit')->isClicked()&&$mode=="delete") {
}

0
src/schedule-2.0/src/Controller/RestController.php Normal file → Executable file
View File

View File

@@ -48,7 +48,6 @@ class SecurityController extends AbstractController
$redirect = $request->get("redirect");
// Init Client CAS
\phpCAS::setDebug('/var/www/html/schedule/var/log/cas.log');
\phpCAS::client(CAS_VERSION_2_0, $this->getParameter('casHost'), intval($this->getParameter('casPort')), is_null($this->getParameter('casPath')) ? '' : $this->getParameter('casPath'), false);
\phpCAS::setNoCasServerValidation();
@@ -147,7 +146,6 @@ class SecurityController extends AbstractController
public function logoutcas() {
// Init Client CAS
\phpCAS::setDebug('/var/www/html/schedule/var/log/cas.log');
\phpCAS::client(CAS_VERSION_2_0, $this->getParameter('casHost'), intval($this->getParameter('casPort')), is_null($this->getParameter('casPath')) ? '' : $this->getParameter('casPath'), false);
\phpCAS::setNoCasServerValidation();

View File

@@ -55,7 +55,7 @@ class ServiceController extends AbstractController
$data = new Entity();
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"submit"));
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","doliActive"=>$this->getParameter("doliActive")));
// Récupération des data du formulaire
$form->handleRequest($request);
@@ -90,7 +90,7 @@ class ServiceController extends AbstractController
$data=$em->getRepository($this->entity)->find($id);
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"update"));
$form = $this->createForm(Form::class,$data,array("mode"=>"update","doliActive"=>$this->getParameter("doliActive")));
// Récupération des data du formulaire
$form->handleRequest($request);

0
src/schedule-2.0/src/Controller/TimerController.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/.gitignore vendored Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Breakday.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Cron.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Customer.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Domaine.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Event.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Job.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Nature.php Normal file → Executable file
View File

36
src/schedule-2.0/src/Entity/Offer.php Normal file → Executable file
View File

@@ -66,21 +66,21 @@ class Offer
private $active;
/**
* @ORM\Column(name="iddolibarr", type="decimal", scale=5, nullable=true)
* @ORM\Column(name="iddolibarr", type="string", nullable=true)
*
*/
private $iddolibarr;
/**
* @ORM\Column(name="typedolibarr", type="string", nullable=true)
*
*/
private $typedolibarr;
/**
* @ORM\ManyToOne(targetEntity="Project", inversedBy="offers")
*/
private $project;
/**
* @ORM\ManyToOne(targetEntity="Service", inversedBy="offers")
*/
private $service;
public function getTotal()
{
return $this->quantity*$this->pu;
@@ -186,18 +186,6 @@ class Offer
return $this;
}
public function getTypedolibarr(): ?string
{
return $this->typedolibarr;
}
public function setTypedolibarr(?string $typedolibarr): self
{
$this->typedolibarr = $typedolibarr;
return $this;
}
public function getCost(): ?string
{
return $this->cost;
@@ -210,5 +198,17 @@ class Offer
return $this;
}
public function getService(): ?Service
{
return $this->service;
}
public function setService(?Service $service): self
{
$this->service = $service;
return $this;
}
}

0
src/schedule-2.0/src/Entity/Penalty.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Project.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Script.php Normal file → Executable file
View File

57
src/schedule-2.0/src/Entity/Service.php Normal file → Executable file
View File

@@ -32,7 +32,13 @@ class Service
* @ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* @ORM\Column(name="dolibarrcode", type="string", nullable=true)
*
*/
private $dolibarrcode;
/**
* @ORM\OneToMany(targetEntity="User", mappedBy="service", cascade={"persist"}, orphanRemoval=false)
*/
@@ -43,10 +49,16 @@ class Service
*/
private $projects;
/**
* @ORM\OneToMany(targetEntity="Offer", mappedBy="service", cascade={"persist"}, orphanRemoval=false)
*/
private $offers;
public function __construct()
{
$this->users = new ArrayCollection();
$this->projects = new ArrayCollection();
$this->offers = new ArrayCollection();
}
@@ -138,6 +150,49 @@ class Service
}
}
return $this;
}
/**
* @return Collection|Offer[]
*/
public function getOffers(): Collection
{
return $this->offers;
}
public function addOffer(Offer $offer): self
{
if (!$this->offers->contains($offer)) {
$this->offers[] = $offer;
$offer->setService($this);
}
return $this;
}
public function removeOffer(Offer $offer): self
{
if ($this->offers->contains($offer)) {
$this->offers->removeElement($offer);
// set the owning side to null (unless already changed)
if ($offer->getService() === $this) {
$offer->setService(null);
}
}
return $this;
}
public function getDolibarrcode(): ?string
{
return $this->dolibarrcode;
}
public function setDolibarrcode(string $dolibarrcode): self
{
$this->dolibarrcode = $dolibarrcode;
return $this;
}

0
src/schedule-2.0/src/Entity/Task.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Timer.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/User.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Userproject.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Year.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Yeardomaine.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Entity/Yearproject.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/BreakdayType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/CronType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/CustomerType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/DomaineType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/JobType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/NatureType.php Normal file → Executable file
View File

10
src/schedule-2.0/src/Form/OfferType.php Normal file → Executable file
View File

@@ -109,6 +109,16 @@ class OfferType extends AbstractType
]
);
$builder->add('service',
EntityType::class, [
"class" => "App:Service",
"label" => "Service",
"choice_label" => "name",
"placeholder" => "Selectionner un Service",
]
);
}
public function configureOptions(OptionsResolver $resolver)

View File

@@ -0,0 +1,77 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
class OfferdolibarrType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('submit',
SubmitType::class, [
"label" => "Valider",
"attr" => ["class" => "btn btn-success no-print"],
]
);
$builder->add('name',
TextType::class, [
"label" => "Nom (désignation produit ajoutée en fin de nom automatiquement)"
]
);
$builder->add('project',
Select2EntityType::class, [
"label" => "Projet",
"disabled" => false,
"required" => true,
"multiple" => false,
"remote_route" => "app_project_select",
"class" => "App:Project",
"primary_key" => "id",
"text_property" => "displayname",
"minimum_input_length" => 0,
"page_limit" => 10,
"allow_clear" => true,
"delay" => 250,
"cache" => false,
"cache_timeout" => 60000,
"language" => "fr",
"theme" => "bootstrap4",
"placeholder" => "Selectionner un Projet",
//"attr" => ["class" => "form-control", "style" => "margin-bottom:15px"]
]
);
$builder->add('tasks', HiddenType::class,["mapped" => false]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\Entity\Offer',
'mode' => 'string',
));
}
}

2
src/schedule-2.0/src/Form/ProjectType.php Normal file → Executable file
View File

@@ -69,7 +69,7 @@ class ProjectType extends AbstractType
$builder->add('service',
EntityType::class, [
"class" => "App:Service",
"label" => "Activité",
"label" => "Service",
"choice_label" => "name",
]
);

10
src/schedule-2.0/src/Form/ServiceType.php Normal file → Executable file
View File

@@ -46,6 +46,15 @@ class ServiceType extends AbstractType
],
]
);
if($options["doliActive"]) {
$builder->add('dolibarrcode',
TextType::class, [
"required" => false,
"label" =>"Code Produit Dolibarr"
]
);
}
}
public function configureOptions(OptionsResolver $resolver)
@@ -53,6 +62,7 @@ class ServiceType extends AbstractType
$resolver->setDefaults(array(
'data_class' => 'App\Entity\Service',
'mode' => 'string',
'doliActive' => 'string',
));
}
}

0
src/schedule-2.0/src/Form/TaskType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/TimerType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/UserType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/YearType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/YeardomaineType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Form/YearprojectType.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Kernel.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Migrations/.gitignore vendored Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/.gitignore vendored Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/BreakdayRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/CronRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/CustomerRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/DomaineRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/EventRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/JobRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/NatureRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/OfferRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/PenaltyRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/ProjectRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/ScriptRepository.php Normal file → Executable file
View File

2
src/schedule-2.0/src/Repository/ServiceRepository.php Normal file → Executable file
View File

@@ -34,7 +34,7 @@ class ServiceRepository extends ServiceEntityRepository
->from('App:Offer','offer')
->Where('offer.active=:activeoffer')
->andWhere('project.active=:activeproject')
->andWhere('project.service=service')
->andWhere('offer.service=service')
->andWhere('offer.project=project');
if($idservice!="all")

0
src/schedule-2.0/src/Repository/TaskRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/TimerRepository.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Repository/UserRepository.php Normal file → Executable file
View File

View File

117
src/schedule-2.0/src/Service/dolibarrApi.php Normal file → Executable file
View File

@@ -15,6 +15,7 @@ class dolibarrApi
private $session;
private $client;
private $doliuri;
private $dolikey;
public function __construct(EntityManagerInterface $em, ContainerInterface $container, HttpClientInterface $client )
{
@@ -22,77 +23,61 @@ class dolibarrApi
$this->container = $container;
$this->client = $client;
$this->doliuri = $this->container->getParameter('doliUri');
$this->dolikey = $this->container->getParameter('doliApiKey');
}
public function getOrders() {
$start=new \Datetime();
$start->sub(new \DateInterval('P6M'));
$response = $this->client->request('GET',$this->doliuri."/api/index.php/orders?sortfield=t.rowid&sortorder=DESC&limit=100&sqlfilters=(t.date_creation%3A%3E%3A'".$start->format("Ymd")."')");
$content = $response->toArray();
$tbcontent = [];
foreach($content as $order){
$order['customer_name'] = $this->getCustomer($order['socid']);
$qty = 0;
foreach($order['lines'] as $line){
$qty = $qty + intval($line['qty']);
private function CallAPI($method, $url, $data = false)
{
$curl = curl_init();
$httpheader = ['DOLAPIKEY: '.$this->dolikey];
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
$httpheader[] = "Content-Type:application/json";
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
$httpheader[] = "Content-Type:application/json";
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
default:
if ($data)
$url = sprintf("%s%s?DOLAPIKEY=%s&%s", $this->doliuri."/api/index.php/", $url, $this->dolikey, http_build_query($data));
else
$url = sprintf("%s%s?DOLAPIKEY=%s", $this->doliuri."/api/index.php/", $url, $this->dolikey);
}
$order['total_qty'] = $qty;
array_push($tbcontent, $order);
}
return $tbcontent;
}
public function getOrder($id, $type) {
$start=new \Datetime();
$start->sub(new \DateInterval('P6M'));
$order=[];
if ($type =="commande") {
$response = $this->client->request('GET',$this->doliuri."/api/index.php/orders/".$id);
$order=$response->toArray();
}
if ($type =="propal") {
$response = $this->client->request('GET',$this->doliuri."/api/index.php/proposals/".$id);
$order=$response->toArray();
}
$order['customer_name'] = $this->getCustomer($order['socid']);
$qty = 0;
foreach($order['lines'] as $line){
$qty = $qty + intval($line['qty']);
}
$order['total_qty'] = $qty;
return $order;
// Optional Authentication:
// curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
// curl_setopt($curl, CURLOPT_USERPWD, "username:password");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
public function getPropals() {
$start=new \Datetime();
$start->sub(new \DateInterval('P6M'));
$response = $this->client->request('GET',$this->doliuri."/api/index.php/proposals?sortfield=t.rowid&sortorder=DESC&limit=100&sqlfilters=(t.datec%3A%3E%3A'".$start->format("Ymd")."')");
$content = $response->toArray();
$tbcontent = [];
foreach($content as $propal){
$propal['customer_name'] = $this->getCustomer($propal['socid']);
$qty = 0;
foreach($propal['lines'] as $line){
$qty = $qty + intval($line['qty']);
}
$propal['total_qty'] = $qty;
//$propal['customer_name'] = $this->getCustomer($propal['socid']);
array_push( $tbcontent, $propal);
}
return $tbcontent;
public function getOrder($ref) {
$response = $this->CallAPI('GET','orders/ref/'.$ref);
return json_decode($response);
}
public function getCustomer($customerid) {
$response = $this->client->request('GET',$this->doliuri."/api/index.php/thirdparties/".$customerid);
$content = $response->toArray();
return $content['name'];
}
}

0
src/schedule-2.0/src/Service/icsService.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Service/notificationService.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Service/passwordEncoder.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Service/sessionListener.php Normal file → Executable file
View File

0
src/schedule-2.0/src/Service/uploadListener.php Normal file → Executable file
View File

View File

@@ -198,7 +198,7 @@
]
},
"php": {
"version": "7.2"
"version": "7.4"
},
"php-http/client-common": {
"version": "2.3.0"

View File

@@ -0,0 +1,116 @@
{% extends 'base.html.twig' %}
{% block body %}
<h1 class="page-header">
Récupération Commande Client Dolibarr
</h1>
<a class="btn btn-secondary" href={{ path('app_offer') }}>Annuler</a>
<br><br>
<div class="card">
<div class="card-header">
<i class="fa fa-pencil-alt fa-fw"></i> Informations
</div>
<div class="card-body">
<div class="form-group ">
<label class="control-label required" for="id">ID Proposition<span class="mandatory">*</span></label>
<input type="text" id="ref" name="ref" required="required" class=" form-control" value="CO2311-0222">
<button id="search" class="btn btn-success mt-1" style="width:100%">Rechercher</span>
</div>
</div>
</div>
<div id="card-propal" class="card mt-3" style="display:none">
<div class="card-header">
<i class="fa fa-pencil-alt fa-fw"></i> Lignes propositions
</div>
<div class="card-body" id="propal">
</div>
</div>
<div id="card-offer" class="card mt-3 mb-3" style="display:none">
<div class="card-header">
<i class="fa fa-pencil-alt fa-fw"></i> Importer dans Schedule
</div>
<div class="card-body" id="propal">
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.project) }}
{{ form_widget(form.submit) }}
{{ form_end(form) }}
</div>
</div>
{% endblock %}
{% block localjavascript %}
$("#search").click(function() {
console.log("search propositions = "+$("#ref").val());
$.ajax({
type: "POST",
data: {
ref: $("#ref").val(),
},
url: "{{ path('app_offer_getdolibarr') }}",
success: function (datas) {
console.log(datas);
console.log("-----------");
if(datas.error||Object.keys(datas).length === 0) {
$("#propal").html("");
$("#card-propal").hide();
$("#card-offer").hide();
}
else {
html ="<h3>"+$("#ref").val()+"</h3>";
if(datas.note_public) html+="<strong>Note public</strong><br><small style='display: block;line-height: 14px;'>"+datas.note_public.replace(/(\r\n|\r|\n)/g, '<br>')+"</small><br><br>";
if(datas.note_private) html+="<strong>Note privée</strong><br><small style='display: block;line-height: 14px;'>"+datas.note_private.replace(/(\r\n|\r|\n)/g, '<br>')+"</small><br><br>";
tbtask={};
datas.lines.forEach(function(line){
console.log(line);
if(!tbtask[line.product_ref]) tbtask[line.product_ref]={idoffer:"", idline: "", ref: "", label: "", qty: 0, price:0 };
tbtask[line.product_ref]["idoffer"]=$("#ref").val();
tbtask[line.product_ref]["idline"]=line.id;
tbtask[line.product_ref]["ref"]=line.product_ref;
tbtask[line.product_ref]["label"]=line.product_label;
tbtask[line.product_ref]["qty"]=parseInt(line.qty)+tbtask[line.product_ref]["qty"];
tbtask[line.product_ref]["price"]=parseInt(line.price);
});
html+="<table style='width:100%;'>";
html+="<thead><tr>";
html+="<th>Ref</th>";
html+="<th>Designation</th>";
html+="<th>Qte</th>";
html+="<th>PU</th>";
html+="<th>Total</th>";
html+="</tr></thead>";
Object.values(tbtask).forEach(task => {
html+="<tr>";
html+="<td>"+task.ref+"</td>";
html+="<td>"+task.label+"</td>";
html+="<td>"+task.qty+"</td>";
html+="<td>"+task.price+"</td>";
html+="<td>"+(task.qty*task.price)+"</td>";
html+="</tr>";
});
html+="</table>";
$("#propal").html(html);
$("#card-propal").show();
$("#card-offer").show();
$("#offerdolibarr_tasks").val(JSON.stringify(tbtask));
}
}
});
});
{% endblock %}

View File

@@ -53,6 +53,7 @@
<div class="card-body">
{{ form_row(form.name) }}
{{ form_row(form.ref) }}
{{ form_row(form.service) }}
{{ form_row(form.project) }}
{{ form_row(form.quantity) }}

View File

@@ -1,75 +0,0 @@
{% extends "base.html.twig" %}
{% block localstyle %}
td {
padding:5px !important;
}
{% if fgprint is defined and fgprint %}
table { font-size:10px;}
th,td {
border: 1px solid #37474F;
}
thead {
display: table-header-group;
}
tr { page-break-inside: avoid; }
{%endif%}
{% endblock %}
{% block body %}
<h1 class="page-header">
Nouvelles Commandes Dolibarr
</h1>
<p>Liste des dernières commandes/propal récupérées depuis Dolibarr.<br>
Les commandes doivent avoir un statut "Validée", et le Propal un statut "Signée" pour apparaître dans la liste.</p>
<div class="card">
<div class="dataTable_wrapper">
<table class="table table-striped table-bordered table-hover small" id="dataTables" style="width:100%">
<thead>
<tr>
<th width="70px" class="no-sort no-print">Action</th>
<th width="300px">client</th>
<th width="150px">ref</th>
<th width="150px">ref_client</th>
<th width="50">statut</th>
<th width="100px" class="text-center no-sort no-string">total_ht</th>
<th width="100px" class="text-center no-sort no-string">total_tva</th>
<th width="100px" class="text-center no-sort no-string">total_ttc</th>
</tr>
</thead>
<tbody>
{% for order in orders %}
<tr>
<td class="no-print">
<a href="{{path("app_offer_convert", {type:order.type, id:order.id})}}"><i class="fas fa-file-download"></i></a>
</td>
<td>{{order.customer_name}}</td>
{% if order.type =="commande" %}<td><a href="https://doli.cadoles.com/dolibarr/commande/card.php?id={{order.id}}" target="_blank">{{order.ref}}</td>{% endif %}
{% if order.type =="propal" %}<td><a href="https://doli.cadoles.com/dolibarr/comm/propal/card.php?id={{order.id}}" target="_blank">{{order.ref}}</td>{% endif %}
<td>{{order.ref_client}}</td>
<td>{{order.statut}}</td>
<td class="text-right">{{order.total_ht|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{order.total_tva|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{order.total_ttc|number_format(2, '.', ' ')}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block localjavascript %}
$(document).ready(function() {
$('#dataTables').DataTable({
columnDefs: [ { "targets": "no-sort", "orderable": false }, { "targets": "no-string", "type" : "num" } ],
responsive: true,
iDisplayLength: 100,
order: [[ 2, "asc" ]]
});
});
{% endblock %}

View File

@@ -23,7 +23,7 @@
<a class="btn btn-success" href={{ path('app_offer_submit') }}>Ajouter</a>
{% if doliactive == "true" %}
<a class="btn btn-success" href={{ path('app_offer_getorders') }}>Récupérer les commandes de Dolibarr</a>
<a class="btn btn-success" href={{ path('app_offer_dolibarr') }}>Récupérer les commandes de Dolibarr</a>
{% endif %}
<div class="custom-control custom-switch float-right">
@@ -57,14 +57,9 @@
{% if not loop01.projects is empty %}
{% set haveoffer=false %}
{% set haveproject=false %}
{% for project in loop01.projects %}
{% if app.session.get('activeproject')==project.active and (app.session.get('idproject')=="all" or app.session.get('idproject')==project.id) %}
{% for offer in project.offers %}
{% if app.session.get('activeoffer')==offer.active %}
{% set haveoffer=true %}
{% endif %}
{% endfor %}
{% for offer in loop01.offers %}
{% if app.session.get('activeoffer')==offer.active and app.session.get('activeproject')==offer.project.active and (app.session.get('idproject')=="all" or app.session.get('idproject')==offer.project.id) %}
{% set haveoffer=true %}
{% set haveproject=true %}
{% endif %}
{% endfor %}
@@ -94,10 +89,36 @@
</tr>
</thead>
<tbody>
{% for project in loop01.projects %}
{% if app.session.get('activeproject')==project.active and (app.session.get('idproject')=="all" or app.session.get('idproject')==project.id) %}
{% if loop01.offers is defined %}
{% for offer in loop01.offers %}
{% if app.session.get('activeoffer')==offer.active and app.session.get('activeproject')==offer.project.active and (app.session.get('idproject')=="all" or app.session.get('idproject')==offer.project.id) %}
<tr>
<td class="no-print">
<a href="{{path("app_offer_update",{id:offer.id})}}"><i class="fa fa-file"></i></a>
</td>
<td>{{offer.project.customer.name}}</td>
<td>{{offer.project.name}}</td>
<td>{{offer.name}}</td>
{% if offer.iddolibarr %}
<td><a href="{{doliUri}}/commande/card.php?ref={{offer.ref}}" target="_blank">{{offer.ref}}</td>
{% else %}
<td>{{offer.ref}}</td>
{% endif %}
<td class="text-right">{{offer.validate|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.cost|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.quantity|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.pu|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.total|number_format(2, '.', ' ')}}</td>
</tr>
{%endif%}
{% endfor %}
{% else %}
{% for project in loop01.projects %}
{% for offer in project.offers %}
{% if app.session.get('activeoffer')==offer.active %}
{% if app.session.get('activeoffer')==offer.active and app.session.get('activeproject')==offer.project.active and (app.session.get('idproject')=="all" or app.session.get('idproject')==offer.project.id) %}
<tr>
<td class="no-print">
<a href="{{path("app_offer_update",{id:offer.id})}}"><i class="fa fa-file"></i></a>
@@ -105,11 +126,11 @@
<td>{{offer.project.customer.name}}</td>
<td>{{offer.project.name}}</td>
<td>{{offer.name}}</td>
{%if offer.iddolibarr %}
{% if offer.typedolibarr == "commande" %}<td><a href="https://doli.cadoles.com/dolibarr/commande/card.php?id={{offer.iddolibarr}}" target="_blank">{{offer.ref}}</td>{% endif %}
{% if offer.typedolibarr == "propal" %}<td><a href="https://doli.cadoles.com/dolibarr/comm/propal/card.php?id={{offer.iddolibarr}}" target="_blank">{{offer.ref}}</td>{% endif %}
{% endif %}
{% if offer.iddolibarr %}
<td><a href="{{doliUri}}/commande/card.php?ref={{offer.ref}}" target="_blank">{{offer.ref}}</td>
{% else %}
<td>{{offer.ref}}</td>
{% endif %}
<td class="text-right">{{offer.validate|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.cost|number_format(2, '.', ' ')}}</td>
@@ -117,10 +138,10 @@
<td class="text-right">{{offer.pu|number_format(2, '.', ' ')}}</td>
<td class="text-right">{{offer.total|number_format(2, '.', ' ')}}</td>
</tr>
{% endif %}
{% endfor %}
{%endif%}
{% endfor %}
{%endif%}
{% endfor %}
{% endfor %}
{% endif %}
</tbody>
</table>
</div>

Some files were not shown because too many files have changed in this diff Show More