Version imprimable du sujet

Cliquez ici pour voir ce sujet dans son format original

Forum osCommerce-fr _ Echanges développeurs _ Enregistrer la commande dans la BDD avant le paiement

Écrit par : feydaykyn 2 Nov 2010, 11:33

Bonjour à tous,

comme pas mal de monde, j'ai des problèmes avec l'enregistrement des commandes qui ne se font pas... J'ai installé OrderCheck, mais cette contribution ne règle pas tous les problèmes, tout en amenant de nombreuses exceptions et des trous dans les numéros de commande (horrible pour la compta).
Du coup je me demande si ce ne serait pas une bonne idée de modifier directement le fonctionnement d'OSCommerce et faire en sorte que l'enregistrement des commandes se fasse avant le paiement, au moment où le client clique sur "confirmer la commande". Si celui-ci a bien lieu ensuite, la commande est marquée comme validée, sinon elle est marquée comme annulée.

Est-ce que cela vous semble une bonne idée ?

Merci !
Nathan

Écrit par : titi02330 13 Nov 2010, 00:55

Salut,

Je suis d'accord avec toi, j'ai des soucis avec CMCIC qui des fois me renvoi des commandes vides, j'arrive à retrouver le client avec son panier dans la BDD mais c'est super galère et puis heureusement je ne n'ai pas beaucoup de clients sinon j'imagine même pas !

Je te soutiens à fond feydaykyn !

Lecteurs de ce post, dites le si vous trouvez que c'est une bonne idée !!!

Écrit par : chti_poupon 13 Nov 2010, 09:57

smile.gif Bonjour !
Pour mon compte, j'ai installé recover cart sales qui permet de voir tous les paniers abandonnés pour une raison ou pour une autre, (pour un prospect identifié) d'expédier un mail de relance et de suivre ses achats ultérieurs.
Tous les paniers abandonnés ne le sont pas pour un retour CB non effectué et on risque de tomber de Charybde en Scylla en sauvegardant des paniers dont on n'est pas sûr que le client avait vraiment la volonté d'acheter ou autre chose (test, concurrence, bobonne contre, pas de sous...). Là encore il faudra se renseigner auprès du client.

Ce qui me semblerait positif à faire, c'est l'information que les banques ne font guère sur 3Dsecure que nos clients aient l'épais dossier d'identification sous la main avant de se connecter (au CIC: carte de clés +portable+CB bien sûr).
Il faudrait un tableau - à jour - de ce que demandent chaque banque.
En fouinant dans GG j'ai trouvé une telle page chez zzzz mais elle est déjà obsolète.

Une Belle journée à vous !
Chti poupon

Écrit par : dvf 13 Nov 2010, 11:48

alors le problème du panier vide est assez simple à réglé

Il s 'agit d 'un problème de session.

20 Min sous osc , par défaut, du coup , sur le cic/cmcic , ils ont 45 min exactement.

Si le mec va pisser , faire son café , prendre sa douche et revient valider sa cb ben la banque prend les sous tongue.gif

mais toi tu est out car la session est détruite


dans le fichier include/functions/sessions.php

tu modif ce champs tout au début du fichier


par sa

