Merge branch 'develop' into membership-rework

This commit is contained in:
Laurent Destailleur 2022-07-11 10:56:31 +02:00 committed by GitHub
commit e29df476e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
96 changed files with 771 additions and 129 deletions

View File

@ -220,7 +220,7 @@ llxheader('', $title, $help_url);
// Create mode
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans('NewAccountingAccount'));
print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";

View File

@ -154,7 +154,7 @@ $help_url = "EN:Module_Double_Entry_Accounting";
llxHeader('', $title, $help_url);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewFiscalYear"));
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';

View File

@ -340,7 +340,7 @@ if ($action == 'delete') {
print $formconfirm;
}
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("CreateMvts"));
$object = new BookKeeping($db);

View File

@ -920,7 +920,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// -----------------------------------------
// Create mode
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$object->canvas = $canvas;
$object->state_id = GETPOST('state_id', 'int');

View File

@ -253,7 +253,7 @@ $help_url = "EN:Module_EMail_Collector|FR:Module_Collecteur_de_courrier_électro
llxHeader('', 'EmailCollector', $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewEmailCollector", $langs->transnoentitiesnoconv("EmailCollector")));
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -51,6 +51,9 @@ print load_fiche_titre($langs->trans("PerfDolibarr"), '', 'title_setup');
print '<span class="opacitymedium">'.$langs->trans("YouMayFindPerfAdviceHere", 'https://wiki.dolibarr.org/index.php/FAQ_Increase_Performance').'</span> (<a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("Reload").'</a>)<br>';
print '<br>';
print '<hr>';
// Recupere la version de PHP
$phpversion = version_php();
print "<br><strong>PHP</strong> - ".$langs->trans("Version").": ".$phpversion."<br>\n";

View File

@ -172,7 +172,7 @@ print '<tr class="oddeven nohover"><td style="padding-left: 8px" class="nohover"
print '<table class="centpercent noborderbottom">';
print '<tr>';
print '<td class="tdtop">';
print '<td class="tdtop nopaddingleftimp">';
print '<div id="div_container_exportoptions">';
print '<fieldset id="exportoptions"><legend>'.$langs->trans("ExportMethod").'</legend>';
@ -195,7 +195,7 @@ print '</fieldset>';
print '</div>';
print '</td>';
print '<td class="tdtop">';
print '<td class="tdtop nopaddingrightimp">';
print '<button id="btn" type="button" onclick="hideoptions()">'.$langs->trans("ShowAdvancedOptions").'</button>';

View File

@ -166,7 +166,7 @@ $help_url = '';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Asset")), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -138,7 +138,7 @@ $help_url = '';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("AssetModel")), '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';

View File

@ -268,7 +268,7 @@ $help_url ='EN:Module_BOM';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewBOM"), '', 'bom');
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -144,7 +144,7 @@ $h++;
$hselected = 'card';
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
/*
* Fact bookmark creation mode
*/

View File

