From ba3b6b6aa5d372d41869eb0559d3e8bbfb64d561 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 8 Jul 2017 17:57:35 +0200 Subject: [PATCH] Better support of vat with code in expense report --- htdocs/commande/class/commande.class.php | 8 +- htdocs/core/lib/functions.lib.php | 2 +- htdocs/expensereport/card.php | 442 +++++++++--------- .../class/expensereport.class.php | 107 +++-- 4 files changed, 308 insertions(+), 251 deletions(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 40e258a8e82..c326efa7e49 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1360,10 +1360,10 @@ class Commande extends CommonOrder $this->line->vat_src_code=$vat_src_code; $this->line->tva_tx=$txtva; - $this->line->localtax1_tx=$txlocaltax1; - $this->line->localtax2_tx=$txlocaltax2; - $this->line->localtax1_type = $localtaxes_type[0]; - $this->line->localtax2_type = $localtaxes_type[2]; + $this->line->localtax1_tx=$localtaxes_type[1]; + $this->line->localtax2_tx=$localtaxes_type[3]; + $this->line->localtax1_type=$localtaxes_type[0]; + $this->line->localtax2_type=$localtaxes_type[2]; $this->line->fk_product=$fk_product; $this->line->product_type=$product_type; $this->line->fk_remise_except=$fk_remise_except; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5c3d78aa0ee..a12e4c18ba4 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3892,7 +3892,7 @@ function getTaxesFromId($vatrowid) * @param Societe $buyer Company object * @param Societe $seller Company object * @param int $firstparamisid 1 if first param is id into table (use this if you can) - * @return array array(localtax_type1(1-6/0 if not found), rate localtax1, localtax_type1, rate localtax2, accountancycodecust, accountancycodesupp) + * @return array array(localtax_type1(1-6/0 if not found), rate localtax1, localtax_type2, rate localtax2, accountancycodecust, accountancycodesupp) */ function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0) { diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 596636c74b0..951659a2b59 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -122,7 +122,7 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e if (empty($reshook)) { - if ($cancel) + if ($cancel) { $action=''; $fk_projet=''; @@ -155,7 +155,7 @@ if (empty($reshook)) { // Because createFromClone modifies the object, we must clone it so that we can restore it later $orig = clone $object; - + $result=$object->createFromClone($socid); if ($result > 0) { @@ -171,7 +171,7 @@ if (empty($reshook)) } } } - + if ($action == 'confirm_delete' && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->supprimer) { $object = new ExpenseReport($db); @@ -187,20 +187,20 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == 'add' && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); - + $object->date_debut = $date_start; $object->date_fin = $date_end; - + $object->fk_user_author = GETPOST('fk_user_author','int'); if (! ($object->fk_user_author > 0)) $object->fk_user_author = $user->id; - + $fuser=new User($db); $fuser->fetch($object->fk_user_author); - + $object->fk_statut = 1; $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); $object->fk_user_validator = GETPOST('fk_user_validator','int'); @@ -212,20 +212,20 @@ if (empty($reshook)) $ret = $extrafields->setOptionalsFromPost($extralabels, $object); if ($ret < 0) $error++; } - + if ($object->periode_existe($fuser,$object->date_debut,$object->date_fin)) { $error++; setEventMessages($langs->trans("ErrorDoubleDeclaration"), null, 'errors'); $action='create'; } - + if (! $error) { $db->begin(); - + $id = $object->create($user); - + if ($id > 0) { $db->commit(); @@ -240,25 +240,25 @@ if (empty($reshook)) } } } - + if ($action == 'update' && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - + $object->date_debut = $date_start; $object->date_fin = $date_end; - + if($object->fk_statut < 3) { $object->fk_user_validator = GETPOST('fk_user_validator','int'); } - + $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); $object->note_public = GETPOST('note_public'); $object->note_private = GETPOST('note_private'); $object->fk_user_modif = $user->id; - + $result = $object->update($user); if ($result > 0) { @@ -270,14 +270,14 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == 'update_extras') { // Fill array 'array_options' with data from update form $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute')); if ($ret < 0) $error++; - + if (! $error) { // Actions on extra fields (by external module or standard code) @@ -293,17 +293,17 @@ if (empty($reshook)) } else if ($reshook < 0) $error++; } - + if ($error) $action = 'edit_extras'; } - + if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); $result = $object->setValidate($user); - + if ($result > 0) { // Define output language @@ -319,51 +319,51 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0 && $object->fk_user_validator > 0) { $langs->load("mails"); - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_validator); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_author); $emailFrom = $expediteur->email; - + if ($emailTo && $emailFrom) { $filename=array(); $filedir=array(); $mimetype=array(); - + // SUBJECT $subject = $langs->trans("ExpenseReportWaitingForApproval"); - + // CONTENT $link = $urlwithroot.'/expensereport/card.php?id='.$object->id; $message = $langs->trans("ExpenseReportWaitingForApprovalMessage", $expediteur->getFullName($langs), get_date_range($object->date_debut,$object->date_fin,'',$langs), $link); - + // Rebuild pdf /* $object->setDocModel($user,""); $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); - + if($resultPDF): // ATTACHMENT array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref).".pdf"); array_push($mimetype,"application/pdf"); */ - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); - + if ($mailfile) { // SEND @@ -408,13 +408,13 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == "confirm_save_from_refuse" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); $result = $object->set_save_from_refuse($user); - + if ($result > 0) { // Define output language @@ -430,35 +430,35 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) // TODO Translate this so we can remove condition { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_validator); $emailTo = $destinataire->email; - + if ($emailTo) { // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_author); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais à re-approuver"; - + // CONTENT $dateRefusEx = explode(" ",$object->date_refuse); - + $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Le {$dateRefusEx[0]} à {$dateRefusEx[1]} vous avez refusé d'approuver la note de frais \"{$object->ref}\". Vous aviez émis le motif suivant : {$object->detail_refuse}\n\n"; $message.= "L'auteur vient de modifier la note de frais, veuillez trouver la nouvelle version en pièce jointe.\n"; @@ -466,11 +466,11 @@ if (empty($reshook)) $message.= "- Période : du {$object->date_debut} au {$object->date_fin}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // Génération du pdf avant attachement $object->setDocModel($user,""); $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); - + if($resultPDF) { // ATTACHMENT @@ -478,10 +478,10 @@ if (empty($reshook)) array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); array_push($mimetype,"application/pdf"); - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); - + if (! $mailfile->error) { // SEND @@ -512,15 +512,15 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + // Approve if ($action == "confirm_approve" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->approve) { $object = new ExpenseReport($db); $object->fetch($id); - + $result = $object->setApproved($user); - + if ($result > 0) { // Define output language @@ -536,44 +536,44 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) // TODO Translate this so we can remove condition { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // CC $emailCC = $conf->global->NDF_CC_EMAILS; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_valid); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais validée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être approuvé!\n"; $message.= "- Approbateur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // Génération du pdf avant attachement $object->setDocModel($user,""); $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); - + if($resultPDF): // ATTACHMENT $filename=array(); $filedir=array(); $mimetype=array(); @@ -586,12 +586,12 @@ if (empty($reshook)) ".pdf" ); array_push($mimetype,"application/pdf"); - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename,$emailCC); - + if(!$mailfile->error): - + // SEND $result=$mailfile->sendfile(); if ($result): @@ -601,7 +601,7 @@ if (empty($reshook)) else: setEventMessages($langs->trans("ErrorFailedToSendMail",$emailFrom,$emailTo), null, 'errors'); endif; - + else: setEventMessages($langs->trans("ErrorFailedToSendMail",$emailFrom,$emailTo), null, 'errors'); endif; @@ -617,14 +617,14 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->approve) { $object = new ExpenseReport($db); $object->fetch($id); - + $result = $object->setDeny($user,GETPOST('detail_refuse')); - + if ($result > 0) { // Define output language @@ -640,30 +640,30 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) // TODO Translate this so we can remove condition { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_refuse); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais refusée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être refusée.\n"; @@ -671,10 +671,10 @@ if (empty($reshook)) $message.= "- Motif de refus : {$_POST['detail_refuse']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); - + if(!$mailfile->error) { // SEND @@ -698,17 +698,17 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + //var_dump($user->id == $object->fk_user_validator);exit; if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && GETPOST('detail_cancel') && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - + if ($user->id == $object->fk_user_valid || $user->id == $object->fk_user_author) { $result = $object->set_cancel($user,GETPOST('detail_cancel')); - + if ($result > 0) { // Define output language @@ -724,30 +724,30 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) // TODO Translate this so we can remove condition { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_cancel); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais annulée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être annulée.\n"; @@ -755,10 +755,10 @@ if (empty($reshook)) $message.= "- Motif d'annulation : {$_POST['detail_cancel']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); - + if(!$mailfile->error) { // SEND @@ -791,7 +791,7 @@ if (empty($reshook)) setEventMessages($langs->transnoentitiesnoconv("OnlyOwnerCanCancel"), '', 'errors'); // Should not happened } } - + if ($action == "confirm_brouillonner" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); @@ -799,7 +799,7 @@ if (empty($reshook)) if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { $result = $object->setStatut(0); - + if ($result > 0) { // Define output language @@ -815,11 +815,11 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); @@ -835,14 +835,14 @@ if (empty($reshook)) setEventMessages("NOT_AUTHOR", '', 'errors'); } } - + if ($action == 'set_paid' && $id > 0 && $user->rights->expensereport->to_paid) { $object = new ExpenseReport($db); $object->fetch($id); - + $result = $object->set_paid($id, $user); - + if ($result > 0) { // Define output language @@ -858,50 +858,50 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) // TODO Translate this so we can remove condition { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($user->id); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "'ERP - Note de frais payée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être payée.\n"; $message.= "- Payeur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // Generate pdf before attachment $object->setDocModel($user,""); $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); - + if(!$mailfile->error): - + // SEND $result=$mailfile->sendfile(); if ($result): - + // Retour if($result): Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); @@ -909,11 +909,11 @@ if (empty($reshook)) else: dol_print_error($db); endif; - + else: dol_print_error($db,$acct->error); endif; - + else: $mesg="Impossible d'envoyer l'email."; setEventMessages($mesg, null, 'errors'); @@ -926,49 +926,50 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == "addline" && $user->rights->expensereport->creer) { $error = 0; - + $db->begin(); - + $object_ligne = new ExpenseReportLine($db); - - $vatrate = GETPOST('vatrate'); + + $vatrate = GETPOST('vatrate','alpha'); // May be 8.5* (8.5NPROM) + $object_ligne->comments = GETPOST('comments'); $qty = GETPOST('qty','int'); if (empty($qty)) $qty=1; $object_ligne->qty = $qty; - + $up=price2num(GETPOST('value_unit'),'MU'); $object_ligne->value_unit = $up; - + $object_ligne->date = $date; - + $object_ligne->fk_c_type_fees = GETPOST('fk_c_type_fees'); - + // if VAT is not used in Dolibarr, set VAT rate to 0 because VAT rate is necessary. if (empty($vatrate)) $vatrate = "0.000"; $object_ligne->vatrate = price2num($vatrate); - + $object_ligne->fk_projet = $fk_projet; - - + + if (! GETPOST('fk_c_type_fees') > 0) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors'); $action=''; } - + if ($vatrate < 0 || $vatrate == '') { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("VAT")), null, 'errors'); $action=''; } - + /* Projects are never required. To force them, check module forceproject if ($conf->projet->enabled) { @@ -978,7 +979,7 @@ if (empty($reshook)) setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Project")), null, 'errors'); } }*/ - + // Si aucune date n'est rentrée if (empty($object_ligne->date) || $object_ligne->date=="--") { @@ -991,21 +992,42 @@ if (empty($reshook)) $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PriceUTTC")), null, 'errors'); } - + // S'il y'a eu au moins une erreur if (! $error) { $object_ligne->fk_expensereport = $_POST['fk_expensereport']; - + $type = 0; // TODO What if service ? - $seller = ''; // seller is unknown - $tmp = calcul_price_total($qty, $up, 0, $vatrate, 0, 0, 0, 'TTC', 0, $type, $seller); - + + // We don't know seller and buyer for expense reports + $seller = $mysoc; + $buyer = new Societe($db); + + $localtaxes_type=getLocalTaxesFromRate($vatrate,0,$buyer,$seller); + + // Clean vat code + $vat_src_code=''; + + if (preg_match('/\((.*)\)/', $vatrate, $reg)) + { + $vat_src_code = $reg[1]; + $vatrate = preg_replace('/\s*\(.*\)/', '', $vatrate); // Remove code into vatrate. + } + $vatrate = preg_replace('/\*/','',$vatrate); + + $tmp = calcul_price_total($qty, $up, 0, $vatrate, 0, 0, 0, 'TTC', 0, $type, $seller, $localtaxes_type); + + $object_ligne->vat_src_code = $vat_src_code; $object_ligne->vatrate = price2num($vatrate); $object_ligne->total_ttc = $tmp[2]; $object_ligne->total_ht = $tmp[0]; $object_ligne->total_tva = $tmp[1]; - + $object_ligne->localtax1_tx = $localtaxes_type[1]; + $object_ligne->localtax2_tx = $localtaxes_type[3]; + $object_ligne->localtax1_type = $localtaxes_type[0]; + $object_ligne->localtax2_type = $localtaxes_type[2]; + $result = $object_ligne->insert(); if ($result > 0) { @@ -1019,20 +1041,20 @@ if (empty($reshook)) $db->rollback(); } } - + $action=''; } - + if ($action == 'confirm_delete_line' && GETPOST("confirm") == "yes" && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - + $object_ligne = new ExpenseReportLine($db); $object_ligne->fetch(GETPOST("rowid")); $total_ht = $object_ligne->total_ht; $total_tva = $object_ligne->total_tva; - + $result=$object->deleteline(GETPOST("rowid"), $user); if ($result >= 0) { @@ -1051,11 +1073,11 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + $object->update_totaux_del($object_ligne->total_ht,$object_ligne->total_tva); header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); exit; @@ -1065,12 +1087,12 @@ if (empty($reshook)) setEventMessages($object->error, $object->errors, 'errors'); } } - + if ($action == "updateligne" && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - + $rowid = $_POST['rowid']; $type_fees_id = GETPOST('fk_c_type_fees'); $projet_id = $fk_projet; @@ -1082,7 +1104,7 @@ if (empty($reshook)) // if VAT is not used in Dolibarr, set VAT rate to 0 because VAT rate is necessary. if (empty($vatrate)) $vatrate = "0.000"; $vatrate = price2num($vatrate); - + if (! GETPOST('fk_c_type_fees') > 0) { $error++; @@ -1095,7 +1117,7 @@ if (empty($reshook)) setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Vat")), null, 'errors'); $action=''; } - + if (! $error) { // TODO Use update method of ExpenseReportLine @@ -1117,13 +1139,13 @@ if (empty($reshook)) } $model=$object->modelpdf; $ret = $object->fetch($id); // Reload to get new records - + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } } - + $result = $object->recalculer($id); - + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); exit; } @@ -1133,8 +1155,8 @@ if (empty($reshook)) } } } - - + + /* * Generate or regenerate the PDF document */ @@ -1142,12 +1164,12 @@ if (empty($reshook)) { $depl = new ExpenseReport($db, 0, $_GET['id']); $depl->fetch($id); - + if ($_REQUEST['model']) { $depl->setDocModel($user, $_REQUEST['model']); } - + $outputlangs = $langs; if (! empty($_REQUEST['lang_id'])) { @@ -1161,7 +1183,7 @@ if (empty($reshook)) $action=''; } } - + // Remove file in doc form else if ($action == 'remove_file') { @@ -1169,9 +1191,9 @@ if (empty($reshook)) if ($object->fetch($id)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - + $object->fetch_thirdparty(); - + $langs->load("other"); $upload_dir = $conf->expensereport->dir_output; $file = $upload_dir . '/' . GETPOST('file'); @@ -1210,7 +1232,7 @@ if ($action == 'create') print ''; print ''; - + // Date start print ''; print ''; @@ -1218,7 +1240,7 @@ if ($action == 'create') $form->select_date($date_start?$date_start:-1,'date_debut',0,0,0,'',1,1); print ''; print ''; - + // Date end print ''; print ''; @@ -1226,7 +1248,7 @@ if ($action == 'create') $form->select_date($date_end?$date_end:-1,'date_fin',0,0,0,'',1,1); print ''; print ''; - + print ''; print ''; print ''; print ''; - + print ''; print ''; print ''; print ''; - + // Payment mode if (! empty($conf->global->EXPENSEREPORT_ASK_PAYMENTMODE_ON_CREATION)) { @@ -1294,7 +1316,7 @@ if ($action == 'create') if (empty($reshook) && ! empty($extrafields->attribute_label)) { print $object->showOptionals($extrafields, 'edit'); } - + print ''; print '
'.$langs->trans("DateStart").'
'.$langs->trans("DateEnd").'
'.$langs->trans("User").''; @@ -1238,7 +1260,7 @@ if ($action == 'create') print $s; print '
'.$langs->trans("VALIDATOR").''; @@ -1255,7 +1277,7 @@ if ($action == 'create') } print '
'; @@ -1314,7 +1336,7 @@ else $result = $object->fetch($id, $ref); $res = $object->fetch_optionals($object->id, $extralabels); - + if ($result > 0) { if (! in_array($object->fk_user_author, $user->getAllChildIds(1))) @@ -1365,7 +1387,7 @@ else $userfee->fetch($object->fk_user_author); print $userfee->getNomUrl(-1); print ''; - + // Ref print ''.$langs->trans("Ref").''; print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref', ''); @@ -1460,7 +1482,7 @@ else // Paiement incomplet. On demande si motif = escompte ou autre $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('CloneExpenseReport'), $langs->trans('ConfirmCloneExpenseReport', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } - + if ($action == 'save') { $formconfirm=$form->form_confirm($_SERVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_validate","","",1); @@ -1510,13 +1532,13 @@ else // Print form confirm print $formconfirm; - - + + // Expense report card - + $linkback = ''.$langs->trans("BackToList").''; - - + + $morehtmlref='
'; /* // Ref customer @@ -1557,15 +1579,15 @@ else } }*/ $morehtmlref.='
'; - - + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); - - + + print '
'; print '
'; print '
'; - + print ''; // Author @@ -1580,7 +1602,7 @@ else print $userauthor->getNomUrl(-1); } print ''; - + print ''; print ''; print '"; print ''; - + print ''; print ''; print ''; print ''; - + print ''; print ''; print ''; @@ -1638,7 +1660,7 @@ else $userfee=new User($db); $userfee->fetch($object->fk_user_validator); print $userfee->getNomUrl(-1); - if (empty($userfee->email) || ! isValidEmail($userfee->email)) + if (empty($userfee->email) || ! isValidEmail($userfee->email)) { $langs->load("errors"); print img_warning($langs->trans("ErrorBadEMail", $userfee->email)); @@ -1658,7 +1680,7 @@ else print $userfee->getNomUrl(-1); } print ''; - + print ''; print ''; print ''; @@ -1680,7 +1702,7 @@ else print $userapp->getNomUrl(-1); } print ''; - + print ''; print ''; print ''; @@ -1696,7 +1718,7 @@ else $userfee->fetch($object->fk_user_refuse); print $userfee->getNomUrl(-1); print ''; - + print ''; print ''; print '
'.$langs->trans("Period").''; @@ -1607,12 +1629,12 @@ else if($object->fk_statut==6) $rowspan+=2; print "
'.$langs->trans("AmountVAT").''.price($object->total_tva).'
'.$langs->trans("AmountTTC").''.price($object->total_ttc).'
'.$langs->trans("MOTIF_CANCEL").''.$object->detail_cancel.'
'.$langs->trans("DateApprove").''.dol_print_date($object->date_approve,'dayhour').'
'.$langs->trans("DATE_REFUS").''.dol_print_date($object->date_refuse,'dayhour'); @@ -1725,14 +1747,14 @@ else // Other attributes $cols = 3; include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; - + print '
'; print '
'; print '
'; print '
'; //print '
'; - + // List of payments $sql = "SELECT p.rowid, p.num_payment, p.datep as dp, p.amount,"; $sql.= "c.code as type_code,c.libelle as payment_type"; @@ -1744,7 +1766,7 @@ else $sql.= " AND e.entity = ".$conf->entity; $sql.= " AND p.fk_typepayment = c.id"; $sql.= " ORDER BY dp"; - + $resql = $db->query($sql); if ($resql) { @@ -1758,7 +1780,7 @@ else print ''.$langs->trans("Amount").''; print ' '; print ''; - + $var=True; while ($i < $num) { @@ -1774,14 +1796,14 @@ else $totalpaid += $objp->amount; $i++; } - + if ($object->paid == 0) { print "".$langs->trans("AlreadyPaid")." :".price($totalpaid)."\n"; print "".$langs->trans("AmountExpected")." :".price($object->total_ttc)."\n"; - + $remaintopay = $object->total_ttc - $totalpaid; - + print "".$langs->trans("RemainderToPay")." :"; print ''.price($remaintopay)."\n"; } @@ -1791,14 +1813,14 @@ else else { dol_print_error($db); - } - + } + print '
'; print '
'; print '
'; - + print '

'; - + print '
'; // Fetch Lines of current expense report @@ -1815,17 +1837,17 @@ else $actiontouse='updateligne'; if (($object->fk_statut==0 || $object->fk_statut==99) && $action != 'editline') $actiontouse='addline'; - + print '
'; print ''; print ''; print ''; print ''; - - + + print '
'; print ''; - + $resql = $db->query($sql); if ($resql) { @@ -1885,7 +1907,7 @@ else print ''; print ''; print ''; - + if ($action != 'editline') { print ''; @@ -1906,7 +1928,7 @@ else print ''; } - + print ''; } @@ -1914,7 +1936,7 @@ else { //modif ligne!!!!! print ''; - + print ''; // Select date @@ -1929,7 +1951,7 @@ else $formproject->select_projects(-1, $objp->fk_projet,'fk_projet', 0, 0, 1, 1); print ''; } - + // Select type print ''; // Unit price @@ -1960,7 +1984,7 @@ else print ''; print ''; } - + print ''; print ''; - + print ''; print ''; - + // Select date print ''; } - + // Select type print ''; // Unit price @@ -2048,13 +2072,13 @@ else } print ''; - + print ''; } // Fin si c'est payé/validé print '
'.vatrate($objp->vatrate,true).''.price($objp->value_unit).''.$objp->qty.''.price($objp->total_ht).'
'; select_type_fees_id($objp->type_fees_code,'fk_c_type_fees'); @@ -1942,7 +1964,9 @@ else // VAT print ''; - print $form->load_tva('vatrate', (isset($_POST["vatrate"])?$_POST["vatrate"]:$objp->vatrate), $mysoc, ''); + $seller=$mysoc; + $buyer=new Societe($db); + print $form->load_tva('vatrate', (isset($_POST["vatrate"])?$_POST["vatrate"]:$objp->vatrate), $seller, $buyer, 0, 0, '', false, 1); print ''.$langs->trans('AmountHT').''.$langs->trans('AmountTTC').''; print ''; print ''; @@ -1996,11 +2020,11 @@ else print '
'; $form->select_date($date?$date:-1,'date'); @@ -2013,7 +2037,7 @@ else $formproject->select_projects(-1, $fk_projet, 'fk_projet', 0, 0, 1, 1); print ''; select_type_fees_id($fk_c_type_fees,'fk_c_type_fees',1); @@ -2028,7 +2052,7 @@ else print ''; $defaultvat=-1; if (! empty($conf->global->EXPENSEREPORT_NO_DEFAULT_VAT)) $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS = 'none'; - print $form->load_tva('vatrate', ($vatrate!=''?$vatrate:$defaultvat), $mysoc, '', 0, 0, '', false); + print $form->load_tva('vatrate', ($vatrate!=''?$vatrate:$defaultvat), $mysoc, '', 0, 0, '', false, 1); print '
'; print '
'; - + print '
'; } else @@ -2167,15 +2191,15 @@ if ($action != 'create' && $action != 'edit') } } - + // If status is Appoved // -------------------- - + if ($user->rights->expensereport->approve && $object->fk_statut == 5) { print '
id.'">'.$langs->trans('Deny').'
'; } - + // If bank module is used if ($user->rights->expensereport->to_paid && ! empty($conf->banque->enabled) && $object->fk_statut == 5) { @@ -2189,8 +2213,8 @@ if ($action != 'create' && $action != 'edit') print '
' . $langs->trans('DoPayment') . '
'; } } - - // If bank module is not used + + // If bank module is not used if (($user->rights->expensereport->to_paid || empty($conf->banque->enabled)) && $object->fk_statut == 5) { //if ((round($remaintopay) == 0 || empty($conf->banque->enabled)) && $object->paid == 0) @@ -2199,26 +2223,26 @@ if ($action != 'create' && $action != 'edit') print '
'.$langs->trans("ClassifyPaid")."
"; } } - + if ($user->rights->expensereport->creer && ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) && $object->fk_statut == 5) { // Cancel print '
id.'">'.$langs->trans('Cancel').'
'; } - + // TODO Replace this. It should be SetUnpaid and should go back to status unpaid not canceled. if (($user->rights->expensereport->approve || $user->rights->expensereport->to_paid) && $object->fk_statut == 6) { // Cancel print '
id.'">'.$langs->trans('Cancel').'
'; } - + // Clone if ($user->rights->expensereport->creer) { print '
' . $langs->trans("ToClone") . '
'; } - - /* If draft, validated, cancel, and user can create, he can always delete its card before it is approved */ + + /* If draft, validated, cancel, and user can create, he can always delete its card before it is approved */ if ($user->rights->expensereport->creer && $user->id == $object->fk_user_author && $object->fk_statut <= 4) { // Delete @@ -2269,7 +2293,7 @@ if ($action != 'create' && $action != 'edit' && ($id || $ref)) $object->fetch_thirdparty(); $result = $object->add_object_linked('fichinter', GETPOST('LinkedFichinter')); } - + // Show links to link elements $linktoelements=array(); if (! empty($conf->global->EXPENSES_LINK_TO_INTERVENTION)) diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index e3970ab6b93..2bf9144dce2 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -37,9 +37,9 @@ class ExpenseReport extends CommonObject var $picto = 'trip'; var $lignes=array(); - + public $date_debut; - + public $date_fin; var $fk_user_validator; @@ -65,7 +65,7 @@ class ExpenseReport extends CommonObject // Update var $date_modif; var $fk_user_modif; - + // Refus var $date_refuse; var $detail_refuse; @@ -128,7 +128,7 @@ class ExpenseReport extends CommonObject $fuserid = $this->fk_user_author; // Note fk_user_author is not the 'author' but the guy the expense report is for. if (empty($fuserid)) $fuserid = $user->id; - + $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; @@ -235,35 +235,35 @@ class ExpenseReport extends CommonObject function createFromClone($socid=0) { global $user,$hookmanager; - + $error=0; - + $this->context['createfromclone'] = 'createfromclone'; - + $this->db->begin(); - + // get extrafields so they will be clone foreach($this->lines as $line) //$line->fetch_optionals($line->rowid); - + // Load source object $objFrom = clone $this; - + $this->id=0; $this->ref = ''; $this->statut=0; - + // Clear fields $this->fk_user_author = $user->id; // Note fk_user_author is not the 'author' but the guy the expense report is for. $this->fk_user_valid = ''; $this->date_create = ''; $this->date_creation = ''; $this->date_validation = ''; - + // Create clone $result=$this->create($user); if ($result < 0) $error++; - + if (! $error) { // Hook of thirdparty module @@ -274,15 +274,15 @@ class ExpenseReport extends CommonObject $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) $error++; } - + // Call trigger $result=$this->call_trigger('EXPENSEREPORT_CLONE',$user); if ($result < 0) $error++; // End call triggers } - + unset($this->context['createfromclone']); - + // End if (! $error) { @@ -295,8 +295,8 @@ class ExpenseReport extends CommonObject return -1; } } - - + + /** * update * @@ -399,7 +399,7 @@ class ExpenseReport extends CommonObject $this->fk_user_refuse = $obj->fk_user_refuse; $this->fk_user_cancel = $obj->fk_user_cancel; $this->fk_user_approve = $obj->fk_user_approve; - + $user_author = new User($this->db); if ($this->fk_user_author > 0) $user_author->fetch($this->fk_user_author); @@ -588,7 +588,7 @@ class ExpenseReport extends CommonObject $auser->fetch($obj->fk_user_approve); $this->user_approve = $auser; } - + } $this->db->free($resql); } @@ -1000,7 +1000,7 @@ class ExpenseReport extends CommonObject $sql.= ", ref_number_int = ".$ref_number_int; } $sql.= ' WHERE rowid = '.$this->id; - + $resql=$this->db->query($sql); if ($resql) { @@ -1215,7 +1215,7 @@ class ExpenseReport extends CommonObject $sql = 'SELECT MAX(de.ref_number_int) as max'; $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' de'; - + $result = $this->db->query($sql); if($this->db->num_rows($result) > 0): @@ -1359,7 +1359,7 @@ class ExpenseReport extends CommonObject * @param int $rowid Line to edit * @param int $type_fees_id Type payment * @param int $projet_id Project id - * @param double $vatrate Vat rate + * @param double $vatrate Vat rate. Can be '8.5* (8.5NPROM...)' * @param string $comments Description * @param real $qty Qty * @param double $value_unit Value init @@ -1369,14 +1369,34 @@ class ExpenseReport extends CommonObject */ function updateline($rowid, $type_fees_id, $projet_id, $vatrate, $comments, $qty, $value_unit, $date, $expensereport_id) { - global $user; + global $user, $mysoc; if ($this->fk_statut==0 || $this->fk_statut==99) { $this->db->begin(); + $type = 0; // TODO What if type is service ? + + // We don't know seller and buyer for expense reports + $seller = $mysoc; + $buyer = new Societe($this->db); + + $localtaxes_type=getLocalTaxesFromRate($vatrate,0,$buyer,$seller); + + // Clean vat code + $vat_src_code=''; + + if (preg_match('/\((.*)\)/', $vatrate, $reg)) + { + $vat_src_code = $reg[1]; + $vatrate = preg_replace('/\s*\(.*\)/', '', $vatrate); // Remove code into vatrate. + } + $vatrate = preg_replace('/\*/','',$vatrate); + + $tmp = calcul_price_total($qty, $value_unit, 0, $vatrate, 0, 0, 0, 'TTC', 0, $type, $seller, $localtaxes_type); + // calcul de tous les totaux de la ligne - $total_ttc = price2num($qty*$value_unit, 'MT'); + //$total_ttc = price2num($qty*$value_unit, 'MT'); $tx_tva = $vatrate / 100; $tx_tva = $tx_tva + 1; @@ -1386,6 +1406,9 @@ class ExpenseReport extends CommonObject // fin calculs $ligne = new ExpenseReportLine($this->db); + + $ligne->rowid = $rowid; + $ligne->comments = $comments; $ligne->qty = $qty; $ligne->value_unit = $value_unit; @@ -1395,11 +1418,21 @@ class ExpenseReport extends CommonObject $ligne->fk_c_type_fees = $type_fees_id; $ligne->fk_projet = $projet_id; - $ligne->total_ht = $total_ht; - $ligne->total_tva = $total_tva; - $ligne->total_ttc = $total_ttc; - $ligne->vatrate = price2num($vatrate); - $ligne->rowid = $rowid; + //$ligne->total_ht = $total_ht; + //$ligne->total_tva = $total_tva; + //$ligne->total_ttc = $total_ttc; + //$ligne->vatrate = price2num($vatrate); + + $ligne->vat_src_code = $vat_src_code; + $ligne->vatrate = price2num($vatrate); + $ligne->total_ttc = $tmp[2]; + $ligne->total_ht = $tmp[0]; + $ligne->total_tva = $tmp[1]; + $ligne->localtax1_tx = $localtaxes_type[1]; + $ligne->localtax2_tx = $localtaxes_type[3]; + $ligne->localtax1_type = $localtaxes_type[0]; + $ligne->localtax2_type = $localtaxes_type[2]; + // Select des infos sur le type fees $sql = "SELECT c.code as code_type_fees, c.label as libelle_type_fees"; @@ -1540,7 +1573,7 @@ class ExpenseReport extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user as ugu, ".MAIN_DB_PREFIX."usergroup_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd"; $sql.= " WHERE ugu.fk_usergroup = ur.fk_usergroup AND ur.fk_id = rd.id and rd.module = 'expensereport' AND rd.perms = 'approve'"; // Permission 'Approve'; //print $sql; - + dol_syslog(get_class($this)."::fetch_users_approver_expensereport sql=".$sql); $result = $this->db->query($sql); if($result) @@ -1679,7 +1712,7 @@ class ExpenseReport extends CommonObject $now=dol_now(); $userchildids = $user->getAllChildIds(1); - + $sql = "SELECT ex.rowid, ex.date_valid"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as ex"; if ($option == 'toapprove') $sql.= " WHERE ex.fk_statut = 2"; @@ -1711,7 +1744,7 @@ class ExpenseReport extends CommonObject while ($obj=$this->db->fetch_object($resql)) { $response->nbtodo++; - + if ($option == 'toapprove') { if ($this->db->jdate($obj->date_valid) < ($now - $conf->expensereport->approve->warning_delay)) { @@ -1735,7 +1768,7 @@ class ExpenseReport extends CommonObject return -1; } } - + /** * Return if an expense report is late or not * @@ -1745,11 +1778,11 @@ class ExpenseReport extends CommonObject public function hasDelay($option) { global $conf; - + //Only valid members if ($option == 'toapprove' && $this->status != 2) return false; if ($option == 'topay' && $this->status != 5) return false; - + $now = dol_now(); if ($option == 'toapprove') { @@ -1757,7 +1790,7 @@ class ExpenseReport extends CommonObject } else return ($this->datevalid?$this->datevalid:$this->date_valid) < ($now - $conf->expensereport->payment->warning_delay); - } + } }