Code
  if (STORE_SESSIONS == 'mysql') {
    if (defined('DIR_WS_ADMIN')) {
      if (!$SESS_LIFE = (SESSION_TIMEOUT_ADMIN + 900)) {
        $SESS_LIFE = (SESSION_TIMEOUT_ADMIN + 900);
      }
    } else {
    //  if (!$SESS_LIFE = get_cfg_var('session.gc_maxlifetime')) {
        $SESS_LIFE = 3600;
     // }
    }



voilà soucis réglé wink.gif

par défault c 'est 24 min

hors... on sait que la banque c 'est 45 min

dont trop chiant , trop court !

Écrit par : chti_poupon 13 Nov 2010, 12:53

smile.gif Bonjour !
Certes, j'adopte ta modification et te remercie de ton info sur CMCIC.
Mais, quand je recherche les courriels:

Citation
CM-CIC paiement : Reference : 0000000xxxxx - Etat : REFUSEE

je relève les heures des courriels et j'ai, sous la même référence :
18:34 et 18:32
16:04, 16:06, 16:10
13:49, 13:52
Ce n'est pas seulement un problème de "petit coin". Et quand on leur prend la CB par téléphone, on peut causer et les clients ne sont visiblement pas informés.
arrow.gif Je maintiens mon désir de page information "grand public". Quelqu'un en connait une ?
Une belle journée ! cool.gif
Chti Poupon

Écrit par : dvf 13 Nov 2010, 13:22

là tu parles du 3d et de la difficulté

surtout par exemple

CIC/Cmic

tu doit avoir ta clefs (carte) + email avec un code !

J'ai 3 solutions de paiements sur mon site

BNP
Cmcic
paypal

pour celà que je connais ton problème.

je l'ai résolu avec la BNP mercanet en supprimant le 3ds...

y a moyen de le faire au cmcic je pense , il faut insister auprès du commercial , et dire sinon , je vire le système et je vais à la concurrence

sachant que sans 3d , je me suis prit fraude pour un motant assez significatif et donc , faut faire son calcul !

il ne toucherons plus leur comm à 1% ^^


Écrit par : dvf 13 Nov 2010, 13:25

http://www.bnpparibas.net/banque/portail/particulier/Fiche?type=folder&identifiant=Securisez_vos_paiements_sur_Internet_20080618122128
https://www.creditmutuel.fr/cmcee/fr/banques/professionnels/quotidien/optimiser-vos-encaissements/3d-secure.html
https://particuliers.societegenerale.fr/votre_site/configuration_securite/paiements_securises.html
http://www.caisse-epargne.fr/evo-authentification-cb.aspx
https://e.lcl.fr/quotidien/epargne-et-placements/devenir-client/devenir-client/cartes/3d-secure/
http://www.bpbfc.banquepopulaire.fr/pg3r0i2058_3D_Secure__s%C3%83%C2%A9curisation_de_vos_achats_sur_Internet.html

Écrit par : Gnidhal 13 Nov 2010, 16:10

Faut pas mélanger les sujets et les buts.
le 3DS est une sécurité bancaire qui a ses avantages et travers. Le mode de validation 3DS est propre à chaque client en fonction de sa banque et des options qu'il a choisi. Au CM on peut virer une partie du 3DS et on doit simplement saisir sa date de naissance en complément mais c'est coté client. Dans d'autres banques on peut aussi désactiver le contrôle 3DS coté client. On prend alors le risque des débits indus sur piratage de sa CB.
Le commerçant peut de son coté demander à sa banque de supprimer le 3DS sur son compte commerçant, avec les risques d'impayés que ça comporte.*
Ce paramètre 3DS n'a que peu de rapport avec la question initiale.

Pour répondre à la question initiale :
Allonger la durée de session à 45mn est une rustine qui ne résout pas tout. Cela vaut pour les quelques cas de timeout et uniquement pour certains modules.
Avec un paiement via Atos, la session coté banque ne se ferme pas il me semble: tant que la fenêtre du navigateur reste sur la page de paiement (il me semble que c'est ce que m'a confié un tech. de la hot-line Atos Crédit Mutuel) on peut payer la somme indiquée. Donc le timeout de 45mn sera insuffisant.

Pré enregistrer la commande est une possibilité (qui d'ailleurs peut se faire en adaptant les scripts d'ordercheck) mais ça ne changera pas grand chose aux trous de commandes. Il y aura simplement des dizaines de commandes annulées ce qui risque de poser un problème avec la gestion des stocks.
En effet, ceux qui gèrent les stocks en réel se trouvent face à un problème pour les commandes par chèque : si le chèque n'arrive pas, le stock reste décompté tant que le contenu de la commande n'a pas été remis en stock.
Pas trop grave car les paiements par chèque sont rares. Plus délicat avec les ratés ou les essais de paiement par CB : à quel moment faut-il décompter le stock ? Au traitement de la commande ou à la prise de commande ?
Ceux qui connaissent le fonctionnement des autres solutions de commerce en ligne sur ce point (presta_ et magen_) pourraient peut-être nous éclairer ?

J'entrevois une possibilité qui serait de gérer une table "stock" qui contiendrait les deux champs : stock selon commandes en cours, stock selon commandes expédiées pour chaque produit. Mais pour bien faire il faudrait aussi tracer les commandes qui sont responsables du delta de stock...
C'est pas un petit chantier en somme wink.gif

Écrit par : Havock 15 Nov 2010, 10:47

Citation
J'entrevois une possibilité qui serait de gérer une table "stock" qui contiendrait les deux champs : stock selon commandes en cours, stock selon commandes expédiées pour chaque produit. Mais pour bien faire il faudrait aussi tracer les commandes qui sont responsables du delta de stock...
C'est pas un petit chantier en somme


On s'éloigne un peu du sujet, mais pour partager mon expérience sur les stocks j'ai traité le problème de la façon suivante.

J'ai fait une petite moulinette access qui remonte les stocks réels de mes produits de Sage vers oscommerce.

Je distingue les produits en déstockage (qui ne seront donc plus disponibles une fois que tous ceux en stock seront vendus) et les autres produits.

Pour les produits qui ne sont pas en déstockage, je déduit du stock Sage importé les quantité correspondants aux commandes en attentes payées (par cb, paypal et chèques reçus) et j'indique ces quantités corrigées comme stock sur le site. Ce stock est sur-estimé car il ne prends pas en compte les commandes par chèque dont le chèque n'a pas encore été reçu, mais ce n'est pas trop gênant tant que le temps de réapprovisionnement par mes fournisseurs est faible.

Pour les produits en destockage, je déduit du stock Sage importé les quantité correspondants aux commandes en attentes payées (par cb, paypal et chèques reçus) ainsi que celles correspondant aux commandes par chèque non encore reçus (mais passés depuis moins de 30 jours). Le stock est sous-estimé, mais cela évite d'avoir des problème d'indisponibilité si les clients mettent du temps à envoyer leur chèque.

P.S. : On pourrait peut-être créer un sujet séparé pour partager nos avis et expérience sur le traitement des stocks ?

Écrit par : brouillard 15 Nov 2010, 16:07

J'ai eu le même problème, je l'ai résolu "en partie" , j'ai changé le classement des clients dans customers.php
pour afficher le dénier inscrit comme ceci :

CODE

$search = '';
if (isset($HTTP_GET_VARS['search']) && tep_not_null($HTTP_GET_VARS['search'])) {
$keywords = tep_db_input(tep_db_prepare_input($HTTP_GET_VARS['search']));
$search = "where c.customers_lastname like '%" . $keywords . "%'
or c.customers_firstname like '%" . $keywords . "%'
or c.customers_email_address like '%" . $keywords . "%'
or c.customers_id like '%" . $keywords . "%'";
}

$customers_query_raw = "select c.customers_id, c.customers_lastname, c.customers_firstname, c.customers_email_address, a.entry_country_id
from " . TABLE_CUSTOMERS . " c left join " . TABLE_ADDRESS_BOOK . " a on c.customers_id = a.customers_id
and c.customers_default_address_id = a.address_book_id " . $search . "
order by c.customers_id desc;


j'ai affiché le panier du client en dessous de sa fiche :
CODE

<td width="25%" valign="top"><table>

<?php

//############## panier client - valider la commande ##########################
//##### Pour les paiements par Carte Bancaire encaissées mais pas enregistrées ############
$heading = array();
$contents = array();

//remplire $shoppingCart->contents
$index_panier = 0;
$products_query = tep_db_query("select products_id, customers_basket_quantity from " .
TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$cInfo->customers_id . "'");
while ($panier_products = tep_db_fetch_array($products_query)) {
$shoppingCart->contents[$panier_products['products_id']] = array('qty' =>
$panier_products['customers_basket_quantity']);

//attributes
list($products_id, $options_id1, $options_values_id1, $options_id2, $options_values_id2) = preg_split("/[\{\}]/",
$panier_products['products_id']);

$options_id = array($options_id1, $options_id2);
$options_values_id = array($options_values_id1, $options_values_id2);

for ($j = 0, $n = sizeof($panier_products); $j < $n; $j++) {
$shoppingCart->contents[$panier_products['products_id']]['attributes'][$options_id[$j]] = $options_values_id[$j];
}

$index_panier++;
}
if (isset($cInfo) && is_object($cInfo) && $index_panier != "") {
$heading[] = array('text' => '<b>' . TABLE_HEADING_SHOPPING_CART . ' ' . $cInfo->customers_firstname . ' ' .
$cInfo->customers_lastname . '</b>');
$contents = array('form' => tep_draw_form('customers', FILENAME_CUSTOMERS,
tep_get_all_get_params(array('cID', 'action')) . 'cID=' . $cInfo->customers_id . '&action=validercmd'));

$products = $shoppingCart->get_products();
for ($i = 0, $n = sizeof($products); $i < $n; $i++) {
$contents[] = array('text' => $products[$i]['quantity'] . ' x ' . $products[$i]['name']);
}

if (sizeof($products) > 0) {
$contents[] = array('text' => tep_draw_separator('pixel_black.gif', '100%', '1'));
$contents[] = array('align' => 'right', 'text' => '<b>' . TEXT_SHOPPING_CART_SUBTOTAL . ' ' .
$currencies->format($shoppingCart->show_total(), true) . '</b>');
$contents[] = array('align' => 'right', 'text' => TEXT_SHOPPING_CART_WEIGHT . ' ' .
number_format($shoppingCart->show_weight(), 2, ',', '') . TEXT_WEIGHT);
} else {
$contents[] = array('text' => '&nbsp;');
}

$contents[] = array('align' => 'right', 'text' => TEXT_SHIPPING_COST . ' ' . tep_draw_input_field('fdp', '', 'size="5"'));

$address = (tep_address_label((int)$cInfo->customers_id, true, ' ', '<br>'));
$contents[] = array('text' => tep_draw_separator('pixel_black.gif', '100%', '1'));
$contents[] = array('text' => TABLE_HEADING_ADDRESS_BOOK_ENTRIES);
$contents[] = array('text' => tep_draw_separator('pixel_black.gif', '100%', '1'));
for ($i = 0, $n = sizeof($address); $i < $n; $i++) {
$contents[] = array('text' => tep_draw_radio_field('address_shipping', $address[$i]['address_book_id'], false) .
$address[$i]['firstname'] . ' ' . $address[$i]['lastname']);
$contents[] = array('text' => $address[$i]['postcode'] . ' ' . $address[$i]['city'] .
tep_draw_hidden_field('address_invoice[]', $address[$i]['address_book_id'], ''));
}

$contents[] = array('align' => 'center', 'text' => '<br>' . tep_image_submit('button_confirm.gif', IMAGE_COMFIRM));
}

if ( (tep_not_null($heading)) && (tep_not_null($contents)) ) {
echo ' <tr><td width="25%" valign="top">' . "\n";

$box = new box;
echo $box->infoBox($heading, $contents);

echo ' </td></tr>' . "\n";
}
//############## Fin panier client - valider commande ##########################
?>

<tr>

<?php
//############## Fiche client ##########################
$check_numberof_orders= tep_db_query("select count(orders_id) as total_ord from " . TABLE_ORDERS . " where
customers_id = '" . (int)$cInfo->customers_id . "'");
$getit = tep_db_fetch_array($check_numberof_orders);
$all_orders = $getit['total_ord'];

$heading = array();
$contents = array();

switch ($action) {
case 'confirm':
$heading[] = array('text' => '<b>' . TEXT_INFO_HEADING_DELETE_CUSTOMER . '</b>');

$contents = array('form' => tep_draw_form('customers', FILENAME_CUSTOMERS, tep_get_all_get_params(array('cID',
'action')) . 'cID=' . $cInfo->customers_id . '&action=deleteconfirm'));
$contents[] = array('text' => TEXT_DELETE_INTRO . '<br><br><b>' . $cInfo->customers_firstname . ' ' .
$cInfo->customers_lastname . '</b>');
if (isset($cInfo->number_of_reviews) && ($cInfo->number_of_reviews) > 0) $contents[] = array('text' => '<br>' .
tep_draw_checkbox_field('delete_reviews', 'on', true) . ' ' . sprintf(TEXT_DELETE_REVIEWS, $cInfo->number_of_reviews));
$contents[] = array('align' => 'center', 'text' => '<br>' . tep_image_submit('button_delete.gif', IMAGE_DELETE) . ' <a
href="' . tep_href_link(FILENAME_CUSTOMERS, tep_get_all_get_params(array('cID', 'action')) . 'cID=' .
$cInfo->customers_id) . '">' . tep_image_button('button_cancel.gif', IMAGE_CANCEL) . '</a>');
break;
default:
if (isset($cInfo) && is_object($cInfo)) {
$heading[] = array('text' => '<b>' . $cInfo->customers_firstname . ' ' . $cInfo->customers_lastname . '</b>');

$contents[] = array('align' => 'center', 'text' => '<a href="' . tep_href_link(FILENAME_CUSTOMERS,
tep_get_all_get_params(array('cID', 'action')) . 'cID=' . $cInfo->customers_id . '&action=edit') . '">' .
tep_image_button('button_edit.gif', IMAGE_EDIT) . '</a> <a href="' . tep_href_link(FILENAME_CUSTOMERS,
tep_get_all_get_params(array('cID', 'action')) . 'cID=' . $cInfo->customers_id . '&action=confirm') . '">' .
tep_image_button('button_delete.gif', IMAGE_DELETE) . '</a> <a href="' . tep_href_link(FILENAME_ORDERS, 'cID=' .
$cInfo->customers_id) . '">' . tep_image_button('button_orders.gif', IMAGE_ORDERS) . '</a> <a href="' .
tep_href_link(FILENAME_MAIL, 'selected_box=tools&customer=' . $cInfo->customers_email_address) . '">' .
tep_image_button('button_email.gif', IMAGE_EMAIL) . '</a>');
$contents[] = array('text' => '<br>' . TEXT_DATE_ACCOUNT_CREATED . ' ' .
tep_date_short($cInfo->date_account_created));
$contents[] = array('text' => '<br>' . TEXT_DATE_ACCOUNT_LAST_MODIFIED . ' ' .
tep_date_short($cInfo->date_account_last_modified));
$contents[] = array('text' => '<br>' . TEXT_INFO_DATE_LAST_LOGON . ' ' .
tep_date_short($cInfo->date_last_logon));
$contents[] = array('text' => '<br>' . TEXT_INFO_NUMBER_OF_LOGONS . ' ' . $cInfo->number_of_logons);
$contents[] = array('text' => '<br>' . TEXT_INFO_COUNTRY . ' ' . $cInfo->countries_name);
$contents[] = array('text' => '<br>' . TEXT_INFO_NUMBER_OF_REVIEWS . ' ' . $cInfo->number_of_reviews);
$contents[] = array('text' => '<br>' . TEXT_INFO_NUMBER_OF_ORDERS . ' : ' . $all_orders);
}
break;
}

if ( (tep_not_null($heading)) && (tep_not_null($contents)) ) {
echo ' <td width="25%" valign="top">' . "\n";

$box = new box;
echo $box->infoBox($heading, $contents);

echo ' </td>' . "\n";
}
//############## fin fiche client ##########################

?>
</tr>

</table>
</td>


et après la case 'deleteconfirm': j'ai traite l'enregistrement de la commande il reste à mettre à jour de
final_price après l'enregistrement des options attributes et gérer le stock
CODE

//############## Panier client - valider commande ##########################
case 'validercmd':

$index_panier = 0;
$products_query = tep_db_query("select products_id, customers_basket_quantity from " .
TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$HTTP_GET_VARS['cID'] . "'");
while ($panier_products = tep_db_fetch_array($products_query)) {
$shoppingCart->contents[$panier_products['products_id']] = array('qty' =>
$panier_products['customers_basket_quantity']);

//attributes
list($products_id1, $options_id1, $options_values_id1, $options_id2, $options_values_id2) = preg_split("/[\{\}]/",
$panier_products['products_id']);

$produits[] = array('id' => $products_id1, 'attributes' => array( array('options_id' => $options_id1,
'options_values_id' => $options_values_id1), array('options_id' => $options_id2, 'options_values_id' =>
$options_values_id2)));

$index_panier++;
}

$customer_id = tep_db_prepare_input($HTTP_GET_VARS['cID']);
$fdp = tep_db_prepare_input($HTTP_POST_VARS['fdp']);
$address_invoice = tep_db_prepare_input($HTTP_POST_VARS['address_invoice']);
$address_shipping = tep_db_prepare_input($HTTP_POST_VARS[address_shipping]);

if ($address_shipping == "" || $fdp == "") {

$messageStack->add_session(WARNING_ORDER_NOT_UPDATED, 'warning');

} else {
//insertion de la commande dans la table ORDERS
$customer_billing_address_query = tep_db_query("select c.customers_firstname, c.customers_lastname,
c.customers_telephone, c.customers_email_address, ab.entry_company, ab.entry_street_address, ab.entry_suburb,
ab.entry_postcode, ab.entry_city, ab.entry_zone_id, z.zone_name, co.countries_id, co.countries_name,
co.countries_iso_code_2, co.countries_iso_code_3, co.address_format_id, ab.entry_state
from " . TABLE_CUSTOMERS . " c, " . TABLE_ADDRESS_BOOK . " ab left join " . TABLE_ZONES . " z on (ab.entry_zone_id = z.zone_id)
left join " . TABLE_COUNTRIES . " co on (ab.entry_country_id = co.countries_id) where c.customers_id = '" . (int)$customer_id . "' and ab.customers_id = '" . (int)$customer_id . "' and c.customers_default_address_id = ab.address_book_id");

$customer_billing_address = tep_db_fetch_array($customer_billing_address_query);

$shipping_address_query = tep_db_query("select ab.entry_firstname, ab.entry_lastname, ab.entry_company,
ab.entry_street_address, ab.entry_suburb, ab.entry_postcode, ab.entry_city, ab.entry_zone_id, z.zone_name,
ab.entry_country_id, c.countries_id, c.countries_name, c.countries_iso_code_2, c.countries_iso_code_3,
c.address_format_id, ab.entry_state from " . TABLE_ADDRESS_BOOK . " ab
left join " . TABLE_ZONES . " z on (ab.entry_zone_id = z.zone_id) left join " . TABLE_COUNTRIES . " c on (ab.entry_country_id = c.countries_id) where ab.customers_id = '" . (int)$customer_id . "' and ab.address_book_id = '" .
(int)$address_shipping . "'");

$shipping_address = tep_db_fetch_array($shipping_address_query);

$sql_data_array = array('customers_id' => $customer_id,
'customers_name' => $customer_billing_address['customers_firstname'] . ' ' .
$customer_billing_address['customers_lastname'],
'customers_company' => $customer_billing_address['entry_company'],
'customers_street_address' => $customer_billing_address['entry_street_address'],
'customers_suburb' => $customer_billing_address['entry_suburb'],
'customers_city' => $customer_billing_address['entry_city'],
'customers_postcode' => $customer_billing_address['entry_postcode'],
'customers_state' => $customer_billing_address['entry_state'],
'customers_country' => $customer_billing_address['countries_name'],
'customers_telephone' => $customer_billing_address['customers_telephone'],
'customers_email_address' => $customer_billing_address['customers_email_address'],
'customers_address_format_id' => $customer_billing_address['address_format_id'],
'delivery_name' => $shipping_address['entry_firstname'] . ' ' . $shipping_address['entry_lastname'],
'delivery_company' => $shipping_address['entry_company'],
'delivery_street_address' => $shipping_address['entry_street_address'],
'delivery_suburb' => $shipping_address['entry_suburb'],
'delivery_city' => $shipping_address['entry_city'],
'delivery_postcode' => $shipping_address['entry_postcode'],
'delivery_state' => $shipping_address['entry_state'],
'delivery_country' => $shipping_address['countries_name'],
'delivery_address_format_id' => $shipping_address['address_format_id'],
'billing_name' => $customer_billing_address['customers_firstname'] . ' ' .
$customer_billing_address['customers_lastname'],
'billing_company' => $customer_billing_address['entry_company'],
'billing_street_address' => $customer_billing_address['entry_street_address'],
'billing_suburb' => $customer_billing_address['entry_suburb'],
'billing_city' => $customer_billing_address['entry_city'],
'billing_postcode' => $customer_billing_address['entry_postcode'],
'billing_state' => $customer_billing_address['entry_state'],
'billing_country' => $customer_billing_address['countries_name'],
'billing_address_format_id' => $customer_billing_address['address_format_id'],
'payment_method' => ENTRY_SHOPPING_CART,
'cc_type' => ENTRY_SHOPPING_CART,
'cc_owner' => '',
'cc_number' => '',
'cc_expires' => '',
'date_purchased' => 'now()',
'orders_status' => 1,
'currency' => DEFAULT_CURRENCY,
'currency_value' => $currencies->get_value(DEFAULT_CURRENCY));
tep_db_perform(TABLE_ORDERS, $sql_data_array);
$orders_id = tep_db_insert_id();

//insertion des produits dans la table ORDERS_PRODUCTS
$products = $shoppingCart->get_products();
for ($i = 0, $n = sizeof($products); $i < $n; $i++) {
$sql_data_array = array('orders_id' => (int)$orders_id,
'products_id' => (int)$products[$i]['id'],
'products_model' => $products[$i]['model'],
'products_name' => $products[$i]['name'],
'products_price' => (float)$products[$i]['price'],
'final_price' => (float)$products[$i]['final_price'],
'products_tax' => (float)(tep_get_tax_rate($products[$i]['tax_class_id'])),
'products_quantity' => (int)$products[$i]['quantity']);
tep_db_perform(TABLE_ORDERS_PRODUCTS, $sql_data_array);
$order_products_id = tep_db_insert_id();

//insertion des attributs dans la table ORDERS_PRODUCTS_ATTRIBUTES
for($j = 0; $j < sizeof($produits[$i]['attributes']); $j++) {
$attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name,
pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " .
TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" .
(int)$products[$i]['id'] . "' and pa.options_id = '" . $produits[$i]['attributes'][$j]['options_id'] . "' and pa.options_id =
popt.products_options_id and pa.options_values_id = '" . $produits[$i]['attributes'][$j]['options_values_id'] . "' and
pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and
poval.language_id = '" . $languages_id . "'");
$attributes_values = tep_db_fetch_array($attributes);

$sql_data_array = array('orders_id' => $orders_id,
'orders_products_id' => $order_products_id,
'products_options' => $attributes_values['products_options_name'],
'products_options_values' => $attributes_values['products_options_values_name'],
'options_values_price' => $attributes_values['options_values_price'],
'price_prefix' => $attributes_values['price_prefix']);
tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array);
}

$products_ordered .= $products[$i]['quantity'] . ' x ' . $products[$i]['name'] . ' (' . $products[$i]['model'] . ') = ' . $currencies->display_price($products[$i]['final_price'], tep_get_tax_rate($products[$i]['tax_class_id']), $products[$i]['quantity']) . "\n <br>";

} //for produits

//sous_total ...........................
$sort_order_soustotal_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_title = 'Ordre de tri' and configuration_key = 'MODULE_ORDER_TOTAL_SUBTOTAL_SORT_ORDER'");

while($soustotal_sort_order = tep_db_fetch_array($sort_order_soustotal_query)) {
$sql_data_array = array('orders_id' => $orders_id,
'title' => TEXT_SHOPPING_CART_SUBTOTAL,
'text' => $currencies->format($shoppingCart->show_total(), true),
'value' => (float)$shoppingCart->show_total(),
'class' => 'ot_subtotal',
'sort_order' => $soustotal_sort_order['configuration_value']);

tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
}

//fdp ..................................
$sort_order_fdp_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_title = 'Ordre de tri' and configuration_key = 'MODULE_ORDER_TOTAL_SHIPPING_SORT_ORDER'");

while($fdp_sort_order = tep_db_fetch_array($sort_order_fdp_query)) {
$sql_data_array = array('orders_id' => $orders_id,
'title' => TEXT_SHIPPING_COST,
'text' => $currencies->format($fdp, true),
'value' => (float)$fdp,
'class' => 'ot_shipping',
'sort_order' => $fdp_sort_order['configuration_value']);

tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
}

//Tax ..................................
$somme_tax = tep_somme_tax_group($orders_id);

$tax_description[] = $somme_tax[0];
$somme_taxs[] = $somme_tax[1];

$tax_description[] = $somme_tax[2];
$somme_taxs[] = $somme_tax[3];

$tax_description[] = $somme_tax[4];
$somme_taxs[] = $somme_tax[5];

for ($i = 0; $i < sizeof($somme_taxs); $i++) {
if ($tax_description[$i] != "" && $somme_taxs[$i] != 0) {


$sort_order_tax_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_title = 'Ordre de tri' and configuration_key = 'MODULE_ORDER_TOTAL_TAX_SORT_ORDER'");

while($tax_sort_order = tep_db_fetch_array($sort_order_tax_query)) {
$sql_data_array = array('orders_id' => $orders_id,
'title' => $tax_description[$i] . ': ',
'text' => $currencies->format($somme_taxs[$i], true),
'value' => (float)$somme_taxs[$i],
'class' => 'ot_tax',
'sort_order' => $tax_sort_order['configuration_value']);

tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
}
}
}

//total ...........................
$sort_order_total_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_title = 'Ordre de tri' and configuration_key = 'MODULE_ORDER_TOTAL_TOTAL_SORT_ORDER'");

while($total_sort_order = tep_db_fetch_array($sort_order_total_query)) {
$sql_data_array = array('orders_id' => $orders_id,
'title' => TEXT_SHOPPING_CART_TOTAL,
'text' => '<b>' . $currencies->format(($shoppingCart->show_total() + $fdp), true) . '</b>',
'value' => (float)($shoppingCart->show_total() + $fdp),
'class' => 'ot_total',
'sort_order' => $total_sort_order['configuration_value']);

tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
}

//email de confirmation (on a empoché l'argent et t'auras rien pour noël)
$totals_query = tep_db_query("select title, text from " . TABLE_ORDERS_TOTAL . " where orders_total_avoir is null and orders_id = '" . (int)$orders_id . "' order by sort_order");
while ($totals = tep_db_fetch_array($totals_query)) {
$order_totals[] = array('title' => $totals['title'],
'text' => $totals['text']);
}

$email_order = STORE_NAME . "\n <br>" .
EMAIL_SEPARATOR . "\n <br>" .
EMAIL_TEXT_ORDER_NUMBER . ' ' . $orders_id . "\n <br>" .
EMAIL_TEXT_INVOICE_URL . ' ' . HTTP_SERVER . '/' . EMAIL_PAGE_ACCOUNT_HISTORY_INFO . '?order_id=' . $orders_id . "\n <br>" .
EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n <br><br>" . EMAIL_TEXT_PRODUCTS . "\n <br>" .
EMAIL_SEPARATOR . "\n <br>" .
$products_ordered . "\n <br>" .
EMAIL_SEPARATOR . "\n <br>" . $order_totals[0]['title'] . ' ' . $order_totals[0]['text'] . "\n <br>" .
$order_totals[1]['title'] . ' ' . $order_totals[1]['text'] . "\n <br>" . $order_totals[2]['title'] . ' ' . $order_totals[2]['text'] . "\n
<br>" . $order_totals[3]['title'] . ' ' . $order_totals[3]['text'] . "\n <br>" . $order_totals[4]['title'] . ' ' . $order_totals[4]
['text'] . "\n\n <br><br>" .
EMAIL_TEXT_DELIVERY_ADDRESS . "\n <br>" .
EMAIL_SEPARATOR . "\n <br>" . $shipping_address['entry_firstname'] . ' ' .
$shipping_address['entry_lastname'];
if ($shipping_address['entry_company'] != "") $email_order .= "\n <br>" .
$shipping_address['entry_company']; $email_order .= "\n <br>" . $shipping_address['entry_street_address'];
if ($shipping_address['entry_suburb'] != "") $email_order .= "\n <br>" . $shipping_address['entry_suburb']; $email_order .= "\n <br>" . $shipping_address['entry_postcode'] . ' ' . $shipping_address['entry_city'];
if ($shipping_address['entry_state'] != "") $email_order .= "\n <br>" . $shipping_address['entry_state']; $email_order .= "\n <br>" . $shipping_address['countries_name'] . "\n\n <br><br>" .
EMAIL_TEXT_BILLING_ADDRESS . "\n <br>" .
EMAIL_SEPARATOR . "\n <br>" . $customer_billing_address['customers_firstname'] . ' ' .
$customer_billing_address['customers_lastname'];
if ($customer_billing_address['entry_company'] != "") $email_order .= "\n <br>" .
$customer_billing_address['entry_company']; $email_order .= "\n <br>" .
$customer_billing_address['entry_street_address'];
if ($customer_billing_address['entry_suburb'] != "") $email_order .= "\n <br>" .
$customer_billing_address['entry_suburb']; $email_order .= "\n <br>" . $customer_billing_address['entry_postcode'] . ' '
. $customer_billing_address['entry_city'];
if ($customer_billing_address['entry_state'] != "") $email_order .= "\n <br>" .
$customer_billing_address['entry_state']; $email_order .= "\n <br>" . $customer_billing_address['countries_name'] .
"\n\n <br><br>" .
EMAIL_TEXT_PAYMENT_METHOD . "\n <br>" . EMAIL_SEPARATOR . "\n <br>" . ENTRY_SHOPPING_CART .
"\n\n <br><br>";

tep_mail($customer_billing_address['customers_firstname'] . ' ' . $customer_billing_address['customers_lastname'],
$customer_billing_address['customers_email_address'], EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER,
STORE_OWNER_EMAIL_ADDRESS);

tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added,
customer_notified, comments, track_num, track_num2) values ('" . (int)$orders_id . "', '1', now(), '1', ' ', ' ', ' ')");

//vider le panier du client (commencer par brouillard)
tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "'");
tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" .
(int)$customer_id . "'");
}