@ -923,7 +923,7 @@ $arrayrecurrulefreq = array(
$help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda';
llxHeader('', $langs->trans("Agenda"), $help_url);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$contact = new Contact($db);
$socpeopleassigned = GETPOST("socpeopleassigned", 'array');

View File

@ -704,7 +704,7 @@ llxHeader(
array()
);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
// EMailing in creation mode
print '<form name="new_mailing" action="'.$_SERVER['PHP_SELF'].'" method="POST">'."\n";
print '<input type="hidden" name="token" value="'.newToken().'">';

View File

@ -1537,7 +1537,7 @@ llxHeader('', $title, $help_url);
$now = dol_now();
// Add new proposal
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$currency_code = $conf->currency;
print load_fiche_titre($langs->trans("NewProp"), '', 'propal');

View File

@ -320,6 +320,8 @@ if (empty($reshook)) {
$db->begin();
$nbOrders = is_array($orders) ? count($orders) : 1;
foreach ($orders as $id_order) {
$cmd = new Commande($db);
if ($cmd->fetch($id_order) <= 0) {
@ -455,10 +457,11 @@ if (empty($reshook)) {
$objecttmp->context['createfromclone'];
$rang = $lines[$i]->rang;
$rang = ($nbOrders > 1) ? -1 : $lines[$i]->rang;
//there may already be rows from previous orders
if (!empty($createbills_onebythird))
if (!empty($createbills_onebythird)) {
$rang = $TFactThirdNbLines[$cmd->socid];
}
$result = $objecttmp->addline(
$desc,

View File

@ -336,7 +336,7 @@ $help_url = 'EN:Module_Banks_and_Cash|FR:Module_Banques_et_Caisses|ES:Módulo_Ba
// Creation
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$object = new Account($db);
$title = $langs->trans("NewFinancialAccount");

View File

@ -339,7 +339,7 @@ foreach ($bankcateg->fetchAll() as $bankcategory) {
}
// Create mode
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
// Update fields properties in realtime
if (!empty($conf->use_javascript_ajax)) {
print "\n".'<script type="text/javascript">';

View File

@ -194,7 +194,7 @@ $form = new Form($db);
/*
* Action create
*/
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
//WYSIWYG Editor
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';

View File

@ -2890,7 +2890,7 @@ llxHeader('', $title, $help_url);
// Mode creation
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$facturestatic = new Facture($db);
$extrafields->fetch_name_optionals_label($facturestatic->table_element);

View File

@ -145,7 +145,7 @@ $title = $langs->trans("LT".$object->ltt)." - ".$langs->trans("Card");
$help_url = '';
llxHeader('', $title, $helpurl);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->transcountry($lttype == 2 ? "newLT2Payment" : "newLT1Payment", $mysoc->country_code));
print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" name="formlocaltax" method="post">'."\n";

View File

@ -343,7 +343,7 @@ llxHeader("", $title, $help_url);
// Form to create a social contribution
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewSocialContribution"));
print '<form name="charge" method="post" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -398,7 +398,7 @@ if ($id) {
}
// Form to enter VAT
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("VAT").' - '.$langs->trans("New"));
if (!empty($conf->use_javascript_ajax)) {

View File

@ -626,7 +626,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
if ($user->rights->societe->contact->creer) {
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
/*
* Fiche en mode creation
*/

View File

@ -784,8 +784,10 @@ if (empty($reshook)) {
setEventMessages($object->error, $object->errors, 'errors');
}
} elseif ($action == 'confirm_activate' && $confirm == 'yes' && $user->rights->contrat->creer) {
// Close all lines
$result = $object->activateAll($user);
$date_start = dol_mktime(12, 0, 0, GETPOST('d_startmonth'), GETPOST('d_startday'), GETPOST('d_startyear'));
$date_end = dol_mktime(12, 0, 0, GETPOST('d_endmonth'), GETPOST('d_endday'), GETPOST('d_endyear'));
$comment = GETPOST('comment', 'alpha');
$result = $object->activateAll($user, $date_start, 0, $comment, $date_end);
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
@ -1017,7 +1019,7 @@ if ($result > 0) {
}
// Create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans('AddContract'), '', 'contract');
$soc = new Societe($db);
@ -1260,7 +1262,12 @@ if ($action == 'create' || (empty($action) && empty($id))) {
// Confirmation de la fermeture
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1);
} elseif ($action == 'activate') {
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", '', 0, 1);
$formquestion = array(
array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), /*'value' => $form->selectDate('', '', $usehm, $usehm, '', "active", 1, 0),*/ /*'socid', '(s.client=1 OR s.client=2 OR s.client=3)'*/),
array('type' => 'date', 'name' => 'd_end', 'label' => $langs->trans("DateEndPlanned"), /*'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0),*/ '', ''),
array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300')
);
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280);
} elseif ($action == 'clone') {
// Clone confirmation
$formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)')));

View File

@ -369,7 +369,7 @@ class Contrat extends CommonObject
* @return int <0 if KO, >0 if OK
* @see ()
*/
public function activateAll($user, $date_start = '', $notrigger = 0, $comment = '')
public function activateAll($user, $date_start = '', $notrigger = 0, $comment = '', $date_end = '')
{
if (empty($date_start)) {
$date_start = dol_now();
@ -387,7 +387,7 @@ class Contrat extends CommonObject
if ($contratline->statut != ContratLigne::STATUS_OPEN) {
$contratline->context = $this->context;
$result = $contratline->active_line($user, $date_start, -1, $comment); // This call trigger LINECONTRACT_ACTIVATE
$result = $contratline->active_line($user, $date_start, !empty($date_end) ? $date_end : -1, $comment); // This call trigger LINECONTRACT_ACTIVATE
if ($result < 0) {
$error++;
$this->error = $contratline->error;

View File

@ -69,10 +69,10 @@ $type = $mode;
// Check securitykey
$securekeyseed = '';
if ($type == 'proposal') {
$securekeyseed = $conf->global->PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN;
$securekeyseed = isset($conf->global->PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN) ? $conf->global->PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN : '';
}
if (!dol_verifyHash($securekeyseed.$type.$ref, $SECUREKEY, '0')) {
if (empty($SECUREKEY) || !dol_verifyHash($securekeyseed.$type.$ref, $SECUREKEY, '0')) {
http_response_code(403);
print 'Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref);
exit(-1);
@ -122,28 +122,40 @@ if ($action == "importSignature") {
}
if (!$error) {
$newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
// Defined modele of doc
$directdownloadlink = $object->getLastMainDocLink('proposal');
$pdf = pdf_getInstance();
$pdf->Open();
$pdf->AddPage();
$pagecount = $pdf->setSourceFile($upload_dir.$ref.".pdf"); // original PDF
if (preg_match('/\.pdf/i', $directdownloadlink)) {
$newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
$sourcefile = $upload_dir.$ref.".pdf";
for ($i=1;$i<($pagecount+1);$i++) {
if ($i>1) $pdf->AddPage();
$tppl=$pdf->importPage($i);
$pdf->useTemplate($tppl);
if (dol_is_file($sourcefile)) {
$pdf = pdf_getInstance();
$pdf->Open();
$pdf->AddPage();
$pagecount = $pdf->setSourceFile($sourcefile); // original PDF
for ($i=1; $i<($pagecount+1); $i++) {
if ($i>1) $pdf->AddPage();
$tppl=$pdf->importPage($i);
$pdf->useTemplate($tppl);
}
$pdf->Image($upload_dir.$filename, 129, 239.6, 60, 15); // FIXME Position will be wrong with non A4 format. Use a value from width and height of page minus relative offset.
$pdf->Close();
$pdf->Output($newpdffilename, "F");
// Index the new file and update the last_main_doc property of object.
$object->indexFile($newpdffilename, 1);
}
} else {
// Adding signature on doc not yet supported
}
}
$pdf->Image($upload_dir.$filename, 129, 239.6, 60, 15); // FIXME Position will be wrong with non A4 format. Use a value from width and height of page minus relative offset.
$pdf->Close();
$pdf->Output($newpdffilename, "F");
if (!$error) {
$db->begin();
// Index the new file and update the last_main_doc property of object.
$object->indexFile($newpdffilename, 1);
$online_sign_ip = getUserRemoteIP();
$online_sign_name = ''; // TODO Ask name on form to sign

View File

@ -602,6 +602,8 @@ abstract class CommonObject
// No constructor as it is an abstract class
/**
* Check an object id/ref exists
* If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch
@ -648,6 +650,7 @@ abstract class CommonObject
return -1;
}
/**
* Method to output saved errors
*
@ -5530,7 +5533,9 @@ abstract class CommonObject
* Index a file into the ECM database
*
* @param string $destfull Full path of file to index
* @param int $update_main_doc_field Update field main_doc file into table of object
* @param int $update_main_doc_field Update field main_doc fied into the table of object.
* This param is set when called for a document generation if document generator hase
* ->update_main_doc_field set and returns ->result['fullpath'].
* @return int <0 if KO, >0 if OK
*/
public function indexFile($destfull, $update_main_doc_field)
@ -8907,7 +8912,7 @@ abstract class CommonObject
}
}
} else {
$this->{$field} = !empty($obj->{$field}) ? $obj->{$field} : null;
$this->{$field} = isset($obj->{$field}) ? $obj->{$field} : null;
}
}

View File

@ -2071,6 +2071,7 @@ class ExtraFields
}
if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'chkbxlst')))) {
//when unticking boolean field, it's not set in POST
continue;
}

View File

@ -8550,7 +8550,7 @@ class Form
if (empty($conf->supplier_proposal->enabled)) {
continue; // Do not show if module disabled
}
} elseif ($objecttype == 'shipping' || $objecttype == 'shipment') {
} elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
$tplpath = 'expedition';
if (empty($conf->expedition->enabled)) {
continue; // Do not show if module disabled
@ -8668,6 +8668,11 @@ class Form
'perms'=>1,
'label'=>'LinkToProposal',
'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('propal').')'),
'shipping'=>array(
'enabled'=>$conf->expedition->enabled,
'perms'=>1,
'label'=>'LinkToExpedition',
'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('shipping').')'),
'order'=>array(
'enabled'=>(!empty($conf->commande->enabled) ? $conf->commande->enabled : 0),
'perms'=>1,

View File

@ -3343,6 +3343,17 @@ function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addli
//ex: +61_A_BCDE_FGHI
$newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 1).$separ.substr($newphone, 4, 4).$separ.substr($newphone, 8, 4);
}
} elseif (strtoupper($countrycode) == "LU") {
// Luxembourg
if (dol_strlen($phone) == 10) {// fixe 6 chiffres +352_AA_BB_CC
$newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2);
} elseif (dol_strlen($phone) == 11) {// fixe 7 chiffres +352_AA_BB_CC_D
$newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 1);
} elseif (dol_strlen($phone) == 12) {// fixe 8 chiffres +352_AA_BB_CC_DD
$newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
} elseif (dol_strlen($phone) == 13) {// mobile +352_AAA_BB_CC_DD
$newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
}
}
if (!empty($addlink)) { // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set)
if ($conf->browser->layout == 'phone' || (!empty($conf->clicktodial->enabled) && !empty($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) { // If phone or option for, we use link of phone
@ -5458,9 +5469,10 @@ function print_fleche_navigation($page, $file, $options = '', $nextpage = 0, $be
* @param boolean $addpercent Add a percent % sign in output
* @param int $info_bits Miscellaneous information on vat (0=Default, 1=French NPR vat)
* @param int $usestarfornpr -1=Never show, 0 or 1=Use '*' for NPR vat rates
* @param int $html Used for html output
* @return string String with formated amounts ('19,6' or '19,6%' or '8.5% (NPR)' or '8.5% *' or '19,6 (CODEX)')
*/
function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0)
function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0, $html = 0)
{
$morelabel = '';
@ -5468,9 +5480,11 @@ function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0)
$rate = str_replace('%', '', $rate);
$addpercent = true;
}
$reg = array();
if (preg_match('/\((.*)\)/', $rate, $reg)) {
$morelabel = ' ('.$reg[1].')';
$rate = preg_replace('/\s*'.preg_quote($morelabel, '/').'/', '', $rate);
$morelabel = ' '.($html ? '<span class="opacitymedium">' : '').'('.$reg[1].')'.($html ? '</span>' : '');
}
if (preg_match('/\*/', $rate)) {
$rate = str_replace('*', '', $rate);
@ -7832,7 +7846,7 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null, $con
} else {
if (! $msgishtml) {
$valueishtml = dol_textishtml($value, 1);
var_dump("valueishtml=".$valueishtml);
//var_dump("valueishtml=".$valueishtml);
if ($valueishtml) {
$text = dol_htmlentitiesbr($text);

View File

@ -954,6 +954,7 @@ function getCustomerInvoiceUnpaidOpenTable($maxCount = 500, $socid = 0)
$i++;
$total += $obj->total_ht;
$total_ttc += $obj->total_ttc;
$totalam += $obj->am;
continue;
}

View File

@ -239,22 +239,26 @@ class modResource extends DolibarrModules
$this->export_code[$r] = $this->rights_class.'_'.$r;
$this->export_label[$r] = "ResourceSingular"; // Translation key (used only if key ExportDataset_xxx_z not found)
$this->export_permission[$r] = array(array("resource", "read"));
$this->export_fields_array[$r] = array('r.rowid'=>'IdResource', 'r.ref'=>'ResourceFormLabel_ref', 'c.code'=>'ResourceTypeCode', 'c.label'=>'ResourceType', 'r.description'=>'ResourceFormLabel_description', 'r.note_private'=>"NotePrivate", 'r.note_public'=>"NotePublic", 'r.asset_number'=>'AssetNumber', 'r.datec'=>"DateCreation", 'r.tms'=>"DateLastModification");
$this->export_fields_array[$r] = array('r.rowid'=>'IdResource', 'r.ref'=>'ResourceFormLabel_ref', 'c.rowid'=>'ResourceTypeID', 'c.code'=>'ResourceTypeCode', 'c.label'=>'ResourceTypeLabel', 'r.description'=>'ResourceFormLabel_description', 'r.note_private'=>"NotePrivate", 'r.note_public'=>"NotePublic", 'r.asset_number'=>'AssetNumber', 'r.datec'=>"DateCreation", 'r.tms'=>"DateLastModification");
$this->export_TypeFields_array[$r] = array('r.rowid'=>'List:resource:ref', 'r.ref'=>'Text', 'r.asset_number'=>'Text', 'r.description'=>'Text', 'c.code'=>'Text', 'c.label'=>'List:c_type_resource:label', 'r.datec'=>'Date', 'r.tms'=>'Date', 'r.note_private'=>'Text', 'r.note_public'=>'Text');
$this->export_entities_array[$r] = array('r.rowid'=>'resource', 'r.ref'=>'resource', 'c.code'=>'resource', 'c.label'=>'resource', 'r.description'=>'resource', 'r.note_private'=>"resource", 'r.resource'=>"resource", 'r.asset_number'=>'resource', 'r.datec'=>"resource", 'r.tms'=>"resource");
$keyforselect = 'resource';
$keyforelement = 'resource';
$keyforaliasextra = 'extra';
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
$this->export_dependencies_array[$r] = array('resource'=>array('r.rowid')); // We must keep this until the aggregate_array is used. To add unique key if we ask a field of a child to avoid the DISTINCT to discard them.
$this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'resource as r';
$this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_resource as c ON c.rowid=r.fk_code_type_resource';
$this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_resource as c ON c.code = r.fk_code_type_resource';
$this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'resource_extrafields as extra ON extra.fk_object = r.rowid';
$this->export_sql_end[$r] .= ' WHERE r.entity IN ('.getEntity('resource').')';
// Imports
//--------
$r = 0;

View File

@ -71,6 +71,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales
$this->db = $db;
$this->name = "ODT templates";
$this->description = $langs->trans("DocumentModelOdt");
$this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
$this->scandir = 'PROPALE_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
// Page size for A4 format

View File

@ -67,7 +67,7 @@ abstract class ModelePDFPropales extends CommonDocGenerator
/**
* Classe mere des modeles de numerotation des references de propales
* Parent class for numbering rules of proposals
*/
abstract class ModeleNumRefPropales
{

View File

@ -43,10 +43,10 @@ if (!empty($conf->commande->enabled)) {
print '<input type="text class="flat" id="generate_order_ref" name="generate_order_ref" value="'.GETPOST('generate_order_ref', 'alpha').'" size="10">';
print '<input type="submit" class="none reposition button smallpaddingimp" value="'.$langs->trans("GetSecuredUrl").'">';
if (GETPOST('generate_order_ref', 'alpha')) {
print '<br> -> <strong class="wordbreak">';
$url = getOnlinePaymentUrl(0, 'order', GETPOST('generate_order_ref', 'alpha'));
print '<div class="urllink"><input type="text" class="wordbreak quatrevingtpercent" value="';
print $url;
print "</strong><br>\n";
print '"></div>'."\n";
}
print '</form>';
}
@ -65,10 +65,10 @@ if (isModEnabled('facture')) {
print '<input type="text class="flat" id="generate_invoice_ref" name="generate_invoice_ref" value="'.GETPOST('generate_invoice_ref', 'alpha').'" size="10">';
print '<input type="submit" class="none reposition button smallpaddingimp" value="'.$langs->trans("GetSecuredUrl").'">';
if (GETPOST('generate_invoice_ref', 'alpha')) {
print '<br> -> <strong class="wordbreak">';
$url = getOnlinePaymentUrl(0, 'invoice', GETPOST('generate_invoice_ref', 'alpha'));
print '<div class="urllink"><input type="text" class="wordbreak quatrevingtpercent" value="';
print $url;
print "</strong><br>\n";
print '"></div>'."\n";
}
print '</form>';
}
@ -87,10 +87,10 @@ if (!empty($conf->contrat->enabled)) {
print '<input type="text class="flat" id="generate_contract_ref" name="generate_contract_ref" value="'.GETPOST('generate_contract_ref', 'alpha').'" size="10">';
print '<input type="submit" class="none reposition button smallpaddingimp" value="'.$langs->trans("GetSecuredUrl").'">';
if (GETPOST('generate_contract_ref')) {
print '<br> -> <strong class="wordbreak">';
$url = getOnlinePaymentUrl(0, 'contractline', GETPOST('generate_contract_ref', 'alpha'));
print '<div class="urllink"><input type="text" class="wordbreak quatrevingtpercent" value="';
print $url;
print "</strong><br>\n";
print '"></div>'."\n";
}
print '</form>';
}
@ -109,10 +109,10 @@ if (!empty($conf->adherent->enabled)) {
print '<input type="text class="flat" id="generate_member_ref" name="generate_member_ref" value="'.GETPOST('generate_member_ref', 'alpha').'" size="10">';
print '<input type="submit" class="none reposition button smallpaddingimp" value="'.$langs->trans("GetSecuredUrl").'">';
if (GETPOST('generate_member_ref')) {
print '<br> -> <strong class="wordbreak">';
$url = getOnlinePaymentUrl(0, 'membersubscription', GETPOST('generate_member_ref', 'alpha'));
print '<div class="urllink"><input type="text" class="wordbreak quatrevingtpercent" value="';
print $url;
print "</strong><br>\n";
print '"></div>'."\n";
}
print '</form>';
}
@ -131,10 +131,10 @@ if (!empty($conf->don->enabled)) {
print '<input type="text class="flat" id="generate_donation_ref" name="generate_donation_ref" value="'.GETPOST('generate_donation_ref', 'alpha').'" size="10">';
print '<input type="submit" class="none reposition button smallpaddingimp" value="'.$langs->trans("GetSecuredUrl").'">';
if (GETPOST('generate_donation_ref')) {
print '<br> -> <strong class="wordbreak">';
print '<div class="urllink"><input type="text" class="wordbreak quatrevingtpercent" value="';
$url = getOnlinePaymentUrl(0, 'donation', GETPOST('generate_donation_ref', 'alpha'));
print $url;
print "</strong><br>\n";
print '"></div>'."\n";
}
print '</form>';
}

View File

@ -258,7 +258,7 @@ llxHeader('', $langs->trans("CronTask"));
$head = cron_prepare_head($object);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("CronTask"), '', 'title_setup');
}

View File

@ -259,7 +259,7 @@ llxHeader('', $title, 'Livraison');
$form = new Form($db);
$formfile = new FormFile($db);
if ($action == 'create' || (empty($action) && empty($id))) { // Create. Seems to no be used
if ($action == 'create') { // Create. Seems to no be used
} else // View
{
if ($object->id > 0) {

View File

@ -386,7 +386,7 @@ if (!empty($conf->project->enabled)) {
$formproject = new FormProjets($db);
}
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("AddDonation"), '', 'object_donation');
print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST">';

View File

@ -206,7 +206,7 @@ llxHeader('', $langs->trans("ECMNewSection"));
$form = new Form($db);
$formecm = new FormEcm($db);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
//***********************
// Create
//***********************

View File

@ -166,7 +166,7 @@ $title = $langs->trans("ConferenceOrBooth");
$help_url = '';
llxHeader('', $title, $help_url);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$result = $projectstatic->fetch(GETPOST('fk_project'));
} else {
$result = $projectstatic->fetch($object->fk_project);
@ -392,7 +392,7 @@ if (!empty($withproject)) {
}
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("ConferenceOrBooth")), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -420,7 +420,7 @@ if (!empty($withproject)) {
}
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("ConferenceOrBoothAttendee")), '', 'object_'.$object->picto);

View File

@ -835,7 +835,7 @@ if ($action == 'create2') {
}
// Mode creation.
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$expe = new Expedition($db);
print load_fiche_titre($langs->trans("CreateShipment"), '', 'dolly');
@ -2569,8 +2569,8 @@ if ($action == 'create' || (empty($action) && empty($id))) {
// Show links to link elements
//$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
$somethingshown = $form->showLinkedObjectBlock($object, '');
$linktoelem = $form->showLinkToObjectBlock($object, null, array('shipping'));
$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
print '</div><div class="fichehalfright">';

View File

@ -60,8 +60,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) {
// For now, shipments must stay linked to order, so link is not deletable
if ($object->element != 'commande') {
?>
<a class="reposition" href="<?php echo $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=dellink&dellinkid='.$key; ?>"><?php echo img_picto($langs->transnoentitiesnoconv("RemoveLink"), 'unlink'); ?></a></td>
<?php
<a class="reposition" href="<?php echo $_SERVER["PHP_SELF"].'?id='.$object->id.'&token='.newToken().'&action=dellink&dellinkid='.$key; ?>"><?php echo img_picto($langs->transnoentitiesnoconv("RemoveLink"), 'unlink'); ?></a></td> <?php
}
?>
</tr>

View File

@ -1389,7 +1389,7 @@ $ecmfilesstatic = new EcmFiles($db);
$formexpensereport = new FormExpenseReport($db);
// Create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewTrip"), '', 'trip');
print '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="create">';

View File

@ -796,7 +796,7 @@ $help_url = 'EN:Module_Interventions';
llxHeader('', $langs->trans("Intervention"), $help_url);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
// Create new intervention
$soc = new Societe($db);

View File

@ -960,7 +960,7 @@ class ProductFournisseur extends Product
public function display_price_product_fournisseur($showunitprice = 1, $showsuptitle = 1, $maxlen = 0, $notooltip = 0, $productFournList = array())
{
// phpcs:enable
global $langs;
global $conf, $langs;
$out = '';
$langs->load("suppliers");
@ -978,7 +978,7 @@ class ProductFournisseur extends Product
}
$out .= '</table>';
} else {
$out = ($showunitprice ? price($this->fourn_unitprice * (1 - $this->fourn_remise_percent / 100) + $this->fourn_remise).' '.$langs->trans("HT").' &nbsp; <span class="opacitymedium">(</span>' : '');
$out = ($showunitprice ? price($this->fourn_unitprice * (1 - $this->fourn_remise_percent / 100) + $this->fourn_remise, 0, $langs, 1, -1, -1, $conf->currency).' '.$langs->trans("HT").' &nbsp; <span class="opacitymedium">(</span>' : '');
$out .= ($showsuptitle ? '<span class="opacitymedium">'.$langs->trans("Supplier").'</span>: ' : '').$this->getSocNomUrl(1, 'supplier', $maxlen, $notooltip).' / <span class="opacitymedium">'.$langs->trans("SupplierRef").'</span>: '.$this->ref_supplier;
$out .= ($showunitprice ? '<span class="opacitymedium">)</span>' : '');
}

View File

@ -1547,7 +1547,7 @@ llxHeader('', $title, $help_url);
$now = dol_now();
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans('NewOrderSupplier'), '', 'supplier_order');
dol_htmloutput_events();

View File

@ -1902,7 +1902,7 @@ $help_url = 'EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Mó
llxHeader('', $title, $help_url);
// Mode creation
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$facturestatic = new FactureFournisseur($db);
print load_fiche_titre($langs->trans('NewSupplierInvoice'), '', 'supplier_invoice');

View File

@ -159,7 +159,7 @@ $formcompany = new FormCompany($db);
/*
* Action create
*/
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewEstablishment"));
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';

View File

@ -255,7 +255,7 @@ print '<script type="text/javascript" language="javascript">
</script>';
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewEval"), '', 'object_' . $object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -180,7 +180,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentities('Job')), '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';

View File

@ -187,7 +187,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewSkill"), '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';

View File

@ -661,3 +661,5 @@ DELETE FROM llx_cronjob WHERE label = 'PurgeDeleteTemporaryFilesShort' AND param
ALTER TABLE llx_cronjob DROP INDEX uk_cronjob;
ALTER TABLE llx_cronjob ADD UNIQUE INDEX uk_cronjob (label, entity);
ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0;

View File

@ -42,6 +42,8 @@ ALTER TABLE llx_c_email_templates ADD COLUMN email_to varchar(255);
ALTER TABLE llx_c_email_templates ADD COLUMN email_tocc varchar(255);
ALTER TABLE llx_c_email_templates ADD COLUMN email_tobcc varchar(255);
ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0;
-- v17

View File

@ -17,6 +17,10 @@
-- This table is just an history table to track all receiving done for a
-- particular supplier order. A movement with same information is also done
-- into stock_movement so this table may be useless.
--
-- Detail of each lines of a reception (qty, batch and into wich warehouse is
-- received a purchase order line).
-- This table should be also name llx_receptiondet.
-- ===================================================================
create table llx_commande_fournisseur_dispatch

View File

@ -1,5 +1,5 @@
-- ============================================================================
-- Copyright (C) 2021 Maxime Kohlhaas <support@atm-consulting.fr>
-- Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
--
-- 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
@ -16,6 +16,7 @@
--
-- ============================================================================
ALTER TABLE llx_element_tag ADD UNIQUE INDEX idx_element_tag_uk (fk_categorie, fk_element);
ALTER TABLE llx_element_tag ADD CONSTRAINT fk_element_tag_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid);
ALTER TABLE llx_element_categorie ADD UNIQUE INDEX idx_element_categorie_idx1 (fk_element, fk_categorie);
ALTER TABLE llx_element_contact ADD CONSTRAINT fk_element_categorie_fk_categorie FOREIGN KEY (fk_categorie) REFERENCES llx_fk_categorie(rowid);

