diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 52262405376..09a90516c57 100755 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -95,6 +95,9 @@ clearstatcache(); $workflowcodes=array(); if ($conf->propal->enabled && $conf->commande->enabled) $workflowcodes['WORKFLOW_PROPAL_AUTOCREATE_ORDER']='WORKFLOW_PROPAL_AUTOCREATE_ORDER'; +//if ($conf->propal->enabled && $conf->facture->enabled) $workflowcodes['WORKFLOW_PROPAL_AUTOCREATE_INVOICE']='WORKFLOW_PROPAL_AUTOCREATE_INVOICE'; +//if ($conf->contrat->enabled && $conf->facture->enabled) $workflowcodes['WORKFLOW_CONTRACT_AUTOCREATE_INVOICE']='WORKFLOW_CONTRACT_AUTOCREATE_INVOICE'; +//if ($conf->commande->enabled && $conf->facture->enabled) $workflowcodes['WORKFLOW_ORDER_AUTOCREATE_INVOICE']='WORKFLOW_ORDER_AUTOCREATE_INVOICE'; if (sizeof($workflowcodes) > 0) { diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 63ad1edcae8..3eac7f242b1 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -444,20 +444,25 @@ class Commande extends CommonObject } /** - * \brief Cloture la commande - * \param user Objet utilisateur qui cloture - * \return int <0 if KO, >0 if OK + * Close order + * @param user Objet user that close + * @return int <0 if KO, >0 if OK */ function cloture($user) { global $conf; + $error=0; if ($user->rights->commande->valider) { + $this->db->begin(); + + $now=dol_now(); + $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; $sql.= ' SET fk_statut = 3,'; $sql.= ' fk_user_cloture = '.$user->id.','; - $sql.= ' date_cloture = '.$this->db->idate(mktime()); + $sql.= ' date_cloture = '.$this->db->idate($now); $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut > 0'; if ($this->db->query($sql)) @@ -466,17 +471,26 @@ class Commande extends CommonObject include_once(DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php"); $interface=new Interfaces($this->db); $result=$interface->run_triggers('ORDER_CLOSE',$this,$user,$langs,$conf); - if ($result < 0) { - $error++; $this->errors=$interface->errors; - return -1; - } + if ($result < 0) { $error++; $this->errors=$interface->errors; } // Fin appel triggers - return 1; + + if (! $error) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } } else { - $this->error=$this->db->error(); + $this->error=$this->db->lasterror(); dol_syslog($this->error, LOG_ERR); + + $this->db->rollback(); return -1; } } @@ -923,6 +937,7 @@ class Commande extends CommonObject } else return -1; } + else return -1; } else return 0; } diff --git a/htdocs/commande/fiche.php b/htdocs/commande/fiche.php index 34793ac3164..80664161455 100644 --- a/htdocs/commande/fiche.php +++ b/htdocs/commande/fiche.php @@ -779,6 +779,7 @@ if ($action == 'confirm_close' && $confirm == 'yes' && $user->rights->commande-> $object->fetch($id); // Load order and lines $result = $object->cloture($user); + if ($result < 0) $mesgs=$object->errors; } if ($action == 'confirm_cancel' && $confirm == 'yes' && $user->rights->commande->valider) @@ -1123,7 +1124,7 @@ if ($action == 'create' && $user->rights->commande->creer) { print_fiche_titre($langs->trans('CreateOrder')); - if ($mesg) print $mesg.'
'; + dol_htmloutput_errors($mesg,$mesgs); $soc = new Societe($db); if ($socid) $res=$soc->fetch($socid); @@ -1423,7 +1424,7 @@ else if ($id > 0 || ! empty($ref)) { - if ($mesg) print $mesg.'
'; + dol_htmloutput_errors($mesg,$mesgs); $product_static=new Product($db); diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 011dd922b2d..0cffecf90c2 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -512,7 +512,7 @@ if ($action == 'add' && $user->rights->facture->creer) $object->socid=GETPOST('socid'); $db->begin(); - + $error=0; // Replacement invoice @@ -1148,7 +1148,7 @@ if ($_POST['addfile']) { require_once(DOL_DOCUMENT_ROOT."/lib/files.lib.php"); - // Set tmp user directory TODO Use a dedicated directory for temp mails files + // Set tmp user directory $vardir=$conf->user->dir_output."/".$user->id; $upload_dir = $vardir.'/temp/'; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index bfb9843379c..4247c1f8eb2 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -136,11 +136,11 @@ class Facture extends CommonObject /** * Create invoice in database + * Note: this->ref can be set or empty. If empty, we will use "(PROV)" * @param user Object user that create * @param notrigger 1=Does not execute triggers, 0 otherwise * @param forceduedate 1=Do not recalculate due date from payment condition but force it with value * @return int <0 if KO, >0 if OK - * @remarks this->ref can be set or empty. If empty, we will use "(PROV)" */ function create($user,$notrigger=0,$forceduedate=0) { @@ -602,6 +602,84 @@ class Facture extends CommonObject } } + /** + * Load an object from an order and create a new invoice into database + * @param object Object source + * @return int <0 if KO, 0 if nothing done, 1 if OK + */ + function createFromOrder($object) + { + global $conf,$user,$langs; + + $error=0; + + // Closed order + $this->date = dol_now(); + $this->source = 0; + + for ($i = 0 ; $i < sizeof($object->lines) ; $i++) + { + $line = new FactureLigne($this->db); + + $line->libelle = $object->lines[$i]->libelle; + $line->desc = $object->lines[$i]->desc; + $line->price = $object->lines[$i]->price; + $line->subprice = $object->lines[$i]->subprice; + $line->tva_tx = $object->lines[$i]->tva_tx; + $line->localtax1_tx = $object->lines[$i]->localtax1_tx; + $line->localtax2_tx = $object->lines[$i]->localtax2_tx; + $line->qty = $object->lines[$i]->qty; + $line->fk_remise_except = $object->lines[$i]->fk_remise_except; + $line->remise_percent = $object->lines[$i]->remise_percent; + $line->fk_product = $object->lines[$i]->fk_product; + $line->info_bits = $object->lines[$i]->info_bits; + $line->product_type = $object->lines[$i]->product_type; + $line->rang = $object->lines[$i]->rang; + $line->special_code = $object->lines[$i]->special_code; + $line->fk_parent_line = $object->lines[$i]->fk_parent_line; + + $this->lines[$i] = $line; + } + + $this->socid = $object->socid; + $this->fk_project = $object->fk_project; + $this->cond_reglement_id = $object->cond_reglement_id; + $this->mode_reglement_id = $object->mode_reglement_id; + $this->availability_id = $object->availability_id; + $this->demand_reason_id = $object->demand_reason_id; + $this->date_livraison = $object->date_livraison; + $this->fk_delivery_address = $object->fk_delivery_address; + $this->contact_id = $object->contactid; + $this->ref_client = $object->ref_client; + $this->note = $object->note; + $this->note_public = $object->note_public; + + $this->origin = $object->element; + $this->origin_id = $object->id; + + $ret = $this->create($user); + + if ($ret > 0) + { + // Hooks + if (! empty($object->hooks['objectcard'])) + { + foreach($object->hooks['objectcard'] as $module) + { + $result = $module->createfrom($object,$ret,$this->element); + if ($result < 0) $error++; + } + } + + if (! $error) + { + return 1; + } + else return -1; + } + else return -1; + } + /** * Return clicable link of object (with eventually picto) * @param withpicto Add picto into link diff --git a/htdocs/includes/triggers/interface_modWorkflow_WorkflowManager.class.php b/htdocs/includes/triggers/interface_modWorkflow_WorkflowManager.class.php index 2ba6172b928..8bef1eaa587 100755 --- a/htdocs/includes/triggers/interface_modWorkflow_WorkflowManager.class.php +++ b/htdocs/includes/triggers/interface_modWorkflow_WorkflowManager.class.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2010 Regis Houssin + * Copyright (C) 2011 Laurent Destailleur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -104,11 +105,27 @@ class InterfaceWorkflowManager { include_once(DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'); $order = new Commande($this->db); - return $order->createFromProposal($object,0); + $ret=$order->createFromProposal($object,0); + if ($ret < 0) { $this->error=$invoice->error; $this->errors[]=$invoice->error; } + return $ret; } } - return 0; + // Order to invoice + if ($action == 'ORDER_CLOSE') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_ORDER_AUTOCREATE_INVOICE)) + { + include_once(DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'); + $invoice = new Facture($this->db); + $ret=$invoice->createFromOrder($object,0); + if ($ret < 0) { $this->error=$invoice->error; $this->errors[]=$invoice->error; } + return $ret; + } + } + + return 0; } } diff --git a/htdocs/langs/en_US/workflow.lang b/htdocs/langs/en_US/workflow.lang index b0105dd7e03..bfdef03df19 100755 --- a/htdocs/langs/en_US/workflow.lang +++ b/htdocs/langs/en_US/workflow.lang @@ -4,3 +4,6 @@ WorkflowSetup=Workflow module setup WorkflowDesc=This module is desinged to modify the behaviour of automatic actions into application. By default, workflow is opened (you make thing in order you want). You can enabled automatic actions that you are interesting in. ThereIsNoWorkflowToModify=There is no workflow you can modify for module you have activated. descWORKFLOW_PROPAL_AUTOCREATE_ORDER=Create a customer order automatically after a commercial proposal is signed +descWORKFLOW_PROPAL_AUTOCREATE_INVOICE=Create a customer invoice automatically after a commercial proposal is signed +descWORKFLOW_CONTRACT_AUTOCREATE_INVOICE=Create a customer invoice automatically after a contract is validated +descWORKFLOW_ORDER_AUTOCREATE_INVOICE=Create a customer invoice automatically after a customer order is closed \ No newline at end of file diff --git a/htdocs/langs/fr_FR/workflow.lang b/htdocs/langs/fr_FR/workflow.lang index ce3143c7f3e..06f59ea9e02 100755 --- a/htdocs/langs/fr_FR/workflow.lang +++ b/htdocs/langs/fr_FR/workflow.lang @@ -4,3 +4,6 @@ WorkflowSetup=Configuration du module workflow WorkflowDesc=Ce module vous permet de modifier le comportement d'enchainement automatisé. Par défaut, le workflow est ouvert et non imposé. A vous d'activer les liens automatiques qui vous intéressent. ThereIsNoWorkflowToModify=Il n'y a pas de flux workflow modifiable pour les modules que vous avez activés. descWORKFLOW_PROPAL_AUTOCREATE_ORDER=Créer une commande client automatiquement à la signature d'une proposition commerciale +descWORKFLOW_PROPAL_AUTOCREATE_INVOICE=Créer une facture client automatiquement à la signature d'une proposition commerciale +descWORKFLOW_CONTRACT_AUTOCREATE_INVOICE=Créer une facture client automatiquement à la validation d'un contrat +descWORKFLOW_ORDER_AUTOCREATE_INVOICE=Créer une facture client automatiquement à la cloture d'une commande client \ No newline at end of file