tep_redirect(tep_href_link(FILENAME_CUSTOMERS, tep_get_all_get_params(array('cID', 'action'))));
break;
//############## Fin panier client - valider commande ########################


j'ai créer une petite fonction dans includes/functions/generale.php pour gérer les taxes, parce que j'ai pas trouvé
comment osc les gère
CODE
//Calculer la somme des taxes par groupe
function tep_somme_tax_group($order_id) {

$index_products = 0;
$orders_products_query = tep_db_query("select products_tax, products_quantity, final_price from " .
TABLE_ORDERS_PRODUCTS . " where orders_id = '" . (int)$order_id . "'");
while ($orders_products = tep_db_fetch_array($orders_products_query))
{
$products[$index_products] = array('qty' => $orders_products['products_quantity'],
'tax' => $orders_products['products_tax'],
'final_price' => $orders_products['final_price']);
$index_products++;
}

$index_tax = 0;
$tax_query = tep_db_query("select tax_rate, tax_description from " . TABLE_TAX_RATES . " order by tax_priority asc");

$tax_rate = array();
$tax_description = array();

while($tax = tep_db_fetch_array($tax_query))
{
array_push($tax_rate, $tax['tax_rate']);
array_push($tax_description, $tax['tax_description']);

$index_tax++;
}

for ($i = 0; $i < $index_products; $i++) {

$products_total_ht[$i] = $products[$i]['final_price'] * $products[$i]['qty'];

//calcule tax01, on supprime les autres taxes
$calcul_tax01[$i][$products[$i]['tax']] = tep_calculate_tax($products_total_ht[$i], $products[$i]['tax']);
unset($calcul_tax01[$i][$tax_rate[1]], $calcul_tax01[$i][$tax_rate[2]]);
$calcul_tax001[$i]= implode(", ", $calcul_tax01[$i]);
$calcul_tax0001[$i] = $calcul_tax001[$i];

//calcule tax02, on supprime les autres taxes
$calcul_tax02[$i][$products[$i]['tax']] = tep_calculate_tax($products_total_ht[$i], $products[$i]['tax']);
unset($calcul_tax02[$i][$tax_rate[0]], $calcul_tax02[$i][$tax_rate[2]]);
$calcul_tax002[$i] = implode(", ", $calcul_tax02[$i]);
$calcul_tax0002[$i] = $calcul_tax002[$i];

//calcule tax03, on supprime les autres taxes
$calcul_tax03[$i][$products[$i]['tax']] = tep_calculate_tax($products_total_ht[$i], $products[$i]['tax']);
unset($calcul_tax03[$i][$tax_rate[0]], $calcul_tax03[$i][$tax_rate[1]]);
$calcul_tax003[$i] = implode(", ", $calcul_tax03[$i]);
$calcul_tax0003[$i] = $calcul_tax003[$i];
}

$somme_tax0001 = array_sum($calcul_tax0001);

$somme_tax0002 = array_sum($calcul_tax0002);

$somme_tax0003 = array_sum($calcul_tax0003);

return array( $tax_description[0], $somme_tax0001, $tax_description[1], $somme_tax0002, $tax_description[2],
$somme_tax0003 );

}