View File

@ -1,5 +1,5 @@
-- ============================================================================
-- Copyright (C) 2021 Maxime Kohlhaas <support@atm-consulting.fr>
-- Copyright (C) 2022 charlene Benke <charlene@patas-monkey.com>
--
-- 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
@ -16,7 +16,7 @@
--
-- ============================================================================
create table llx_element_tag
create table llx_element_categorie
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
fk_categorie integer NOT NULL,

View File

@ -156,7 +156,7 @@ if ($action == 'add' && $permissiontoadd) {
*/
// Creation mode
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$title = $langs->trans("IntracommReportTitle");
llxHeader("", $title);
print load_fiche_titre($langs->trans("IntracommReportTitle"));

View File

@ -169,7 +169,7 @@ $help_url = '';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewKnowledgeRecord"), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -136,4 +136,10 @@ PrintWithoutDetails=Print without details
YearNotDefined=Year is not defined
TakeposBarcodeRuleToInsertProduct=Barcode rule to insert product
TakeposBarcodeRuleToInsertProductDesc=Rule to extract the product reference + a quantity from a scanned barcode.<br>If empty (default value), application will use the full barcode scanned to find the product.<br><br>If defined, syntax must be:<br><b>ref:NB+qu:NB+qd:NB+other:NB</b><br>where NB is the number of characters to use to extract data from the scanned barcode with: <ul><li><b>ref</b> : product reference</li><li><b>qu</b> : quantity to set when inserting item (units)<l/i><li><b>qd</b> : quantity to set when inserting item (decimals)</li><li><b>other</b> : others characters</li></ul>
AlreadyPrinted=Already printed
AlreadyPrinted=Already printed
HideCategories=Hide categories
HideStockOnLine=Hide stock on line
ShowOnlyProductInStock=Show the products in stock
ShowCategoryDescription=Show category description
ShowProductReference=Show reference of products
UsePriceHT=Use price excl. taxes and not price incl. taxes

View File

@ -40,6 +40,7 @@ Language_es_AR=Spanish (Argentina)
Language_es_BO=Spanish (Bolivia)
Language_es_CL=Spanish (Chile)
Language_es_CO=Spanish (Colombia)
Language_es_CR=Spanish (Costa Rica)
Language_es_DO=Spanish (Dominican Republic)
Language_es_EC=Spanish (Ecuador)
Language_es_GT=Spanish (Guatemala)

View File

@ -801,6 +801,7 @@ URLPhoto=URL of photo/logo
SetLinkToAnotherThirdParty=Link to another third party
LinkTo=Link to
LinkToProposal=Link to proposal
LinkToExpedition= Link to expedition
LinkToOrder=Link to order
LinkToInvoice=Link to invoice
LinkToTemplateInvoice=Link to template invoice

View File

@ -136,3 +136,9 @@ PrintWithoutDetails=Générer sans les détails
YearNotDefined=L'année n'est pas définie
TakeposBarcodeRuleToInsertProduct=Règle de lecture du code barre des produits
TakeposBarcodeRuleToInsertProductDesc=Règle pour extraire la référence produit + une quantité d'un code barre scanné. <br> Si vide (valeur par défaut), l'application utilisera le code-barres complet scanné pour trouver le produit. <br> <br> Si elle est définie, la syntaxe doit être: <br> <b> ref: NB + Qu: NB + QD: NB + autres: NB </b> <br> où NB est le nombre de caractères à utiliser pour extraire les données du code à barres scannés avec: <ul> <li> <b> ref </b>: référence produit </li> <li> <b> qu </b>: quantité de jeu lors de l'insertion article (unités) <l/i> <li> <b> </b> qd: quantité de jeu lors de l'insertion article (décimaux) </li> <li> <b> autre </b>: autres caractères </li> </ul>
HideCategories=Masquer les catégories
HideStockOnLine=Masquer le stock en ligne
ShowOnlyProductInStock=Affficher les produits en stock
ShowCategoryDescription=Afficher la description des catégories
ShowProductReference=Afficher la référence des produits
UsePriceHT= Utiliser le prix HT et non en TTC

View File

@ -801,6 +801,7 @@ URLPhoto=URL de la photo/logo
SetLinkToAnotherThirdParty=Lier vers un autre tiers
LinkTo=Lier à
LinkToProposal=Lier à une proposition commerciale
LinkToExpedition=Lier à une expédition
LinkToOrder=Lier à une commande
LinkToInvoice=Lier à une facture
LinkToTemplateInvoice=Lien vers le modèle de facture

View File

@ -254,7 +254,7 @@ llxHeader("", $title, $help_url);
// Create mode
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
//WYSIWYG Editor
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';

View File

@ -242,7 +242,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
if (empty($permissiontoadd)) {
accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1);
exit;

View File

@ -241,7 +241,7 @@ llxHeader('', $title, '');
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
if (GETPOST('fk_bom', 'int') > 0) {
$titlelist = $langs->trans("ToConsume");
if ($objectbom->bomtype == 1) {

View File

@ -259,7 +259,7 @@ $help_url = '';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewPartnership"), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -181,7 +181,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewInventory"), '', 'product');
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -1177,7 +1177,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_
if (empty($positiverates)) {
$positiverates = '0';
}
echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), '%', $object->tva_npr);
echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), '%', $object->tva_npr, 0, 1);
/*
if ($object->default_vat_code)
{

View File

@ -290,7 +290,7 @@ $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
llxHeader("", $title, $help_url);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewWarehouse"), '', 'stock');
dol_set_focus('input[name="libelle"]');

View File

@ -734,6 +734,15 @@ if ($id > 0 || $ref) {
$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
$text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'<br>' : '');
$parameters = array();
$reshook = $hookmanager->executeHooks('physicalStockTextStockOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
if ($reshook > 0) {
$text_stock_options = $hookmanager->resPrint;
} elseif ($reshook == 0) {
$text_stock_options .= $hookmanager->resPrint;
} else {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
print '<tr><td>';
print $form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1);
@ -820,6 +829,15 @@ if ($id > 0 || $ref) {
$helpondiff .= $langs->trans("ProductQtyToConsumeByMO").': '.$object->stats_mrptoconsume['qty'].'<br>';
$helpondiff .= $langs->trans("ProductQtyToProduceByMO").': '.$object->stats_mrptoproduce['qty'];
}
$parameters = array('found' => &$found, 'id' => $object->id, 'includedraftpoforvirtual' => null);
$reshook = $hookmanager->executeHooks('virtualStockHelpOnDiff', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
if ($reshook > 0) {
$helpondiff = $hookmanager->resPrint;
} elseif ($reshook == 0) {
$helpondiff .= $hookmanager->resPrint;
} else {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
}
// Calculating a theorical value

View File

@ -378,7 +378,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("Batch"), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -413,7 +413,7 @@ print '});
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("StockTransfer")), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -328,7 +328,7 @@ if ($source == 'proposal') {
// Object
$text = '<b>'.$langs->trans("SignatureProposalRef", $proposal->ref).'</b>';
print '<tr class="CTableRow2"><td class="CTableRow2 tdtop">'.$langs->trans("Designation");
print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
print '</td><td class="CTableRow2">'.$text;
if ($proposal->status == $proposal::STATUS_VALIDATED) {
$directdownloadlink = $proposal->getLastMainDocLink('proposal');

View File

@ -728,7 +728,7 @@ if ($action == 'create2') {
}
// Mode creation.
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$recept = new Reception($db);
print load_fiche_titre($langs->trans("CreateReception"));

View File

@ -846,6 +846,21 @@ class Reception extends CommonObject
}
}
// Check batch is set
$product = new Product($this->db);
$product->fetch($fk_product);
if (!empty($conf->productbatch->enabled)) {
$langs->load("errors");
if (!empty($product->status_batch) && empty($batch)) {
$this->error = $langs->trans('ErrorProductNeedBatchNumber', $product->ref);
return -1;
} elseif (empty($product->status_batch) && !empty($batch)) {
$this->error = $langs->trans('ErrorProductDoesNotNeedBatchNumber', $product->ref);
return -1;
}
}
unset($product);
// extrafields
$line->array_options = $supplierorderline->array_options;
if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) {

View File

@ -283,7 +283,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("RecruitmentCandidature")), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -202,7 +202,7 @@ $help_url = '';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewPositionToBeFilled"), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -197,7 +197,7 @@ $form = new Form($db);
$formresource = new FormResource($db);
if ($action == 'create' || $object->fetch($id, $ref) > 0) {
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($title, '', 'object_resource');
print dol_get_fiche_head('');
} else {

View File

@ -457,7 +457,7 @@ if ($id > 0) {
}
// Create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$year_current = strftime("%Y", dol_now());
$pastmonth = strftime("%m", dol_now()) - 1;
$pastmonthyear = $year_current;

View File

@ -981,7 +981,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// -----------------------------------------
// When used in standard mode
// -----------------------------------------
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
/*
* Creation
*/

