Can clone a commercial proposal

This commit is contained in:
Laurent Destailleur 2009-01-14 15:53:52 +00:00
parent 6e15ff8cf3
commit 192cb68c28
8 changed files with 188 additions and 102 deletions

View File

@ -11,7 +11,8 @@ For users:
- New: Add graph report on number of entities in product statistics page. - New: Add graph report on number of entities in product statistics page.
- New: Can delete a supplier order whatever is its status. - New: Can delete a supplier order whatever is its status.
- New: No limit on free text on PDF generated documents. - New: No limit on free text on PDF generated documents.
- New: can force login value when creating a user from a member. - New: Can force login value when creating a user from a member.
- New: Can clone a commercial proposal.
- Fix: Failed to go on the future view of bank transaction if there is no - Fix: Failed to go on the future view of bank transaction if there is no
future bank transaction already wrote. future bank transaction already wrote.
- Fix: Bad ref in supplier list. - Fix: Bad ref in supplier list.

View File

@ -77,6 +77,31 @@ $NBLINES=4;
/* Actions */ /* Actions */
/******************************************************************************/ /******************************************************************************/
// Action clone object
if ($_POST["action"] == 'confirm_clone' && $_POST['confirm'] == 'yes')
{
if (1==0 && empty($_REQUEST["clone_content"]) && empty($_REQUEST["clone_receivers"]))
{
$mesg='<div class="error">'.$langs->trans("NoCloneOptionsSpecified").'</div>';
}
else
{
$object=new Propal($db);
$result=$object->createFromClone($_REQUEST['propalid']);
if ($result > 0)
{
header("Location: ".$_SERVER['PHP_SELF'].'?propalid='.$result);
exit;
}
else
{
$mesg=$object->error;
$_GET['action']='';
$_GET['propalid']=$_REQUEST['propalid'];
}
}
}
// Suppression de la propale // Suppression de la propale
if ($_REQUEST['action'] == 'confirm_delete' && $_REQUEST['confirm'] == 'yes') if ($_REQUEST['action'] == 'confirm_delete' && $_REQUEST['confirm'] == 'yes')
{ {
@ -850,19 +875,20 @@ llxHeader('',$langs->trans('Proposal'),'Proposition');
$html = new Form($db); $html = new Form($db);
$formfile = new FormFile($db); $formfile = new FormFile($db);
if ($_GET['propalid'] > 0) $now=gmmktime();
$id = $_GET['propalid'];
$ref= $_GET['ref'];
if ($id > 0 || ! empty($ref))
{ {
/* /*
* Affichage fiche propal en mode visu * Show object in view mode
*
*/ */
$now=gmmktime();
if ($mesg) print $mesg."<br>"; if ($mesg) print $mesg."<br>";
$propal = new Propal($db); $propal = new Propal($db);
$propal->fetch($_GET['propalid']); $propal->fetch($_GET['propalid'],$_GET['ref']);
$societe = new Societe($db); $societe = new Societe($db);
$societe->fetch($propal->socid); $societe->fetch($propal->socid);
@ -870,6 +896,19 @@ if ($_GET['propalid'] > 0)
$head = propal_prepare_head($propal); $head = propal_prepare_head($propal);
dolibarr_fiche_head($head, 'comm', $langs->trans('Proposal')); dolibarr_fiche_head($head, 'comm', $langs->trans('Proposal'));
// Clone confirmation
if ($_GET["action"] == 'clone')
{
// Create an array for form
$formquestion=array(
//'text' => $langs->trans("ConfirmClone"),
//array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1)
);
// Paiement incomplet. On demande si motif = escompte ou autre
$html->form_confirm($_SERVER["PHP_SELF"].'?propalid='.$propal->id,$langs->trans('ClonePropal'),$langs->trans('ConfirmClonePropal',$propal->ref),'confirm_clone',$formquestion,'yes');
print '<br>';
}
/* /*
* Confirmation de la suppression de la propale * Confirmation de la suppression de la propale
*/ */
@ -906,7 +945,9 @@ if ($_GET['propalid'] > 0)
print '<table class="border" width="100%">'; print '<table class="border" width="100%">';
// Ref // Ref
print '<tr><td>'.$langs->trans('Ref').'</td><td colspan="5">'.$propal->ref.'</td></tr>'; print '<tr><td>'.$langs->trans('Ref').'</td><td colspan="5">';
print $html->showrefnav($propal,'ref','',1,'ref','ref','');
print '</td></tr>';
// Ref client // Ref client
print '<tr><td>'; print '<tr><td>';
@ -1038,7 +1079,7 @@ if ($_GET['propalid'] > 0)
} }
else else
{ {
print dolibarr_print_date($propal->date_livraison,'%a %d %B %Y'); print dolibarr_print_date($propal->date_livraison,'daytext');
} }
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
@ -1727,6 +1768,12 @@ if ($_GET['propalid'] > 0)
print '>'.$langs->trans('Close').'</a>'; print '>'.$langs->trans('Close').'</a>';
} }
// Clone
if ($propal->type == 0 && $user->rights->propale->creer)
{
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?propalid='.$propal->id.'&amp;action=clone&amp;object=propal">'.$langs->trans("ToClone").'</a>';
}
// Delete // Delete
if ($propal->statut == 0 && $user->rights->propale->supprimer) if ($propal->statut == 0 && $user->rights->propale->supprimer)
{ {

View File

@ -1880,17 +1880,16 @@ if ($_GET['action'] == 'create')
} }
else else
{ {
/*
* Show object in view mode
*/
$now=gmmktime(); $now=gmmktime();
$id = $_GET['facid']; $id = $_GET['facid'];
$ref= $_GET['ref']; $ref= $_GET['ref'];
if ($id > 0 || ! empty($ref)) if ($id > 0 || ! empty($ref))
{ {
/* *************************************************************************** */
/* */
/* Fiche en mode visu / edition */
/* */
/* *************************************************************************** */
if ($mesg) print $mesg.'<br>'; if ($mesg) print $mesg.'<br>';
$facstatic = new Facture($db); $facstatic = new Facture($db);
@ -3081,7 +3080,7 @@ else
} }
} }
// Supprimer // Delete
if ($fac->is_erasable() && $user->rights->facture->supprimer && $_GET['action'] != 'delete') if ($fac->is_erasable() && $user->rights->facture->supprimer && $_GET['action'] != 'delete')
{ {
if ($facidnext) if ($facidnext)

View File

@ -242,7 +242,7 @@ RemoveDiscount=Remove discount
WatermarkOnDraftBill=Watermark on draft invoices (nothing if empty) WatermarkOnDraftBill=Watermark on draft invoices (nothing if empty)
CloneInvoice=Clone invoice CloneInvoice=Clone invoice
CloneMainAttributes=Clone object with its main attributes CloneMainAttributes=Clone object with its main attributes
ConfirmCloneInvoice=Are you sure you want to clone this invoice ? ConfirmCloneInvoice=Are you sure you want to clone this invoice <b>%s</b> ?
DisabledBecauseReplacedInvoice=Action disabled because invoice has been replaced DisabledBecauseReplacedInvoice=Action disabled because invoice has been replaced
# PaymentConditions # PaymentConditions

View File

@ -73,6 +73,8 @@ CopyPropalFrom=Create commercial proposal by copying existing proposal
CreateEmptyPropal=Create empty commercial proposals vierge or from list of products/services CreateEmptyPropal=Create empty commercial proposals vierge or from list of products/services
DefaultProposalDurationValidity=Default commercial proposal validity duration (in days) DefaultProposalDurationValidity=Default commercial proposal validity duration (in days)
UseCustomerContactAsPropalRecipientIfExist=Use customer contact address if defined instead of third party address as proposal recipient address UseCustomerContactAsPropalRecipientIfExist=Use customer contact address if defined instead of third party address as proposal recipient address
ClonePropal=Clone commercial proposal
ConfirmClonePropal=Are you sure you want to clone this commercial proposal <b>%s</b> ?
# Document models # Document models
DocModelAzurDescription=A complete proposal model (logo...) DocModelAzurDescription=A complete proposal model (logo...)

View File

@ -242,7 +242,7 @@ WatermarkOnDraftBill=Filigrane sur les brouillons de factures (aucun si vide)
UnpayedNotChecked=Aucune facture impayées n'a été sélectionnée UnpayedNotChecked=Aucune facture impayées n'a été sélectionnée
CloneInvoice=Cloner facture CloneInvoice=Cloner facture
CloneMainAttributes=Cloner l'objet avec ces attributs principaux CloneMainAttributes=Cloner l'objet avec ces attributs principaux
ConfirmCloneInvoice=Etes-vous sur de vouloir cloner cette facture ? ConfirmCloneInvoice=Etes-vous sur de vouloir cloner cette facture <b>%s</b> ?
DisabledBecauseReplacedInvoice=Action désactivée car facture remplacée DisabledBecauseReplacedInvoice=Action désactivée car facture remplacée
# PaymentConditions # PaymentConditions

View File

@ -73,6 +73,8 @@ CopyPropalFrom=Cr
CreateEmptyPropal=Créer proposition/devis vierge ou depuis liste de produits prédéfinis CreateEmptyPropal=Créer proposition/devis vierge ou depuis liste de produits prédéfinis
DefaultProposalDurationValidity=Délai de validité par défaut (en jours) DefaultProposalDurationValidity=Délai de validité par défaut (en jours)
UseCustomerContactAsPropalRecipientIfExist=Utiliser adresse contact suivi client si défini plutot que adresse tiers comme destinataire des propositions UseCustomerContactAsPropalRecipientIfExist=Utiliser adresse contact suivi client si défini plutot que adresse tiers comme destinataire des propositions
ClonePropal=Cloner proposition commerciale
ConfirmClonePropal=Etes-vous sur de vouloir cloner cette proposition commerciale <b>%s</b> ?
# Documents models # Documents models
DocModelAzurDescription=Modèle de propositions commerciales complet (logo...) DocModelAzurDescription=Modèle de propositions commerciales complet (logo...)

View File

@ -514,8 +514,6 @@ class Propal extends CommonObject
// Clean parameters // Clean parameters
$this->fin_validite = $this->datep + ($this->duree_validite * 24 * 3600); $this->fin_validite = $this->datep + ($this->duree_validite * 24 * 3600);
dolibarr_syslog("Propal::create ref=".$this->ref);
$this->db->begin(); $this->db->begin();
$this->fetch_client(); $this->fetch_client();
@ -539,6 +537,7 @@ class Propal extends CommonObject
if ($conf->global->PROPALE_ADD_SHIPPING_DATE) $sql.= ", ".($this->date_livraison?$this->db->idate($this->date_livraison):'null'); if ($conf->global->PROPALE_ADD_SHIPPING_DATE) $sql.= ", ".($this->date_livraison?$this->db->idate($this->date_livraison):'null');
$sql.= ")"; $sql.= ")";
dolibarr_syslog("Propal::create sql=".$sql, LOG_DEBUG);
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if ($resql) if ($resql)
{ {
@ -632,52 +631,101 @@ class Propal extends CommonObject
*/ */
function create_from($user) function create_from($user)
{ {
global $conf,$lang; $this->products=$this->lignes;
$this->products=array();
$i=0;
foreach($this->lignes as $ligne)
{
$this->products[$i]->desc=$ligne->desc;
$this->products[$i]->subprice=$ligne->subprice;
$this->products[$i]->qty=$ligne->qty;
$this->products[$i]->tva_tx=$ligne->tva_tx;
$this->products[$i]->fk_product=$ligne->fk_product;
$this->products[$i]->remise_percent=$ligne->remise_percent;
$i++;
}
return $this->create(); return $this->create();
} }
/** /**
* \brief Recupere de la base les caracteristiques d'une propale * \brief Load an object from its id and create a new one in database
* \param rowid id de la propal a recuperer * \param fromid Id of object to clone
* \return int <0 si ko, 0 si non trouve, >0 si ok * \param invertdetail Reverse sign of amounts for lines
* \return int New id of clone
*/ */
function fetch($rowid) function createFromClone($fromid,$invertdetail=0)
{
global $user,$langs;
$error=0;
$object=new Propal($this->db);
$this->db->begin();
// Load source object
$object->fetch($fromid);
$object->id=0;
$object->statut=0;
// Clear fields
$object->user_author = $user->id;
$object->user_valid = '';
$object->date = '';
$object->datep = gmmktime();
$object->fin_validite = '';
$object->ref_client = '';
$object->products = $object->lignes; // Tant que products encore utilisé
// Create clone
$result=$object->create($user);
// Other options
if ($result < 0)
{
$this->error=$object->error;
$error++;
}
if (! $error)
{
}
// End
if (! $error)
{
$this->db->commit();
return $object->id;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* \brief Load a proposal from database and its ligne array
* \param rowid id of object to load
* \param ref Ref of proposal
* \return int >0 if OK, <0 if KO
*/
function fetch($rowid,$ref='')
{ {
$sql = "SELECT p.rowid,ref,remise,remise_percent,remise_absolue,fk_soc"; $sql = "SELECT p.rowid,ref,remise,remise_percent,remise_absolue,fk_soc";
$sql.= ", total, tva, total_ht"; $sql.= ", total, tva, total_ht";
$sql.= ", ".$this->db->pdate("datep")." as dp"; $sql.= ", datep as dp";
$sql.= ", ".$this->db->pdate("fin_validite")." as dfv"; $sql.= ", fin_validite as dfv";
$sql.= ", ".$this->db->pdate("date_livraison")." as date_livraison"; $sql.= ", date_livraison as date_livraison";
$sql.= ", model_pdf, ref_client"; $sql.= ", model_pdf, ref_client";
$sql.= ", note, note_public"; $sql.= ", note, note_public";
$sql.= ", fk_projet, fk_statut, fk_user_author"; $sql.= ", fk_projet, fk_statut, fk_user_author";
$sql.= ", fk_adresse_livraison"; $sql.= ", fk_adresse_livraison";
$sql.= ", p.fk_cond_reglement, cr.code as cond_reglement_code"; $sql.= ", p.fk_cond_reglement";
$sql.= ", p.fk_mode_reglement, cp.code as mode_reglement_code"; $sql.= ", p.fk_mode_reglement";
$sql.= ", c.label as statut_label"; $sql.= ", c.label as statut_label";
$sql.= ", cr.code as cond_reglement_code, cr.libelle, cr.libelle_facture";
$sql.= ", cp.code as mode_reglement_code";
$sql.= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."propal as p"; $sql.= " FROM ".MAIN_DB_PREFIX."c_propalst as c, ".MAIN_DB_PREFIX."propal as p";
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as cp ON p.fk_mode_reglement = cp.id';
$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'cond_reglement as cr ON p.fk_cond_reglement = cr.rowid'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'cond_reglement as cr ON p.fk_cond_reglement = cr.rowid';
$sql.= " WHERE p.fk_statut = c.id"; $sql.= " WHERE p.fk_statut = c.id";
$sql.= " AND p.rowid='".$rowid."'"; if ($ref) $sql.= " AND p.ref='".$ref."'";
else $sql.= " AND p.rowid=".$rowid;
dolibarr_syslog("Propal::fecth rowid=".$rowid);
dolibarr_syslog("Propal::fecth sql=".$sql, LOG_DEBUG);
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if ($resql) if ($resql)
{ {
@ -685,11 +733,8 @@ class Propal extends CommonObject
{ {
$obj = $this->db->fetch_object($resql); $obj = $this->db->fetch_object($resql);
$this->id = $rowid; $this->id = $obj->rowid;
$this->date = $obj->dp;
$this->datep = $obj->dp;
$this->fin_validite = $obj->dfv;
$this->ref = $obj->ref; $this->ref = $obj->ref;
$this->ref_client = $obj->ref_client; $this->ref_client = $obj->ref_client;
$this->remise = $obj->remise; $this->remise = $obj->remise;
@ -706,32 +751,22 @@ class Propal extends CommonObject
$this->note_public = $obj->note_public; $this->note_public = $obj->note_public;
$this->statut = $obj->fk_statut; $this->statut = $obj->fk_statut;
$this->statut_libelle = $obj->statut_label; $this->statut_libelle = $obj->statut_label;
$this->date = $this->db->jdate($obj->dp);
$this->datep = $this->db->jdate($obj->dp);
$this->fin_validite = $this->db->jdate($obj->dfv);
$this->date_livraison = $this->db->jdate($obj->date_livraison);
$this->adresse_livraison_id = $obj->fk_adresse_livraison;
$this->mode_reglement_id = $obj->fk_mode_reglement; $this->mode_reglement_id = $obj->fk_mode_reglement;
$this->mode_reglement_code = $obj->mode_reglement_code; $this->mode_reglement_code = $obj->mode_reglement_code;
$this->cond_reglement_id = $obj->fk_cond_reglement; $this->cond_reglement_id = $obj->fk_cond_reglement;
$this->cond_reglement_code = $obj->cond_reglement_code; $this->cond_reglement_code = $obj->cond_reglement_code;
$this->date_livraison = $obj->date_livraison; $this->cond_reglement = $objc->libelle;
$this->adresse_livraison_id = $obj->fk_adresse_livraison; $this->cond_reglement_document = $objc->libelle_facture;
$this->user_author_id = $obj->fk_user_author; $this->user_author_id = $obj->fk_user_author;
if ($this->cond_reglement_id)
{
$sql = "SELECT rowid, libelle, code, libelle_facture";
$sql.= " FROM ".MAIN_DB_PREFIX."cond_reglement";
$sql.= " WHERE rowid = ".$this->cond_reglement_id;
$resqlcond = $this->db->query($sql);
if ($resqlcond)
{
$objc = $this->db->fetch_object($resqlcond);
$this->cond_reglement = $objc->libelle;
$this->cond_reglement_document = $objc->libelle_facture;
$this->cond_reglement_code = $objc->code;
}
}
if ($obj->fk_statut == 0) if ($obj->fk_statut == 0)
{ {
$this->brouillon = 1; $this->brouillon = 1;
@ -741,7 +776,7 @@ class Propal extends CommonObject
$this->db->free($resql); $this->db->free($resql);
/* /*
* Lignes propales li<EFBFBD>es <EFBFBD> un produit ou non * Lignes propales liees a un produit ou non
*/ */
$sql = "SELECT d.description, d.price, d.tva_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,"; $sql = "SELECT d.description, d.price, d.tva_tx, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,";
$sql.= " d.info_bits, d.total_ht, d.total_tva, d.total_ttc, d.marge_tx, d.marque_tx, d.special_code, d.rang,"; $sql.= " d.info_bits, d.total_ht, d.total_tva, d.total_ttc, d.marge_tx, d.marque_tx, d.special_code, d.rang,";
@ -796,7 +831,7 @@ class Propal extends CommonObject
else else
{ {
$this->error=$this->db->error(); $this->error=$this->db->error();
dolibarr_syslog("Propal::Fetch Error $this->error, sql=$sql"); dolibarr_syslog("Propal::Fetch Error ".$this->error, LOG_ERROR);
return -1; return -1;
} }
@ -809,7 +844,7 @@ class Propal extends CommonObject
else else
{ {
$this->error=$this->db->error(); $this->error=$this->db->error();
dolibarr_syslog("Propal::Fetch Error sql=$sql ".$this->error); dolibarr_syslog("Propal::Fetch Error ".$this->error, LOG_ERROR);
return -1; return -1;
} }
} }