Écrit par : brouillard 15 Nov 2010, 17:18

http://www.imagup.com/data/1289837867.html

Écrit par : Madmaxx 15 Nov 2010, 19:26

Citation (feydaykyn @ 2 Nov 2010, 11:33) *
....................
Du coup je me demande si ce ne serait pas une bonne idée de modifier directement le fonctionnement d'OSCommerce et faire en sorte que l'enregistrement des commandes se fasse avant le paiement, au moment où le client clique sur "confirmer la commande". Si celui-ci a bien lieu ensuite, la commande est marquée comme validée, sinon elle est marquée comme annulée.
..............................

en gros c'est ce que fait déjà ordercheck, sauf que au lieu de marqué comme annulé, la commande n'est pas validé, donc je ne vois pas l'intérêt de réinventer la roue wink.gif une commande est une commande, et une facture est une facture.

ensuite il ne faut pas confondre les numéros de commandes et les numéros de factures, ce n'est pas du tout la même chose, au même titre que les numéros de devis, ils n'ont pas "forcément" besoin d'avoir de relation entre eux.

Citation (Gnidhal @ 13 Nov 2010, 16:10) *
.......................
Plus délicat avec les ratés ou les essais de paiement par CB : à quel moment faut-il décompter le stock ? Au traitement de la commande ou à la prise de commande ?
......................