View File

@ -2,7 +2,7 @@
/* Copyright (C) 2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2017 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2017 Saasprov <saasprov@gmail.com>
* Copyright (C) 2018-2021 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2018-2022 Thibault FOUCART <support@ptibogxiv.net>
* Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
*
* This program is free software; you can redistribute it and/or modify
@ -104,6 +104,12 @@ if ($action == 'setvalue' && $user->admin) {
if (!$result > 0) {
$error++;
}
if (GETPOSTISSET('STRIPE_LOCATION')) {
$result = dolibarr_set_const($db, "STRIPE_LOCATION", GETPOST('STRIPE_LOCATION', 'alpha'), 'chaine', 0, '', $conf->entity);
if (!$result > 0) {
$error++;
}
}
$result = dolibarr_set_const($db, "ONLINE_PAYMENT_CSS_URL", GETPOST('ONLINE_PAYMENT_CSS_URL', 'alpha'), 'chaine', 0, '', $conf->entity);
if (!$result > 0) {
$error++;
@ -287,7 +293,7 @@ if (empty($conf->stripeconnect->enabled)) {
print '<br>';
}
print '<input class="minwidth300" type="text" name="STRIPE_LIVE_WEBHOOK_KEY" value="'.$conf->global->STRIPE_LIVE_WEBHOOK_KEY.'" placeholder="'.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx">';
$out = img_picto('', 'globe').' <span class="opacitymedium">'.$langs->trans("ToOfferALinkForLiveWebhook").'</span> ';
$out = img_picto('', 'globe', 'class="pictofixedwidth"').' <span class="opacitymedium">'.$langs->trans("ToOfferALinkForLiveWebhook").'</span> ';
$url = dol_buildpath('/public/stripe/ipn.php', 3);
$out .= '<input type="text" id="onlinelivewebhookurl" class="minwidth500" value="'.$url.'" disabled>';
$out .= ajax_autoselect("onlinelivewebhookurl", 0);
@ -347,23 +353,73 @@ print '</td></tr>';
print '<tr class="oddeven"><td>';
print $langs->trans("StripeUserAccountForActions").'</td><td>';
print img_picto('', 'user').$form->select_dolusers($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS, 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0);
print img_picto('', 'user', 'class="pictofixedwidth"').$form->select_dolusers($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS, 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0);
print '</td></tr>';
print '<tr class="oddeven"><td>';
print $langs->trans("BankAccount").'</td><td>';
print img_picto('', 'bank_account').' ';
print img_picto('', 'bank_account', 'class="pictofixedwidth"');
$form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS, 'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1);
print '</td></tr>';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { // What is this for ?
print '<tr class="oddeven"><td>';
print $langs->trans("BankAccountForBankTransfer").'</td><td>';
print img_picto('', 'bank_account').' ';
print img_picto('', 'bank_account', 'class="pictofixedwidth"');
$form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS, 'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS', 0, '', 1);
print '</td></tr>';
}
// Card Present for Stripe Terminal
if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code
print '<tr class="oddeven"><td>';
print $langs->trans("STRIPE_CARD_PRESENT").'</td><td>';
if ($conf->use_javascript_ajax) {
print ajax_constantonoff('STRIPE_CARD_PRESENT');
} else {
$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
print $form->selectarray("STRIPE_CARD_PRESENT", $arrval, $conf->global->STRIPE_CARD_PRESENT);
}
print '</td></tr>';
}
// Locations for Stripe Terminal
if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code
print '<tr class="oddeven"><td>';
print $langs->trans("STRIPE_LOCATION").'</td><td>';
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
global $stripearrayofkeysbyenv;
$site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key'];
\Stripe\Stripe::setApiKey($site_account);
if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) {
$service = 'StripeTest';
$servicestatus = '0';
dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning');
} else {
$service = 'StripeLive';
$servicestatus = '1';
}
$stripe = new Stripe($db);
$stripeacc = $stripe->getStripeAccount($service);
if ($stripeacc) {
$locations = \Stripe\Terminal\Location::all('', array("stripe_account" => $stripeacc));
} else {
$locations = \Stripe\Terminal\Location::all();
}
$location = array();
$location[""] = $langs->trans("EmptyLocation");
foreach ($locations as $locations) {
$location[$locations->id] = $locations->display_name;
}
print $form->selectarray("STRIPE_LOCATION", $location, $conf->global->STRIPE_LOCATION);
print '</td></tr>';
}
// Activate Payment Request API
if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code
print '<tr class="oddeven"><td>';

124
htdocs/stripe/ajax/ajax.php Normal file
View File

@ -0,0 +1,124 @@
<?php
/* Copyright (C) 2021 Thibault FOUCART <support@ptibogxiv.net>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/stripe/ajax/ajax.php
* \brief Ajax action for Stipe ie: Terminal
*/
if (!defined('NOCSRFCHECK')) {
define('NOCSRFCHECK', '1');
}
if (!defined('NOTOKENRENEWAL')) {
define('NOTOKENRENEWAL', '1');
}
if (!defined('NOREQUIREMENU')) {
define('NOREQUIREMENU', '1');
}
if (!defined('NOREQUIREHTML')) {
define('NOREQUIREHTML', '1');
}
if (!defined('NOREQUIREAJAX')) {
define('NOREQUIREAJAX', '1');
}
if (!defined('NOBROWSERNOTIF')) {
define('NOBROWSERNOTIF', '1');
}
require '../../main.inc.php'; // Load $user and permissions
require_once DOL_DOCUMENT_ROOT.'/includes/stripe/stripe-php/init.php';
require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
$action = GETPOST('action', 'aZ09');
$location = GETPOST('location', 'alphanohtml');
$stripeacc = GETPOST('stripeacc', 'alphanohtml');
$servicestatus = GETPOST('servicestatus', 'int');
$amount = GETPOST('amount', 'int');
if (empty($user->rights->takepos->run)) {
accessforbidden();
}
/*
* View
*/
if ($action == 'getConnexionToken') {
try {
// Be sure to authenticate the endpoint for creating connection tokens.
// Force to use the correct API key
global $stripearrayofkeysbyenv;
\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
// The ConnectionToken's secret lets you connect to any Stripe Terminal reader
// and take payments with your Stripe account.
$array = array();
if (isset($location) && !empty($location)) $array['location'] = $location;
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
$connectionToken = \Stripe\Terminal\ConnectionToken::create($array);
} else {
$connectionToken = \Stripe\Terminal\ConnectionToken::create($array, array("stripe_account" => $stripeacc));
}
echo json_encode(array('secret' => $connectionToken->secret));
} catch (Error $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
} elseif ($action == 'createPaymentIntent') {
try {
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
// For Terminal payments, the 'payment_method_types' parameter must include
// 'card_present' and the 'capture_method' must be set to 'manual'
$object = new Facture($db);
$object->fetch($json_obj->invoiceid);
$object->fetch_thirdparty();
$fulltag='INV='.$object->id.'.CUS='.$object->thirdparty->id;
$tag=null;
$fulltag=dol_string_unaccent($fulltag);
$stripe = new Stripe($db);
$customer = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1);
$intent = $stripe->getPaymentIntent($json_obj->amount, $object->multicurrency_code, null, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $customer, $stripeacc, $servicestatus, 1, 'terminal', false, null, 0, 1);
echo json_encode(array('client_secret' => $intent->client_secret));
} catch (Error $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
} elseif ($action == 'capturePaymentIntent') {
try {
// retrieve JSON from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
$intent = \Stripe\PaymentIntent::retrieve($json_obj->id);
} else {
$intent = \Stripe\PaymentIntent::retrieve($json_obj->id, array("stripe_account" => $stripeacc));
}
$intent = $intent->capture();
echo json_encode($intent);
} catch (Error $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
}