en ce qui me concerne je décompte du stock au paiement effectif, c'est à dire à la facturation.
tant que l'on a pas de retour de paiement inutile de retirer un produit du stock, si le client abandonne au moment de payer ...


je ne me sers oscommerce pour la facturation et la gestion de mon stock en réel, mais d'ebp, et en trichant avec les versions d'évaluations, je fait mes import pour facturation.
le client au niveau de la boutique (web, car j'ai une boutique physique aussi) peut a tout moment, consulté non pas sa facture, mais sa commande, qui est en tout point identique a la facture (autre que l'aspect et le numéro de commande), et peut s'il le désire me demandé de lui rééditer sa facture.

ensuite que le numéro de commande ne se suive pas, bof pas grave, tout comme mes devis( j'aimerais pourtant smile.gif ) mais pour la compta, toutes mes facture se suivent.

Écrit par : chrysalide 16 Nov 2010, 10:20

les pbs de numérotation, stocks et autres peuvent être facilement réglés car vous n'envisagez le pré-enregistrement des commandes que dans les tables orders.

Imaginons que le client arrive dans la page checkout_confirmation
Vous préenregistrez dans des tables tmp_orders
Le client paye par CB, Atos ou tout mode de paiement demandant au client de sortir du flux.
le client revient sur checkout_success la commande est validée en tables orders et pré-enregistrement est effacé.

Si cela se passe mal la commande est toujours dans les tables tmp_orders avec toutes les données de commandes (mode de paiement, livraison, etc), il ne reste plus qu'a forcer la validation manuellement.

Donc dans les tables orders il n' y a que des commandes validées avec une numérotation continue et un stock mis a jour que lorsque la commande est validé automatiquement ou manuellement.

C'est ça que vous cherchez a faire ?

Écrit par : feydaykyn 22 Nov 2010, 12:00

@MadMaxx et Chrysalide : c'est en effet ce que fait la contribution ordercheck, mais hélas le système n'est pas parfait :

- pour les non-informaticiens qui s'occupent du traitement des commandes, il faut vérifier en permanence s'il n'y a pas des commandes dans ordercheck, et puisque les numéros de commande ne correspondent pas, cela prend du temps et est cause d'erreurs.
- ordercheck a des bugs par moments, qui font qu'on ne peut pas avoir une confiance totale dans cette contribution (avec la 2.5.1 en tout cas)
- les numéros de commande ne correspondent pas à la chronologie réelles des commandes, dans le cas où d'autres commandes sont enregistrées avant que la commande enregistrée dans ordercheck soit transférée dans les tables "normales" (ça fait beaucoup de fois le mot "commande", désolé !)
-> Dans le cas de notre site, ça s'est révélé être un pis-aller, autant techniquement qu'administrativement

Du coup j'ai modifié le système pour que les commandes soient enregistrées avant de partir sur le serveur de paiement. Si cela peut aider quelqu'un, voici quelques détails :
- j'ai modifié checkout_confirmation.php pour qu'il appelle une page que j'ai nommée checkout_mysafeorder.php, qui va se charger d'enregistrer la commande avec le statut "en instance", mais ne touche pas au stock. Techniquement, il y a maintenant ça à la fin de checkout_confirmation :

CODE
// $$$$$$$ BEGIN my_safe_order
$form_action_url = tep_href_link(FILENAME_CHECKOUT_MY_SAFE_ORDER, '', 'SSL');
// $$$$$$$$$ END my_safe_order

echo tep_draw_form('checkout_confirmation', $form_action_url, 'post');
// ################# Added CGV
echo tep_draw_hidden_field('gv_redeem_code', $_POST['gv_redeem_code']);
// ################# End Added CGV

// $$$$$$$ BEGIN my_safe_order
// if (is_array($payment_modules->modules)) {
// echo $payment_modules->process_button();
// }
// $$$$$$$$$ END my_safe_order

if (isset($$payment->form_submit)) {
$form_submit = $$payment->form_submit;
}
else {
$form_submit = tep_image_submit('button_confirm_order.gif', IMAGE_BUTTON_CONFIRM_ORDER);
}

echo $form_submit . '</form>' . "\n";


et à la fin de checkout_mysafeorder :
CODE
if (isset($$payment->form_action_url))
$redirect_link = $$payment->form_action_url;
else
$redirect_link = tep_href_link(FILENAME_CHECKOUT_PROCESS,'insert_id=' . $insert_id);
tep_redirect($redirect_link, '', 'SSL');


- Le client est ensuite redirigé vers le serveur de paiement, qui, en temps normal, appelle ensuite checkout_process.php, qui réduit le stock, envoie le mail de confirmation, etc. Le statut passe à "Traitement en cours".

Cela laisse deux problèmes pour l'instant :
- il faut toujours vérifier à la main si les commandes marquées "en instance" ont été payées, et changer à la main leur statut le cas échéant
- si l'on change le statut d'une commande en "Traitement en cours", il faut mettre à jour le stock à la main.

-> Je ne vois pas de solution au premier problème, et le second sera "résolu" par un gros bouton "mettre à jour le stock".

Écrit par : chrysalide 22 Nov 2010, 12:39

n'oublions pas que orderc check ou les autres contribs du même jus ne sont là que pour gérer l'exception, 2% des commandes au maximum.
tu es en train de te prendre la tête et tout casser pour un truc qui est facilement justifiable en comptabilité.
Pour les non-informaticiens quoi de difficile de prendre 30s par jour pour jeter un coup d'œil dans Ordercheck, c'est pas la peine de camper devant à longueur de journée.
Si par-contre tu as un taux important de non validation de commande il serait bon de vraiment se pencher sur le pb afin de retomber dans la moyenne donnée plus haut.

Écrit par : feydaykyn 22 Nov 2010, 14:28

Je suis d'accord mais je suis en mission temporaire, donc j'ai mis en place la solution la plus transparente et fiable possible pour des non-informaticiens, en attendant de trouver la vraie solution à ces nombreuses commandes qui partent dans la nature.
Par ailleurs la compta tient absolument à une succession chronologique des commandes, ce que ne permet pas ordercheck.
Donc d'accord avec toi dans l'absolu, mais pas dans mon cas précis.

Écrit par : Gnidhal 1 Dec 2010, 10:26

+1 avec Chrysalide
ton "bricodage" est un pis aller qui génèrera des problèmes de stock (comme je l'expliquais au début) sans compter le problème lié aux "commandes" non finalisées qui sont à la fois en backoffice et dans l'espace du client avec un statut "non payée" qui laisse croire au client qu'il a effectuée une commande.
Par ailleurs si tu a fait comme tu présentes le cas, le client doit repasser sa commande et la payer correctement pour vider son panier. Ce qui génère 2 commandes identiques : 1 payée à traiter, une ou plusieurs précédentes (selon le nombre d'essais de paiement) non payées à annuler.

Il me parait plus évident de faire comprendre aux "non informaticiens" qu'ils travaillent avec un outil informatique qui a ses contraintes et que le "N° de commande" généré par la boutique est en fait un "ticket de caisse" qui n'a rien à voir avec le N° de commande réel.

La compta doit pouvoir intégrer ce système de double numérotation : une numérotation incrémentielle auto qui peut comporter des "trous" et une numérotation réelle qui est parfaitement suivie sans aucun manque de manière chronologique.

Pour résoudre le problème tel que tu le présentes, il me parait plus judicieux de générer un n° de commande parfaitement chronologique au moment du traitement de celle-ci, laissant le "orders_id" à sa place de numéro auto en bdd. (une numérotation totalement informatique étanche à toute compréhension de "non informaticien")

Par ailleurs, la contribution orders_check présente un seul vrai problème de ce coté, c'est le système de voyant (rouge/vert) qui devrait indiquer qu'une commande a correctement été finalisée.
Ce système de voyant ne fonctionne pas correctement puisqu'il est basé sur une comparaison via l'id de commande (qui ne se synchronise pas correctement). Or il faudrait faire la comparaison sur le contenu de la commande complet (nom client, adresses, contenu, total, etc.)

Écrit par : titi02330 10 Dec 2010, 21:27

Bonsoir à toutes et tous,

Pourquoi se prendre la tête avec ordercheck alors qu'on pourrait se la prendre avec PayPal IPN ?!? happy.gif

En somme, PayPal IPN fait exactement ce qu'on recherche tous :
Soit le client finalise et la commande passe en "attente"
Soit le client ne finalise pas ou il y a un problème et la commande reste en "att. Paiement" ce qui permettrait de soit récupérer la commande soit de relancer le client pour qu'il paye (ça marche sur 10% environ... wink.gif )

Le véritable problème c'est les modules bancaires tous autant qu'ils sont, et pour autant que je sache il ont tous le même fonctionnement que PayPal IPN :
- le client quitte le site marchand
- se retrouve sur le serveur de paiement
- le serveur de paiement répond (ou non) à la place du client pour éviter les "pas de retour client après paiement"

L'idée serait donc de savoir comment PP (j'en ai marre de mettre PayPal IPN à chaque fois...) fait pour pré-enregistrer la commande, pour le retour on s'en fiche puisque c'est déjà géré.

Et pour le stock : PP débite si validée et ne débite pas si elle reste en att. Paiement


Voilà ma pensée, donc vaudrait peut être mieux se baser sur PP plutôt que Ordercheck, non ?

Qu'en pensez vous ?

Yann.

Écrit par : Gnidhal 10 Dec 2010, 22:06

Excellente idée, Yapluka smile.gif
Reste toujours le problème du stock.
Il faudrait rédiger une contrib similaire et renvoyer le retour banque vers une page comme celle de PPipn.
Cela dit, PP traite les commandes d'une manière encore plus avancée. Le serveur renvoie bien plus d'infos que la simple validation, car si le paiement est annulé, la commande PP se trouve dans un statut "non payable"
D'ailleurs il n'y a pas que paypal qui utilise cette méthode, le module Fianet fait de même (avec des tas de possibilités supplémentaires)

Écrit par : brouillard 11 Dec 2010, 14:50

Si on enregistre la commande avant le paiement par carte bancaire on ne peut pas savoir si le paiement est validé ou a échoué, le mieux c'est de vérifier les paiement du jour sur la plateforme ATOS avec les commande dans l'Admin.

Voici un contrib qui vous permet d'enregistrer les commandes non-enregistrées avec une seul clic dans l'Admin

http://addons.oscommerce.com/info/7674

Écrit par : titi02330 11 Dec 2010, 16:07

Bonjour a toutes et tous,

gnidhal : pour le "non payable" on n'en a pas besoin... C'est juste pour éviter les doublons, mais si tu as une commande en attente de paiement et une deuxième payée a toi de mettre la première en annulé.

Pour Fianet je ne sais pas grand chose, je viens seulement de renvoyer le contrat... (petite question a part :Gnidhal, tu as Fianet ?)

Dans mon message je disais que le stock du coup était géré si tu fais le décompte du stock sur la page de retour du serveur comme paypal, ou alors c'est que j'ai loupé une etape qui soulevait un autre problème.

Ce qui m'ennuie c'est que je n'ai aucune idée de comment faire tout ça car je ne suis qu'un simple bricoleur de code...

Penses tu que ce soit dur a faire ?

Osc 3 n'a pas ça de prévu ?
Ça serait plus facile a récupérer... Si les developpeurs nous y donne accès.

Brouillard : cette contribution a l'air sympa mais enregistre t-elle les commandes automatiquement ?
L'as tu installé ? Si oui peux tu nous en dire plus ?

Yann.

EDIT : brouillard : il suffit d'utiliser deux statuts de commande comme paypal, après rien ne t'empêche de vérifier les commandes manuellement pour eviter les surprises eventuelles.

Écrit par : Phocea 13 Dec 2010, 10:18

Pour ma part je trouve que order check est amplement suffisant. Suffit de faire attention aux emails recu des banques.
Le pb de 3DS ne me touche plus depuis que SPPLUS me l'a viré. Par contre ce sont des branquignoles car il y a toujours les memes bugs que 2 ans en arrière sur leurs plateforme.

Le seul défaut que je trouverai pour order_check soit la non transparence de la pré sauvegarde. Il y aurait peut être à faire un appel asynchrone lors de l'appel à la banque, pour éviter de passer par une page intermédiaire.

Et pour apporter de l'eau au moulin voici un bout de code que j'utilise déjà en asynchrone pour d'autre besoin

Code
function async_post($url, $parameters) {

        // Parse the call parameters
    foreach ($parameters as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_parameters[] = $key.'='.urlencode($val);
    }
    $post_string = implode('&', $post_parameters);
        
        // Parse the call URL
    $parsed_url = parse_url($url);

        // Open Socket
    $fp = fsockopen($parsed_url['host'], isset($parsed_url['port'])?$parsed_url['port']:80, $errno, $errstr, 30);

    $out = "POST ".$parsed_url['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parsed_url['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}


Par contre pas de callback et pas du véritable asynchrone car on peut encore faire un timeout sur fsockopen

Écrit par : Jesam 13 Dec 2010, 19:50

J'ai plusieurs clients qui tiennent absolument à conserver cette chronologie dans la numérotation des commandes comme l'indique feydaykyn.

J'ai donc tester la contribution de brouillard Order_Confirm.
Les paniers sont correctement affichés à côtés des clients enregistrés et affichés par ordre d'inscription. Là c'est très bien.

Je me suis constitué un panier. Dans l'admin, je le transforme en commande suivant le process décrit par cette contrib.

Je reçois bien un mail indiquant l'enregistrement de ma commande, la commande rentre bien dans la table orders_products mais non dans orders_status_history ou orders_total. Par contre ce panier apparait toujours dans l'admin (pas d'effacement du panier), il n'apparait pas non plus sur la page admin/index avec toutes les commandes reçues.

De plus à l'enregistrement du panier pour le passer en commande j'ai l'erreur suivante:

1054 - Unknown column 'track_num' in 'field list'

insert into orders_status_history (orders_id, orders_status_id, date_added, customer_notified, comments, track_num, track_num2) values ('1167', '1', now(), '1', ' ', ' ', ' ')

[TEP STOP]

Si brouillard à des idées, ce sera avec plaisir, cette contrib étant super utile.

Écrit par : titi02330 13 Dec 2010, 20:04

Salut,

Rajoute track_num et track_num2 dans ta table orders_statut_history, et ça fonctionnera.

Code
ALTER TABLE `orders_status_history` ADD `track_num` VARCHAR( 20 ) DEFAULT NULL;

cela vient de la contribution TrackingOrders

Puis dis nous si tu rencontres d'autres problèmes stp.

Ciao.

Écrit par : Jesam 13 Dec 2010, 23:22

Suite des manip' sur contribution de brouillard Order_Confirm.

J'ai bien ajouté les 2 champs dans la table orders_status_history, comme indiqué par titi02330, je n'ai plus l'affichage d'erreur quand je clique sur le bouton Confirmer pour passer le panier en commande.

Par contre à l'écran rien n'indique que la manip' s'est bien déroulée.

Enregistrement des infos dans les tables orders, orders_products, à présent en plus dans orders_status_history, mais rien dans orders_total.
Egalement donc toujours rien sur la page admin/index dans la liste des commandes.

De plus le panier reste toujours en panier, il n'y a pas de suppression du panier quand je le passe en commande.

Écrit par : brouillard 14 Dec 2010, 13:20

Citation (Jesam @ 13 Dec 2010, 19:50) *
1) mais non dans orders_status_history ou orders_total. // je m'aperçois que "track_num" fait partie d'un autre contrib
2) Par contre ce panier apparait toujours dans l'admin (pas d'effacement du panier) // oublie de dé-commenter
3) il n'apparait pas non plus sur la page admin/index avec toutes les commandes reçues. //le champ "orders_status"de la table orders n'est pas initialisé "à cause du champs track_num".