View File

@ -290,6 +290,34 @@ class Stripe extends CommonObject
return $stripepaymentmethod;
}
/**
* Get the Stripe reader Object from its ID
*
* @param string $reader Reader ID
* @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect
* @param int $status Status (0=test, 1=live)
* @return \Stripe\Terminal\Reader|null Stripe Reader or null if not found
*/
public function getSelectedReader($reader, $key = '', $status = 0)
{
$selectedreader = null;
try {
// Force to use the correct API key
global $stripearrayofkeysbyenv;
\Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
if (empty($key)) { // If the Stripe connect account not set, we use common API usage
$selectedreader = \Stripe\Terminal\Reader::retrieve(''.$reader.'');
} else {
$stripepaymentmethod = \Stripe\Terminal\Reader::retrieve(''.$reader.'', array("stripe_account" => $key));
}
} catch (Exception $e) {
$this->error = $e->getMessage();
}
return $selectedreader;
}
/**
* Get the Stripe payment intent. Create it with confirmnow=false
* Warning. If a payment was tried and failed, a payment intent was created.
@ -350,7 +378,7 @@ class Stripe extends CommonObject
$paymentintent = null;
if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND)) {
if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND) && empty($conf->global->STRIPE_CARD_PRESENT)) {
// Warning. If a payment was tried and failed, a payment intent was created.
// But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe.
// Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will
@ -424,6 +452,9 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_SOFORT)) {
$paymentmethodtypes[] = "sofort";
}
if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') {
$paymentmethodtypes = array("card_present");
}
$dataforintent = array(
"confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
@ -456,6 +487,11 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_KLARNA)) {
unset($dataforintent['setup_future_usage']);
}
if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') {
unset($dataforintent['setup_future_usage']);
$dataforintent["capture_method"] = "manual";
$dataforintent["confirmation_method"] = "manual";
}
if (!is_null($payment_method)) {
$dataforintent["payment_method"] = $payment_method;
$description .= ' - '.$payment_method;
@ -607,6 +643,9 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_BANCONTACT)) {
$paymentmethodtypes[] = "bancontact";
}
if (!empty($conf->global->STRIPE_KLARNA)) {
$paymentmethodtypes[] = "klarna";
}
if (!empty($conf->global->STRIPE_IDEAL)) {
$paymentmethodtypes[] = "ideal";
}

View File

@ -1141,7 +1141,7 @@ if (!empty($conf->project->enabled)) {
$now = dol_now();
// Add new askprice
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
$currency_code = $conf->currency;
print load_fiche_titre($langs->trans("SupplierProposalNew"), '', 'supplier_proposal');

View File

@ -117,6 +117,49 @@ $array = array(1=>"1", 2=>"2", 3=>"3", 4=>"4", 5=>"5", 6=>"6");
print $form->selectarray('TAKEPOS_LINES_TO_SHOW', $array, (empty($conf->global->TAKEPOS_LINES_TO_SHOW) ? '2' : $conf->global->TAKEPOS_LINES_TO_SHOW), 0);
print "</td></tr>\n";
// D'ont display category
print '<tr class="oddeven"><td>';
print $langs->trans('HideCategories');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_HIDE_CATEGORIES", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
// Hide stock on line
print '<tr class="oddeven"><td>';
print $langs->trans('HideStockOnLine');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_HIDE_STOCK_ON_LINE", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
// Only the products in stock
print '<tr class="oddeven"><td>';
print $langs->trans('ShowOnlyProductInStock');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_PRODUCT_IN_STOCK", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
// View description of the categories
print '<tr class="oddeven"><td>';
print $langs->trans('ShowCategoryDescription');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_SHOW_CATEGORY_DESCRIPTION", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
// View reference of products
print '<tr class="oddeven"><td>';
print $langs->trans('ShowProductReference');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_SHOW_PRODUCT_REFERENCE", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
// Use price excl. taxes (HT) and not price incl. taxes (TTC)
print '<tr class="oddeven"><td>';
print $langs->trans('UsePriceHT');
print '<td colspan="2">';
print ajax_constantonoff("TAKEPOS_CHANGE_PRICE_HT", array(), $conf->entity, 0, 0, 1, 0);
print "</td></tr>\n";
print '</table>';
print $form->buttonsSaveCancel("Save", '');

View File

@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2021 Thibault FOUCART <support@ptibogxiv.net>
*
* 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
@ -28,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT."/core/lib/takepos.lib.php";
require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
$terminal = GETPOST('terminal', 'int');
// If socid provided by ajax company selector
@ -73,6 +75,9 @@ if (GETPOST('action', 'alpha') == 'set') {
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CASH".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CHEQUE".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CB".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) {
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$terminaltouse, GETPOST('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, 'alpha'), 'chaine', 0, '', $conf->entity);
}
if (!empty($conf->global->TAKEPOS_ENABLE_SUMUP)) {
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_SUMUP".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
}
@ -174,6 +179,44 @@ if (!empty($conf->banque->enabled)) {
$atleastonefound++;
}
print '</td></tr>';
if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) {
print '<tr class="oddeven"><td>'.$langs->trans("CashDeskBankAccountForStripeTerminal").'</td>'; // Force Stripe Terminal
print '<td>';
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
global $stripearrayofkeysbyenv;
$site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key'];
\Stripe\Stripe::setApiKey($site_account);
if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) {
$service = 'StripeTest';
$servicestatus = '0';
dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning');
} else {
$service = 'StripeLive';
$servicestatus = '1';
}
$stripe = new Stripe($db);
$stripeacc = $stripe->getStripeAccount($service);
if ($stripeacc) {
$readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION, "stripe_account" => $stripeacc));
} else {
$readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION));
}
$reader = array();
$reader[""] = $langs->trans("NoReader");
foreach ($readers as $readers) {
$reader[$reader->id] = $readers->label.' ('.$readers->status.')';
}
print $form->selectarray('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, $reader, $conf->global->{'CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse});
print '</td></tr>';
}
if ($conf->global->TAKEPOS_ENABLE_SUMUP) {
print '<tr class="oddeven"><td>'.$langs->trans("CashDeskBankAccountForSumup").'</td>';
print '<td>';

View File

@ -1,5 +1,6 @@
<?php
/* Copyright (C) 2018 Andreu Bisquerra <jove@bisquerra.com>
* Copyright (C) 2021 Thibault FOUCART <support@ptibogxiv.net>
*
* 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
@ -40,6 +41,7 @@ if (!defined('NOREQUIREHTML')) {
require '../main.inc.php'; // Load $user and permissions
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
$langs->loadLangs(array("main", "bills", "cashdesk", "banks"));
@ -51,11 +53,60 @@ if (empty($user->rights->takepos->run)) {
accessforbidden();
}
if (!empty($conf->stripe->enabled)) {
$service = 'StripeTest';
$servicestatus = 0;
if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) {
$service = 'StripeLive';
$servicestatus = 1;
}
// Force to use the correct API key
global $stripearrayofkeysbyenv;
$site_account = $stripearrayofkeysbyenv[$servicestatus]['publishable_key'];
$stripe = new Stripe($db);
$stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account (no remote access to Stripe here)
$stripecu = $stripe->getStripeCustomerAccount($object->id, $servicestatus, $site_account); // Get remote Stripe customer 'cus_...' (no remote access to Stripe here)
$keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"];
?>
<script src="https://js.stripe.com/terminal/v1/"></script>
<script>
var terminal = StripeTerminal.create({
onFetchConnectionToken: fetchConnectionToken,
onUnexpectedReaderDisconnect: unexpectedDisconnect,
});
function unexpectedDisconnect() {
// In this function, your app should notify the user that the reader disconnected.
// You can also include a way to attempt to reconnect to a reader.
console.log("Disconnected from reader")
}
function fetchConnectionToken() {
<?php
$urlconnexiontoken = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=getConnexionToken&servicestatus='.$servicestatus;
if (!empty($conf->global->STRIPE_LOCATION)) $urlconnexiontoken .= '&location='.$conf->global->STRIPE_LOCATION;
if (!empty($stripeacc)) $urlconnexiontoken .= '&stripeacc='.$stripeacc;
?>
// Do not cache or hardcode the ConnectionToken. The SDK manages the ConnectionToken's lifecycle.
return fetch('<?php echo $urlconnexiontoken; ?>', { method: "POST" })
.then(function(response) {
return response.json();
})
.then(function(data) {
return data.secret;
});
}
</script>
<?php }
/*
* View
*/
if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) {
dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning', 1);
}
$invoice = new Facture($db);
if ($invoiceid > 0) {
$invoice->fetch($invoiceid);
@ -73,6 +124,57 @@ if ($invoiceid > 0) {
}
}
?>
<script>
<?php
if ($invoice->type != $invoice::TYPE_CREDIT_NOTE) {
if (empty($conf->global->$keyforstripeterminalbank)) { ?>
const config = {simulated: <?php if (empty($servicestatus) && !empty($conf->global->STRIPE_TERMINAL_SIMULATED)) { ?> true <?php } else { ?> false <?php } ?>
<?php if (!empty($conf->global->STRIPE_LOCATION)) { ?>, location: '<?php echo $conf->global->STRIPE_LOCATION; ?>'<?php } ?>}
terminal.discoverReaders(config).then(function(discoverResult) {
if (discoverResult.error) {
console.log('Failed to discover: ', discoverResult.error);
} else if (discoverResult.discoveredReaders.length === 0) {
console.log('No available readers.');
} else {
// You should show the list of discoveredReaders to the
// cashier here and let them select which to connect to (see below).
selectedReader = discoverResult.discoveredReaders[0];
//console.log('terminal.discoverReaders', selectedReader); // only active for development
terminal.connectReader(selectedReader).then(function(connectResult) {
if (connectResult.error) {
document.getElementById("card-present-alert").innerHTML = '<div class="error">'+connectResult.error.message+'</div>';
console.log('Failed to connect: ', connectResult.error);
} else {
document.getElementById("card-present-alert").innerHTML = '';
console.log('Connected to reader: ', connectResult.reader.label);
if (document.getElementById("StripeTerminal")) {
document.getElementById("StripeTerminal").innerHTML = '<button type="button" class="calcbutton2" onclick="ValidateStripeTerminal();"><span class="fa fa-2x fa-credit-card iconwithlabel"></span><br>'+connectResult.reader.label+'</button>';
}
}
});
}
});
<?php } else { ?>
terminal.connectReader(<?php echo json_encode($stripe->getSelectedReader($conf->global->$keyforstripeterminalbank, $stripeacc, $servicestatus)); ?>).then(function(connectResult) {
if (connectResult.error) {
document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+connectResult.error.message+'</div>';
console.log('Failed to connect: ', connectResult.error);
} else {
document.getElementById("card-present-alert").innerHTML = '';
console.log('Connected to reader: ', connectResult.reader.label);
if (document.getElementById("StripeTerminal")) {
document.getElementById("StripeTerminal").innerHTML = '<button type="button" class="calcbutton2" onclick="ValidateStripeTerminal();"><span class="fa fa-2x fa-credit-card iconwithlabel"></span><br>'+connectResult.reader.label+'</button>';
}
}
});
<?php } } ?>
</script>
<?php
$arrayofcss = array('/takepos/css/pos.css.php');
$arrayofjs = array();
@ -223,6 +325,112 @@ if ($conf->global->TAKEPOS_NUMPAD == 0) {
});
}
function fetchPaymentIntentClientSecret(amount, invoiceid) {
const bodyContent = JSON.stringify({ amount : amount, invoiceid : invoiceid });
<?php
$urlpaymentintent = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=createPaymentIntent&servicestatus='.$servicestatus;
if (!empty($stripeacc)) $urlpaymentintent .= '&stripeacc='.$stripeacc;
?>
return fetch('<?php echo $urlpaymentintent; ?>', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: bodyContent
})
.then(function(response) {
return response.json();
})
.then(function(data) {
return data.client_secret;
});
}
function capturePaymentIntent(paymentIntentId) {
const bodyContent = JSON.stringify({"id": paymentIntentId})
<?php
$urlpaymentintent = DOL_URL_ROOT.'/stripe/ajax/ajax.php?action=capturePaymentIntent&servicestatus='.$servicestatus;
if (!empty($stripeacc)) $urlpaymentintent .= '&stripeacc='.$stripeacc;
?>
return fetch('<?php echo $urlpaymentintent; ?>', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: bodyContent
})
.then(function(response) {
return response.json();
})
.then(function(data) {
return data.client_secret;
});
}
function ValidateStripeTerminal() {
console.log("Launch ValidateStripeTerminal");
var invoiceid = <?php echo($invoiceid > 0 ? $invoiceid : 0); ?>;
var accountid = $("#selectaccountid").val();
var amountpayed = $("#change1").val();
var excess = $("#change2").val();
if (amountpayed > <?php echo $invoice->getRemainToPay(); ?>) {
amountpayed = <?php echo $invoice->getRemainToPay(); ?>;
}
if (amountpayed == 0) {
amountpayed = <?php echo $invoice->getRemainToPay(); ?>;
}
console.log("Pay with terminal ", amountpayed);
fetchPaymentIntentClientSecret(amountpayed, invoiceid).then(function(client_secret) {
<?php if (empty($servicestatus) && !empty($conf->global->STRIPE_TERMINAL_SIMULATED)) { ?>
terminal.setSimulatorConfiguration({testCardNumber: '<?php echo $conf->global->STRIPE_TERMINAL_SIMULATED; ?>'});
<?php } ?>
document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentSendToStripeTerminal'); ?></div>';
terminal.collectPaymentMethod(client_secret).then(function(result) {
if (result.error) {
// Placeholder for handling result.error
document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
} else {
document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentBeingProcessed'); ?></div>';
console.log('terminal.collectPaymentMethod', result.paymentIntent);
terminal.processPayment(result.paymentIntent).then(function(result) {
if (result.error) {
document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
console.log(result.error)
} else if (result.paymentIntent) {
paymentIntentId = result.paymentIntent.id;
console.log('terminal.processPayment', result.paymentIntent);
capturePaymentIntent(paymentIntentId).then(function(client_secret) {
if (result.error) {
// Placeholder for handling result.error
document.getElementById("card-present-alert").innerHTML = '<div class="error clearboth">'+result.error.message+'</div>';
console.log("error when capturing paymentIntent", result.error);
} else {
document.getElementById("card-present-alert").innerHTML = '<div class="warning clearboth"><?php echo $langs->trans('PaymentValidated'); ?></div>';
console.log("Capture paymentIntent successfull "+paymentIntentId);
parent.$("#poslines").load("invoice.php?place=<?php echo $place; ?>&action=valid&pay=CB&amount="+amountpayed+"&excess="+excess+"&invoiceid="+invoiceid+"&accountid="+accountid, function() {
if (amountpayed > <?php echo $remaintopay; ?> || amountpayed == <?php echo $remaintopay; ?> || amountpayed==0 ) {
console.log("Close popup");
parent.$.colorbox.close();
}
else {
console.log("Amount is not comple, so we do NOT close popup and reload it.");
location.reload();
}
});
}
});
}
});
}
});
});
}
function ValidateSumup() {
console.log("Launch ValidateSumup");
<?php $_SESSION['SMP_CURRENT_PAYMENT'] = "NEW" ?>
@ -271,7 +479,7 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) {
?>
</script>
<div style="position:relative; padding-top: 20px; left:5%; height:150px; width:90%;">
<div style="position:relative; padding-top: 20px; left:5%; height:140px; width:90%;">
<div class="paymentbordline paymentbordlinetotal center">
<span class="takepospay colorwhite"><?php echo $langs->trans('TotalTTC'); ?>: <span id="totaldisplay" class="colorwhite"><?php echo price($invoice->total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?></span></span>
</div>
@ -299,7 +507,6 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) {
}
?>
</div>
<div style="position:absolute; left:5%; height:52%; width:90%;">
<?php
$action_buttons = array(
@ -317,7 +524,11 @@ $action_buttons = array(
),
);
$numpad = $conf->global->TAKEPOS_NUMPAD;
if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) {
print '<span id="card-present-alert">';
dol_htmloutput_mesg($langs->trans('ConnectingToStripeTerminal', 'Stripe'), '', 'warning', 1);
print '</span>';
}
print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '7' : '10').');">'.($numpad == 0 ? '7' : '10').'</button>';
print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '8' : '20').');">'.($numpad == 0 ? '8' : '20').'</button>';
print '<button type="button" class="calcbutton" onclick="addreceived('.($numpad == 0 ? '9' : '50').');">'.($numpad == 0 ? '9' : '50').'</button>';
@ -424,8 +635,18 @@ while ($i < count($arrayOfValidPaymentModes)) {
$i = $i + 1;
}
$keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"];
if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) {
$keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"];
print '<span id="StripeTerminal"></span>';
if (!empty($conf->global->$keyforstripeterminalbank)) {
} else {
$langs->loadLangs(array("errors", "admin"));
//print '<button type="button" class="calcbutton2 disabled" title="'.$langs->trans("SetupNotComplete").'">TerminalOff</button>';
}
}
if ($conf->global->TAKEPOS_ENABLE_SUMUP) {
$keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"];
if (!empty($conf->global->$keyforsumupbank)) {
print '<button type="button" class="calcbutton2" onclick="ValidateSumup();">Sumup</button>';
} else {

View File

@ -259,7 +259,7 @@ $fuserstatic = new User($db);
$form = new Form($db);
$formfile = new FormFile($db);
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewGroup"), '', 'object_group');
dol_set_focus('#nom');

View File

@ -272,7 +272,7 @@ if ($result > 0) {
print '</tr>';
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
// $listofemails=$object->thirdparty_and_contact_email_array();
if ($object->email) {
$actions = array();

View File

@ -158,7 +158,7 @@ $help_url = 'EN:Module_Products#Variants';
llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("ProductAttribute")), '', 'object_' . $object->picto);
print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';

View File

@ -608,6 +608,10 @@ class ProductCombination
$prodcomb2val = new ProductCombination2ValuePair($this->db);
$prodcomb = new ProductCombination($this->db);
$features = array_filter($features, function ($v) {
return !empty($v);
});
foreach ($features as $attr => $attr_val) {
$actual_comp[$attr] = $attr_val;
}

View File

@ -240,7 +240,7 @@ llxHeader('', $title, $help_url);
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
if (empty($permissiontoadd)) {
accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1);
exit;

View File

@ -118,7 +118,7 @@ $formfile = new FormFile($db);
llxHeader('', 'WebsiteAccount', '');
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("WebsiteAccount")));
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';

View File

@ -186,7 +186,7 @@ llxHeader('', $title, $help_url);
<?php
// Part to create
if ($action == 'create' || (empty($action) && empty($id))) {
if ($action == 'create') {
print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Workstation")), '', 'object_'.$object->picto);
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';