De plus à l'enregistrement du panier pour le passer en commande j'ai l'erreur suivante:

1054 - Unknown column 'track_num' in 'field list'

insert into orders_status_history (orders_id, orders_status_id, date_added, customer_notified, comments, track_num, track_num2) values ('1167', '1', now(), '1', ' ', ' ', ' ')

Si brouillard à des idées, ce sera avec plaisir, cette contrib étant super utile.


Bonjour, Durant mes tests j'ai effectivement commenté les 2 lignes pour vider le panier, je me suis aperçue de cela après avoir uploadé le package, je l'ai corrigé et j'espère que cette fois-ci il marchera comme convenu.
Je reste à l'écoute !

1) mais non dans orders_status_history ou orders_total. // je m'aperçois que "track_num" fait partie d'une autre contrib
2) Par contre ce panier apparait toujours dans l'admin (pas d'effacement du panier) // oublie de dé-commenter
3) il n'apparait pas non plus sur la page admin/index avec toutes les commandes reçues. //le champ "orders_status"de la table orders de la commande n'est pas initialisé "à cause du champs track_num".



Pour le track_num, remplace ce code
CODE
tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added,
customer_notified, comments, track_num, track_num2) values ('" . (int)$orders_id . "', '1', now(), '1', ' ', ' ', ' ')");


par celui-ci
CODE

tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added,
customer_notified, comments) values ('" . (int)$orders_id . "', '1', now(), '1', ' ')");


De-commenter ces lignes pour vider le panier
CODE

//vider le panier du client (commencer par brouillard)

tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "'");

tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "'");



J'ai fait une mis à jour de la partie Tax

trouve :

//Tax ..................................

et

//total ...........................


tu supprime tout ce qu'il ce trouve entre ces deux lignes et tu remplace par

CODE
for ($i = 0; $i < sizeof($products); $i++) {

$orders_taxs_query = tep_db_query("select products_tax, sum(final_price*products_tax*products_quantity)/100 as total_tax
from " . TABLE_ORDERS_PRODUCTS . " where products_tax = '" . tep_get_tax_rate($products[$i]['tax_class_id']) . "' and orders_id = '" . (int)$orders_id . "'");
$orders_taxs = tep_db_fetch_array($orders_taxs_query);

$total_tax[] = $orders_taxs['total_tax'];
$tax_somme_group = array_values(array_unique($total_tax));
$products_tax[] = $orders_taxs['products_tax'];
$products_tax_rate = array_values(array_unique($products_tax));
}

for ($i = 0; $i < sizeof($products_tax_rate); $i++) {
$tax_description_query = tep_db_query("select tax_description
from " . TABLE_TAX_RATES . " where tax_rate = '" . $products_tax_rate[$i] . "'");
$tax_description = tep_db_fetch_array($tax_description_query);

$sort_order_tax_query = tep_db_query("select configuration_value
from " . TABLE_CONFIGURATION . " where configuration_title = 'Ordre de tri' and configuration_key = 'MODULE_ORDER_TOTAL_TAX_SORT_ORDER'");
$tax_sort_order = tep_db_fetch_array($sort_order_tax_query);

$sql_data_array = array('orders_id' => $orders_id,
'title' => $tax_description['tax_description'],
'text' => $currencies->format($tax_somme_group[$i], true),
'value' => (float)$tax_somme_group[$i],
'class' => 'ot_tax',
'sort_order' => $tax_sort_order['configuration_value']);
tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
}

Écrit par : Jesam 15 Dec 2010, 15:05

Cela me semble pas mal à présent.
Je retouche un peu la partie envoi du mail d'enregistrement de la commande, puis teste.

Je reviens vous dire si tout est OK.

Écrit par : Gnidhal 8 Feb 2011, 14:37

Ok Jesam, je ne sais pas où tu en es, mais orders_check va bientôt évoluer.

J'ai en effet trouvé un réel problème avec cette contribution au delà du fait qu'elle a un voyant défectueux.
La numérotation des commande est un soucis dès qu'on enregistre un fort trafic des commandes.

Dans ce cas, une commande "sauvée" par orders_check peut ne pas être correctement enregistrée puisqu'il y aura conflit d'id lors de l'enregistrement en table orders par checkout_process
la requête sql est alors bloquée dans le process à cause de la redondance des ID. Le script appelé directement par le serveur de banque est muet et on ne voit pas l'erreur.

J'ai fixé le problème et je vais remettre à plat bientôt une nouvelle contribution.
1/ les voyants marcheront
2/ les commandes correctement enregistrées disparaitront des tables holding_ afin de ménager la bdd
3/ les commandes de plus de 3 mois seront supprimées des tables holding_ dans le même but
4/ je vais essayer de faire en sorte que la numérotation des commandes reste chronologique*

A suivre donc

Écrit par : technologie 1 Mar 2011, 18:12

slt ,
excuse moi , j'ai presque le même soucis.
j'ai fait la mise à jour deux fichiers orders.class et orders d'ou j'ai porté des modifiactions.
il ne m'affiche pas toues les commandes.
en restaurant ces deux fichiers, pareil.
là je suis complètement perdu , je ne sais plus quoi faire.
je suis complément bloqué mais ce commande sont bien dans ma base données.
aidez moi stp.

Écrit par : Johnny124 3 Mar 2011, 13:02

Bonjour Gnidhal,

Peux-tu me dire si tu as réussi à faire les modifications citées plus haut?

Merci.


Écrit par : Gnidhal 4 Mar 2011, 18:59

Citation (Johnny124 @ 3 Mar 2011, 13:02) *
Peux-tu me dire si tu as réussi à faire les modifications citées plus haut?

oui mais pas eu le temps de refaire la contrib'
je vais essayer de faire un brief ici bientôt


Écrit par : Johnny124 4 Mar 2011, 19:24

Super, j'attends patiemment alors. wub.gif


Écrit par : Jesam 31 Aug 2011, 18:04

Après plusieurs voici ma réponse.
Jusqu'à présent je reprenais les commandes non finalisées à la main. Je me suis enfin décidé aujourd'hui à mettre en place la dernière version de la contrib.

J'ai donc téléchargé la version du 28 mars 2011 http://addons.oscommerce.com/info/7674

Pas mal de corrections apportées mais et oui il y a un mais, je n'ai pas d'enregistrement de la commande dans la table orders_total. Tout le reste y est, envoi du mail (pour certains il faudra revoir les é ) l'enregistrement dans la table orders, orders_products et orders_status_history.

J'ai donc du retourner dans la BDD pour compléter à la main la table orders_total. Après cette manip. la commande apparait bien dans l'admin.

Donc encore une retouche à faire.

Et encore bravo à brouillard pour cette contrib

Écrit par : brouillard 31 Aug 2011, 18:17

Donc c'est le total qui ne s'enregistre pas ou toute la commande ?

As-tu rempli le frais d'expédition ? (s'il n'y a pas tu mets 0)

Écrit par : Jesam 12 Sep 2011, 18:37

J'ai bien entré le montant du port dans la cellule prévu pour.

C'est en fait tout les enregistrements dans la table orders_total qui ne se font pas :
8697 2187 Sous-Total: 8,40€ 8.4000 ot_subtotal 1
8698 2187 Envoi postal (Forfait pour frais d'envoi): 4,00€ 4.0000 ot_shipping 2
8699 2187 Dont TVA 19,6%: 1,38€ 1.3766 ot_tax 3
8700 2187 Total: <b>12,40€</b> 12.4000 ot_total 4

CAD les 4 lignes de la commande concernée.

Toutes les autres tables relatives à la commande sont bien renseignées par ton code.

Il y a aussi un pb sur le lien de l'historique envoyé au client, mais là je vais chercher un peu.


Propulsé par Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)