svn commit: r823475 - in /ofbiz/trunk: framework/base/src/org/ofbiz/base/util/ specialpurpose/pos/config/ specialpurpose/pos/screens/800x600/dialog/ specialpurpose/pos/screens/800x600/dialog/error/ specialpurpose/pos/screens/800x600/menu/ specialpurpos...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r823475 - in /ofbiz/trunk: framework/base/src/org/ofbiz/base/util/ specialpurpose/pos/config/ specialpurpose/pos/screens/800x600/dialog/ specialpurpose/pos/screens/800x600/dialog/error/ specialpurpose/pos/screens/800x600/menu/ specialpurpos...

jleroux@apache.org
Author: jleroux
Date: Fri Oct  9 09:24:54 2009
New Revision: 823475

URL: http://svn.apache.org/viewvc?rev=823475&view=rev
Log:
New feature : in the POS adds the possibility to create a client profile (for now : name, email, phone#, card id for promo), email is also used to create an user login with card id as pwd (login/pwd couple follows changes).
The card id is stored in the Person.memberId field. It's used as a promo code. So if the same id is defined as a promocode, any promotion using this promo code will be added to the cart when you select a client from the Client Profile screen. Else a message will pop when selecting the client.
The idea is to generate promo codes and to use them as card id when creating the physical card.

The Client Profile screen (from Promo button in promo panel) allow you to search for all client (all fields empty) or to focus on a client (at least one field files). For now the search use a stric equals but I plan to allow also contains (ie %like%)
You may edit the client profile and as explained above select a client to apply promotions related to his/her card id.
I plan to add a status bar at bottom of the POS screen to see promocodes used (you may still enter arbitrary promo code with the Promo Code button) or even maybe rather the related promotions (but I doubt there will enough place).
The promo code is used as long as the cart is open.

There are also some generics enhancement in PosTransaction not all related to this new feature.


Added:
    ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/ClientProfile.xml
      - copied, changed from r819280, ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/PaidInOut.xml
    ofbiz/trunk/specialpurpose/pos/screens/default/dialog/ClientProfile.xml
    ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/screen/ClientProfile.java
Modified:
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilProperties.java
    ofbiz/trunk/specialpurpose/pos/config/PosUiLabels.xml
    ofbiz/trunk/specialpurpose/pos/config/XuiLabels.properties
    ofbiz/trunk/specialpurpose/pos/config/XuiLabels_fr.properties
    ofbiz/trunk/specialpurpose/pos/config/XuiLabels_zh.properties
    ofbiz/trunk/specialpurpose/pos/config/buttonevents.xml
    ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/error/exception.xml
    ofbiz/trunk/specialpurpose/pos/screens/800x600/menu/promomain.xml
    ofbiz/trunk/specialpurpose/pos/screens/default/menu/promomain.xml
    ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/PosTransaction.java
    ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/event/PromoEvents.java
    ofbiz/trunk/specialpurpose/pos/styles/posstyles.xml

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilProperties.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilProperties.java?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilProperties.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilProperties.java Fri Oct  9 09:24:54 2009
@@ -340,32 +340,59 @@
         try {
             properties.setProperty(name, value);
             FileOutputStream propFile = new FileOutputStream(resource);
-            properties.store(propFile,
-            "##############################################################################\n"
-            +"# Licensed to the Apache Software Foundation (ASF) under one                   \n"
-            +"# or more contributor license agreements.  See the NOTICE file                 \n"
-            +"# distributed with this work for additional information                        \n"
-            +"# regarding copyright ownership.  The ASF licenses this file                   \n"
-            +"# to you under the Apache License, Version 2.0 (the                            \n"
-            +"# \"License\"); you may not use this file except in compliance                 \n"
-            +"# with the License.  You may obtain a copy of the License at                   \n"
-            +"#                                                                              \n"
-            +"# http://www.apache.org/licenses/LICENSE-2.0                                   \n"
-            +"#                                                                              \n"
-            +"# Unless required by applicable law or agreed to in writing,                   \n"
-            +"# software distributed under the License is distributed on an                  \n"
-            +"# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     \n"
-            +"# KIND, either express or implied.  See the License for the                    \n"
-            +"# specific language governing permissions and limitations                      \n"
-            +"# under the License.                                                           \n"
-            +"###############################################################################\n"
-            +"#                                                                              \n"
-            +"# Dynamically modified by OFBiz Framework (org.ofbiz.base.util : UtilProperties.setPropertyValue)\n"
-            +"#                                                                              \n"
-            +"# By default the screen is 1024x768 wide. If you want to use another screen size,\n"
-            +"# you must create a new directory under specialpurpose/pos/screens, like the 800x600.\n"
-            +"# You must also set the 3 related parameters (StartClass, ClientWidth, ClientHeight) accordingly.\n"
-            +"#");
+            if ("XuiLabels".equals(name)) {
+                properties.store(propFile,
+                    "##############################################################################\n"
+                    +"# Licensed to the Apache Software Foundation (ASF) under one                   \n"
+                    +"# or more contributor license agreements.  See the NOTICE file                 \n"
+                    +"# distributed with this work for additional information                        \n"
+                    +"# regarding copyright ownership.  The ASF licenses this file                   \n"
+                    +"# to you under the Apache License, Version 2.0 (the                            \n"
+                    +"# \"License\"); you may not use this file except in compliance                 \n"
+                    +"# with the License.  You may obtain a copy of the License at                   \n"
+                    +"#                                                                              \n"
+                    +"# http://www.apache.org/licenses/LICENSE-2.0                                   \n"
+                    +"#                                                                              \n"
+                    +"# Unless required by applicable law or agreed to in writing,                   \n"
+                    +"# software distributed under the License is distributed on an                  \n"
+                    +"# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     \n"
+                    +"# KIND, either express or implied.  See the License for the                    \n"
+                    +"# specific language governing permissions and limitations                      \n"
+                    +"# under the License.                                                           \n"
+                    +"###############################################################################\n"
+                    +"#                                                                              \n"
+                    +"# Dynamically modified by OFBiz Framework (org.ofbiz.base.util : UtilProperties.setPropertyValue)\n"
+                    +"#                                                                              \n"
+                    +"# By default the screen is 1024x768 wide. If you want to use another screen size,\n"
+                    +"# you must create a new directory under specialpurpose/pos/screens, like the 800x600.\n"
+                    +"# You must also set the 3 related parameters (StartClass, ClientWidth, ClientHeight) accordingly.\n"
+                    +"#");
+            } else {
+                properties.store(propFile,
+                    "##############################################################################\n"
+                    +"# Licensed to the Apache Software Foundation (ASF) under one                   \n"
+                    +"# or more contributor license agreements.  See the NOTICE file                 \n"
+                    +"# distributed with this work for additional information                        \n"
+                    +"# regarding copyright ownership.  The ASF licenses this file                   \n"
+                    +"# to you under the Apache License, Version 2.0 (the                            \n"
+                    +"# \"License\"); you may not use this file except in compliance                 \n"
+                    +"# with the License.  You may obtain a copy of the License at                   \n"
+                    +"#                                                                              \n"
+                    +"# http://www.apache.org/licenses/LICENSE-2.0                                   \n"
+                    +"#                                                                              \n"
+                    +"# Unless required by applicable law or agreed to in writing,                   \n"
+                    +"# software distributed under the License is distributed on an                  \n"
+                    +"# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     \n"
+                    +"# KIND, either express or implied.  See the License for the                    \n"
+                    +"# specific language governing permissions and limitations                      \n"
+                    +"# under the License.                                                           \n"
+                    +"###############################################################################\n"
+                    +"#                                                                              \n"
+                    +"# Dynamically modified by OFBiz Framework (org.ofbiz.base.util : UtilProperties.setPropertyValue)\n"
+                    +"# The comments have been removed, you may still find them on the OFBiz repository... \n"
+                    +"#");
+                
+            }
 
             propFile.close();
         } catch (FileNotFoundException e) {

Modified: ofbiz/trunk/specialpurpose/pos/config/PosUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/config/PosUiLabels.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/config/PosUiLabels.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/config/PosUiLabels.xml Fri Oct  9 09:24:54 2009
@@ -27,6 +27,10 @@
         <value xml:lang="ro">(adjustment)</value>
         <value xml:lang="zh">(调整)</value>
     </property>
+    <property key="PosAllFieldsAreRequired">
+        <value xml:lang="en">All fields are required</value>
+        <value xml:lang="fr">Tous les champs doivent être renseignés</value>
+    </property>
     <property key="PosAmt">
         <value xml:lang="en">AMT</value>
         <value xml:lang="es">Precio</value>
@@ -75,6 +79,10 @@
         <value xml:lang="ro">Ang:</value>
         <value xml:lang="zh">收银员:</value>
     </property>
+    <property key="PosClientProfile">
+        <value xml:lang="en">Client informations, selection add the card# as a promo code</value>
+        <value xml:lang="fr">Informations sur le client, sa sélection entraîne celle de son n° de carte comme code promo</value>
+    </property>
     <property key="PosConfigureItem">
         <value xml:lang="en">Item Configuration</value>
         <value xml:lang="fr">Configuration de l'article</value>
@@ -407,6 +415,10 @@
         <value xml:lang="it">Selezionare un prodotto</value>
         <value xml:lang="zh">选择一个产品</value>
     </property>
+    <property key="PosSelectClientToEdit">
+        <value xml:lang="en">Select a client to edit or select</value>
+        <value xml:lang="fr">Choisissez le client à modifier ou à sélectionner</value>
+    </property>
     <property key="PosSelectProductListDblClickTip">
         <value xml:lang="en">You may use a double click to select the current product</value>
         <value xml:lang="fr">Vous pouvez utiliser le double-clic pour choisir un produit</value>

Modified: ofbiz/trunk/specialpurpose/pos/config/XuiLabels.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/config/XuiLabels.properties?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/config/XuiLabels.properties (original)
+++ ofbiz/trunk/specialpurpose/pos/config/XuiLabels.properties Fri Oct  9 09:24:54 2009
@@ -27,18 +27,20 @@
 CLEAR_ALL=CLEAR ALL
 CLEAR_CACHE=CLEAR CACHE
 CLEAR_ONE=CLEAR ONE
+CLIENT_PROFILE=CLIENT PROFILE
 CLOSE=CLOSE
 CLR=CLR
 CLR_DISC=CLR DISC
 CONFIG_ITEM=Item Configuration
 CREDIT=CREDIT
 Cancel=Cancel
-reasonCommentInOut=Comment
+Create=Create
 DEL=DEL
 Delete=Delete
 ENT=ENT
 EXCEPTION=EXCEPTION
 EXIT=EXIT
+Edit=Update
 FINISH=FINISH
 FUNCTION_NOT_YET_SUPPORTED=FUNCTION NOT YET SUPPORTED
 GIFT_CERT=GIFT CERT
@@ -80,6 +82,8 @@
 SKU=SKU
 Save=Save
 SaveAndClear=<html><center>Save and<br>clear current sale
+Search=Search
+Select=Select
 TERMINAL_IS_CLOSED=TERMINAL IS CLOSED
 TEST_ALERT=TEST ALERT
 TEST_ALERT_BOX=TEST ALERT BOX - TESTING THE DIALOG IMPLEMENTATION
@@ -90,9 +94,15 @@
 UNKNOWN_CARD_TYPE=UNKNOWN CARD TYPE
 VOID_ITEM=VOID ITEM
 VOID_SALE=VOID SALE
-
+cardClient=Card number
+emailClient=Email address
 item_not_configurable=The selected item is not configurable.
+listClient=Clients list
+nameClient=Name
 no_sales=No sales saved
 order_not_found=ORDER NOT FOUND
+phoneClient=Phone number
 problems_reading_card=PROBLEMS READING SWIPED CARD
-product_not_found=PRODUCT NOT FOUND
\ No newline at end of file
+product_not_found=PRODUCT NOT FOUND
+reasonCommentInOut=Comment
+tipLoginPwd=* Initial email address and card number are also used respectively as login and password

Modified: ofbiz/trunk/specialpurpose/pos/config/XuiLabels_fr.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/config/XuiLabels_fr.properties?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/config/XuiLabels_fr.properties (original)
+++ ofbiz/trunk/specialpurpose/pos/config/XuiLabels_fr.properties Fri Oct  9 09:24:54 2009
@@ -27,18 +27,20 @@
 CLEAR_ALL=Tout annuler
 CLEAR_CACHE=Annuler l'encours
 CLEAR_ONE=Annuler le paiement
+CLIENT_PROFILE=Donn\u00e9es client
 CLOSE=Fermer
 CLR=Effacer
 CLR_DISC=Annuler la remise
 CONFIG_ITEM=Configurer l'article
 CREDIT=Cr\u00e9dit
 Cancel=Annuler
-reasonCommentInOut=Commentaire
+Create=Cr\u00e9er
 DEL=Suppr.
 Delete=Supprimer
 ENT=Valider
 EXCEPTION=Exception rencontr\u00e9e
 EXIT=Quitter
+Edit=Modifier
 FINISH=Fin
 FUNCTION_NOT_YET_SUPPORTED=Fonction non encore support\u00e9e
 GIFT_CERT=Bon d'achat
@@ -80,6 +82,8 @@
 SKU=Code
 Save=Sauver
 SaveAndClear=<html><center>Sauver et<br>r\u00e9intialiser la vente
+Search=Rechercher
+Select=S\u00e9lectionner
 TERMINAL_IS_CLOSED=Le terminal est ferm\u00e9
 TEST_ALERT=Alerte (test)
 TEST_ALERT_BOX=Test de l'impl\u00e9mentation des alertes
@@ -90,10 +94,16 @@
 UNKNOWN_CARD_TYPE=Type de carte inconnu
 VOID_ITEM=Annuler l'article
 VOID_SALE=Annuler la vente
-
+cardClient=N\u00b0 de carte
+emailClient=Courriel
 item_not_configurable=Article non configurable
+listClient=Liste des clients
+nameClient=Nom
 no_sales=Aucune vente sauv\u00e9e
 order_not_found=N\u00b0 de transaction inconnu !
+phoneClient=N\u00b0 de t\u00e9l\u00e9phone
 problems_reading_card=Probl\u00e8me lors de la lecture de la carte
 product_not_found=Produit inconnu !
-promo_page=Ce sera la page des promotions...
\ No newline at end of file
+promo_page=Ce sera la page des promotions...
+reasonCommentInOut=Commentaire
+tipLoginPwd=* L'adresse courriel et le n\u00b0 de carte intials sont aussi utilis\u00e9s respectiv. comme id. de connexion et mot de passe

Modified: ofbiz/trunk/specialpurpose/pos/config/XuiLabels_zh.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/config/XuiLabels_zh.properties?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/config/XuiLabels_zh.properties (original)
+++ ofbiz/trunk/specialpurpose/pos/config/XuiLabels_zh.properties Fri Oct  9 09:24:54 2009
@@ -33,7 +33,6 @@
 CONFIG_ITEM=\u660e\u7ec6\u914d\u7f6e
 CREDIT=\u4fe1\u7528\u5361
 Cancel=\u53d6\u6d88
-reasonCommentInOut=\u8bc4\u8bba
 DEL=\u5220\u9664
 Delete=\u5220\u9664
 ENT=\u786e\u8ba4
@@ -90,9 +89,9 @@
 UNKNOWN_CARD_TYPE=\u672a\u77e5\u5361\u7c7b\u578b
 VOID_ITEM=\u7a7a\u884c
 VOID_SALE=\u7a7a\u9500\u552e
-
 item_not_configurable=\u9009\u62e9\u7684\u660e\u7ec6\u6ca1\u6709\u914d\u7f6e\u3002
 no_sales=\u6ca1\u6709\u4fdd\u5b58\u7684\u9500\u552e
 order_not_found=\u8ba2\u5355\u6ca1\u6709\u627e\u5230
 problems_reading_card=\u8bfb\u5361\u95ee\u9898
 product_not_found=\u4ea7\u54c1\u6ca1\u6709\u627e\u5230
+reasonCommentInOut=\u8bc4\u8bba

Modified: ofbiz/trunk/specialpurpose/pos/config/buttonevents.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/config/buttonevents.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/config/buttonevents.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/config/buttonevents.xml Fri Oct  9 09:24:54 2009
@@ -103,6 +103,7 @@
 
     <!-- pos promo menu events -->
     <event button-name="promoCode" class-name="org.ofbiz.pos.event.PromoEvents" method-name="addPromoCode" disable-lock="false"/>
+    <event button-name="clientProfile" class-name="org.ofbiz.pos.event.PromoEvents" method-name="clientProfile" disable-lock="false"/>
 
     <!-- pos mgr menu events -->
     <event button-name="mgrOpenTerm" class-name="org.ofbiz.pos.event.ManagerEvents" method-name="openTerminal" disable-lock="false"/>

Copied: ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/ClientProfile.xml (from r819280, ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/PaidInOut.xml)
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/ClientProfile.xml?p2=ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/ClientProfile.xml&p1=ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/PaidInOut.xml&r1=819280&r2=823475&rev=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/PaidInOut.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/ClientProfile.xml Fri Oct  9 09:24:54 2009
@@ -19,15 +19,27 @@
 -->
 <XPage class="net.xoetrope.swing.XDialog" resource="">
     <Components>
-        <Panel name="InOutPanel" x="0" y="0" w="680" h="200" style="menu">
-            <Label name="amoutLabel" x="20" y="30" w="100" h="40" content="AmountInOut" style="editAndList"/>
-            <Edit name="amountEdit"  x="120" y="20" w="300" h="40" style="editAndList"/>
-            <Label name="reasonLabel" x="20" y="90" w="100" h="40" content="ReasonInOut" style="editAndList"/>
-            <ComboBox name="reasonCombo" x="120" y="80" w="300" h="40" editable="false" style="editAndList"/>
-            <Label name="reasonCommentLabel" x="20" y="140" w="100" h="40" content="reasonCommentInOut" style="editAndList"/>
-            <Edit name="reasonCommentEdit"  x="120" y="130" w="300" h="40" style="editAndList"/>
-            <Button name="BtnCancel" x="460" y="20" w="180" h="40" content="Cancel" style="dialogButton"/>
-            <Button name="BtnOk" x="460" y="80" w="180" h="40" content="Ok" style="dialogButton"/>
+        <Panel name="ClientPanel" x="0" y="0" w="680" h="400" style="menu">
+            <Label name="nameLabel" x="20" y="30" w="100" h="40" content="nameClient" style="editAndList"/>
+            <Edit name="nameEdit"  x="120" y="20" w="300" h="40" style="editAndList"/>
+            <Label name="emailLabel" x="20" y="90" w="100" h="40" content="emailClient" style="editAndList"/>
+            <Edit name="emailEdit"  x="120" y="80" w="300" h="40" style="editAndList"/>
+            <Label name="phoneLabel" x="20" y="150" w="100" h="40" content="phoneClient" style="editAndList"/>
+            <Edit name="phoneEdit"  x="120" y="140" w="300" h="40" style="editAndList"/>
+            <Label name="cardLabel" x="20" y="210" w="100" h="40" content="cardClient" style="editAndList"/>
+            <Edit name="cardEdit"  x="120" y="200" w="300" h="40" style="editAndList"/>
+
+            <Button name="BtnSearch" x="460" y="20" w="180" h="40" content="Search" style="dialogButton"/>
+            <Button name="BtnCreate" x="460" y="80" w="180" h="40" content="Create" style="dialogButton"/>
+            <Button name="BtnEdit" x="460" y="140" w="180" h="40" content="Edit" style="dialogButton"/>
+            <Button name="BtnSelect" x="460" y="200" w="180" h="40" content="Select" style="dialogButton"/>
+            <Button name="BtnCancel" x="460" y="260" w="180" h="40" content="Cancel" style="dialogButton"/>
+
+            <Label name="clientListLabel" x="20" y="330" w="100" h="40" content="listClient" style="editAndList"/>
+            <ComboBox name="clientListCombo" x="120" y="320" w="520" h="40" editable="false" style="editAndList"/>
+
+            <Label name="tipLoginPwdLabel" x="50" y="380" w="630" h="20" content="tipLoginPwd" style="tip"/>
+
         </Panel>
     </Components>
-</XPage>
\ No newline at end of file
+</XPage>

Modified: ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/error/exception.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/error/exception.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/error/exception.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/screens/800x600/dialog/error/exception.xml Fri Oct  9 09:24:54 2009
@@ -19,8 +19,8 @@
 -->
 <XPage>
     <Components>
-        <Panel name="errorPanel" x="0" y="0" w="400" h="300" style="errorpanel" border="0" alignment="Center">
-            <Button w="400" h="300" name="closeBtn" style="error" content="EXCEPTION" alignment="Center"/>
+        <Panel name="errorPanel" x="0" y="0" w="700" h="400" style="errorpanel" border="0" alignment="Center">
+            <Button w="700" h="400" name="closeBtn" style="error" content="EXCEPTION" alignment="Center"/>
         </Panel>
     </Components>
 </XPage>

Modified: ofbiz/trunk/specialpurpose/pos/screens/800x600/menu/promomain.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/screens/800x600/menu/promomain.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/screens/800x600/menu/promomain.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/screens/800x600/menu/promomain.xml Fri Oct  9 09:24:54 2009
@@ -27,5 +27,6 @@
         <Button name="menuPay" x="400" y="0" w="78" h="47" style="posButton" content="PAY" alignment="Center"/>
 
         <Button name="promoCode" x="0" y="49" w="78" h="47" style="posButton" content="PROMO_CODE" alignment="Center"/>
+        <Button name="clientProfile" x="400" y="49" w="78" h="47" style="posButton" content="CLIENT_PROFILE" alignment="Center"/>
     </Components>
-</XPage>
\ No newline at end of file
+</XPage>

Added: ofbiz/trunk/specialpurpose/pos/screens/default/dialog/ClientProfile.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/screens/default/dialog/ClientProfile.xml?rev=823475&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/screens/default/dialog/ClientProfile.xml (added)
+++ ofbiz/trunk/specialpurpose/pos/screens/default/dialog/ClientProfile.xml Fri Oct  9 09:24:54 2009
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<XPage class="net.xoetrope.swing.XDialog" resource="">
+    <Components>
+        <Panel name="ClientPanel" x="0" y="0" w="680" h="400" style="menu">
+            <Label name="nameLabel" x="20" y="30" w="100" h="40" content="nameClient" style="editAndList"/>
+            <Edit name="nameEdit"  x="120" y="20" w="300" h="40" style="editAndList"/>
+            <Label name="emailLabel" x="20" y="90" w="100" h="40" content="emailClient" style="editAndList"/>
+            <Edit name="emailEdit"  x="120" y="80" w="300" h="40" style="editAndList"/>
+            <Label name="phoneLabel" x="20" y="150" w="100" h="40" content="phoneClient" style="editAndList"/>
+            <Edit name="phoneEdit"  x="120" y="140" w="300" h="40" style="editAndList"/>
+            <Label name="cardLabel" x="20" y="210" w="100" h="40" content="cardClient" style="editAndList"/>
+            <Edit name="cardEdit"  x="120" y="200" w="300" h="40" style="editAndList"/>
+
+            <Button name="BtnSearch" x="460" y="20" w="180" h="40" content="Search" style="dialogButton"/>
+            <Button name="BtnCreate" x="460" y="80" w="180" h="40" content="Create" style="dialogButton"/>
+            <Button name="BtnEdit" x="460" y="140" w="180" h="40" content="Edit" style="dialogButton"/>
+            <Button name="BtnSelect" x="460" y="200" w="180" h="40" content="Select" style="dialogButton"/>
+            <Button name="BtnCancel" x="460" y="260" w="180" h="40" content="Cancel" style="dialogButton"/>
+
+            <Label name="clientListLabel" x="20" y="330" w="100" h="40" content="listClient" style="editAndList"/>
+            <ComboBox name="clientListCombo" x="120" y="320" w="520" h="40" editable="false" style="editAndList"/>
+
+            <Label name="tipLoginPwdLabel" x="50" y="380" w="630" h="20" content="tipLoginPwd" style="tip"/>
+
+        </Panel>
+    </Components>
+</XPage>

Modified: ofbiz/trunk/specialpurpose/pos/screens/default/menu/promomain.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/screens/default/menu/promomain.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/screens/default/menu/promomain.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/screens/default/menu/promomain.xml Fri Oct  9 09:24:54 2009
@@ -27,5 +27,6 @@
         <Button name="menuPay" x="510" y="0" w="100" h="60" style="posButton" content="PAY" alignment="Center"/>
 
         <Button name="promoCode" x="0" y="62" w="100" h="60" style="posButton" content="PROMO_CODE" alignment="Center"/>
+        <Button name="clientProfile" x="510" y="62" w="100" h="60" style="posButton" content="CLIENT_PROFILE" alignment="Center"/>
     </Components>
-</XPage>
\ No newline at end of file
+</XPage>

Modified: ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/PosTransaction.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/PosTransaction.java?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/PosTransaction.java (original)
+++ ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/PosTransaction.java Fri Oct  9 09:24:54 2009
@@ -21,17 +21,16 @@
 import java.io.PrintWriter;
 import java.io.Serializable;
 import java.math.BigDecimal;
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Locale;
 import java.util.Map;
-import java.util.ArrayList;
 
+import javolution.util.FastList;
 import javolution.util.FastMap;
-//import javax.swing.SwingWorker;
-
 import net.xoetrope.xui.data.XModel;
 import net.xoetrope.xui.helper.SwingWorker;
 
@@ -49,6 +48,14 @@
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.condition.EntityOperator;
+import org.ofbiz.entity.model.DynamicViewEntity;
+import org.ofbiz.entity.model.ModelKeyMap;
+import org.ofbiz.entity.transaction.GenericTransactionException;
+import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.entity.util.EntityFindOptions;
+import org.ofbiz.entity.util.EntityListIterator;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.guiapp.xui.XuiSession;
 import org.ofbiz.order.shoppingcart.CartItemModifyException;
@@ -62,6 +69,7 @@
 import org.ofbiz.pos.component.Output;
 import org.ofbiz.pos.device.DeviceLoader;
 import org.ofbiz.pos.device.impl.Receipt;
+import org.ofbiz.pos.screen.ClientProfile;
 import org.ofbiz.pos.screen.LoadSale;
 import org.ofbiz.pos.screen.PosScreen;
 import org.ofbiz.pos.screen.SaveSale;
@@ -73,6 +81,7 @@
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ServiceUtil;
 
+@SuppressWarnings("serial")
 public class PosTransaction implements Serializable {
 
     public static final int scale = UtilNumber.getBigDecimalScale("order.decimals");
@@ -87,7 +96,7 @@
 
     private static PrintWriter defaultPrintWriter = new Log4jLoggerWriter(Debug.getLogger(module));
     private static PosTransaction currentTx = null;
-    private static LifoSet savedTx = new LifoSet();
+    private static LifoSet<PosTransaction> savedTx = new LifoSet<PosTransaction>();
     private Locale defaultLocale = Locale.getDefault();
 
     protected XuiSession session = null;
@@ -108,7 +117,7 @@
     protected int drawerIdx = 0;
 
     private GenericValue shipAddress = null;
-    private Map skuDiscounts = FastMap.newInstance();
+    private Map<String, Integer> skuDiscounts = FastMap.newInstance();
     private int cartDiscount = -1;
 
 
@@ -159,7 +168,15 @@
     public String getUserId() {
         return session.getUserId();
     }
-
+    
+    public String getPartyId() {
+        return partyId;
+    }
+    
+    public void setPartyId(String partyId) {
+        this.partyId = partyId;
+    }
+    
     public int getDrawerNumber() {
         return drawerIdx + 1;
     }
@@ -200,7 +217,7 @@
         return (cart == null || cart.size() == 0);
     }
 
-    public List lookupItem(String sku) throws GeneralException {
+    public List<GenericValue> lookupItem(String sku) throws GeneralException {
         return ProductWorker.findProductsById(session.getDelegator(), sku, null);
     }
 
@@ -262,7 +279,7 @@
     }
 
     public List getItemConfigInfo(int index) {
-        List<Map> list = new ArrayList<Map>();
+        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
         // I think I need to initialize the list in a special way
         // to use foreach in receipt.java
 
@@ -566,7 +583,7 @@
         if (productId != null) {
             trace("add item adjustment");
             ShoppingCartItem item = cart.findCartItem(productId, null, null, null, BigDecimal.ZERO);
-            Integer itemAdj = (Integer) skuDiscounts.get(productId);
+            Integer itemAdj = skuDiscounts.get(productId);
             if (itemAdj != null) {
                 item.removeAdjustment(itemAdj.intValue());
             }
@@ -586,15 +603,11 @@
             cart.removeAdjustment(cartDiscount);
             cartDiscount = -1;
         }
-        if (skuDiscounts.size() > 0) {
-            Iterator i = skuDiscounts.keySet().iterator();
-            while (i.hasNext()) {
-                String productId = (String) i.next();
-                ShoppingCartItem item = cart.findCartItem(productId, null, null, null, BigDecimal.ZERO);
-                Integer itemAdj = (Integer) skuDiscounts.remove(productId);
-                if (itemAdj != null) {
-                    item.removeAdjustment(itemAdj.intValue());
-                }
+        for(String productId : skuDiscounts.keySet()) {
+            ShoppingCartItem item = cart.findCartItem(productId, null, null, null, BigDecimal.ZERO);
+            Integer itemAdj = (Integer) skuDiscounts.remove(productId);
+            if (itemAdj != null) {
+                item.removeAdjustment(itemAdj.intValue());
             }
         }
     }
@@ -888,6 +901,7 @@
 
         // clear the tx
         currentTx = null;
+        partyId = "_NA_";
 
         return change;
     }
@@ -1173,6 +1187,7 @@
     }
 
     public void loadSale(PosScreen pos) {
+        trace("Load a sale");
         List shoppingLists = createShoppingLists();
         if (!shoppingLists.isEmpty()) {
             Hashtable salesMap = createSalesMap(shoppingLists);
@@ -1302,6 +1317,7 @@
     }
 
     public boolean addListToCart(String shoppingListId, PosScreen pos, boolean append) {
+        trace("Add list to cart");
         Delegator delegator = session.getDelegator();
         LocalDispatcher dispatcher = session.getDispatcher();
         String includeChild = null; // Perhaps will be used later ...
@@ -1318,6 +1334,7 @@
     }
 
     public boolean restoreOrder(String orderId, PosScreen pos, boolean append) {
+        trace("Restore an order");
         Delegator delegator = session.getDelegator();
         LocalDispatcher dispatcher = session.getDispatcher();
 
@@ -1374,12 +1391,18 @@
     }
 
 
+    public void clientProfile(PosScreen pos) {
+        ClientProfile clientProfile = new ClientProfile(this, pos);
+        clientProfile.openDlg();
+    }
+
     public void saveSale(PosScreen pos) {
-        SaveSale SaveSale = new SaveSale(this, pos);
-        SaveSale.openDlg();
+        SaveSale saveSale = new SaveSale(this, pos);
+        saveSale.openDlg();
     }
 
     public void saveOrder(String shoppingListName, PosScreen pos) {
+        trace("Save an order");
         if (cart.size() == 0) {
             pos.showDialog("dialog/error/exception", UtilProperties.getMessage("OrderErrorUiLabels", "OrderUnableToCreateNewShoppingList",locale));
             return;
@@ -1409,6 +1432,7 @@
     }
 
     public void saveSale(String  shoppingListName, PosScreen pos) {
+        trace("Save a sale");
         if (cart.size() == 0) {
             pos.showDialog("dialog/error/exception", UtilProperties.getMessage("OrderErrorUiLabels", "OrderUnableToCreateNewShoppingList",locale));
             return;
@@ -1467,10 +1491,447 @@
         }
     }
 
-    public String addProductPromoCode(String code, PosScreen pos) {
+    public String addProductPromoCode(String code) {
+        trace("Add a promo code");
         LocalDispatcher dispatcher = session.getDispatcher();
         String result = cart.addProductPromoCode(code, dispatcher);
         calcTax();
         return result;
     }
+
+    // TODO, I really wonder if there is not a better way to do this (DynamicView excluded because of the contactMechId collisions between phone and email)!
+    private List<Map<String, String>> searchContactMechs(Delegator delegator, PosScreen pos, List<Map<String, String>> partyList, String valueToCompare, String contactMechType) {
+        ListIterator<Map<String, String>>  partyListIt = partyList.listIterator();
+        while(partyListIt.hasNext()) {
+            Map<String, String> party = (Map<String, String>) partyListIt.next();
+            String partyId = (String) party.get("partyId");
+            List<Map<String, Object>> partyContactMechValueMaps = ContactMechWorker.getPartyContactMechValueMaps(delegator, partyId, false, contactMechType);
+            Integer nb = 0;
+            for (Map<String, Object> partyContactMechValueMap : partyContactMechValueMaps) {
+                nb++;
+                String keyType = null;
+                String key = null;
+                if ("TELECOM_NUMBER".equals(contactMechType)) {
+                    keyType = "telecomNumber";
+                    key = "contactNumber";
+                } else if ("EMAIL_ADDRESS".equals(contactMechType)) {
+                    keyType = "contactMech";
+                    key = "infoString";
+                }
+                Map<String, Object> keyTypeMap = (Map<String, Object>) partyContactMechValueMap.get(keyType);
+                String keyTypeValue = ((String) keyTypeMap.get(key)).trim();
+                if (valueToCompare.equals(keyTypeValue) || UtilValidate.isEmpty(valueToCompare)) {
+                    if (nb == 1) {
+                        party.put(key, keyTypeValue);
+                        partyListIt.set(party);
+                    } else {
+                        Map partyClone = FastMap.newInstance();
+                        partyClone.putAll(party);
+                        partyClone.put(key, keyTypeValue);
+                        partyListIt.add(partyClone);
+                    }
+                }
+            }
+        }
+        return partyList;
+    }
+
+
+    public List<Map<String, String>> searchClientProfile(String name, String email, String  phone, String card, PosScreen pos) {
+        Delegator delegator = this.session.getDelegator();
+        LocalDispatcher dispatcher = session.getDispatcher();
+        GenericValue userLogin = session.getUserLogin();
+        Locale locale = defaultLocale;
+
+        List<GenericValue> partyList = null;
+        List<Map<String, String>> resultList = null;
+
+        // create the dynamic view entity
+        DynamicViewEntity dynamicView = new DynamicViewEntity();
+
+        // Person (name + card)
+        dynamicView.addMemberEntity("PT", "Party");
+        dynamicView.addAlias("PT", "partyId");
+        dynamicView.addAlias("PT", "statusId");
+        dynamicView.addAlias("PT", "partyTypeId");
+        dynamicView.addMemberEntity("PE", "Person");
+        dynamicView.addAlias("PE", "partyId");
+        dynamicView.addAlias("PE", "lastName");
+        dynamicView.addAlias("PE", "memberId");
+        dynamicView.addAlias("PE", "lastNameLocal");
+        dynamicView.addViewLink("PT", "PE", Boolean.FALSE, ModelKeyMap.makeKeyMapList("partyId"));
+
+        Boolean onlyPhone = UtilValidate.isEmpty(name) && UtilValidate.isEmpty(email) && UtilValidate.isNotEmpty(phone) && UtilValidate.isEmpty(card);
+        if (!onlyPhone) {
+            // ContactMech (email)
+            dynamicView.addMemberEntity("PM", "PartyContactMechPurpose");            
+            dynamicView.addMemberEntity("CM", "ContactMech");
+            dynamicView.addAlias("PM", "contactMechId");
+            dynamicView.addAlias("PM", "contactMechPurposeTypeId");            
+            dynamicView.addAlias("PM", "thruDate");
+            dynamicView.addAlias("CM", "infoString");            
+            dynamicView.addViewLink("PT", "PM", Boolean.FALSE, ModelKeyMap.makeKeyMapList("partyId"));
+            dynamicView.addViewLink("PM", "CM", Boolean.FALSE, ModelKeyMap.makeKeyMapList("contactMechId"));
+        } else {
+            dynamicView.addMemberEntity("PM", "PartyContactMechPurpose");            
+            dynamicView.addMemberEntity("TN", "TelecomNumber");
+            dynamicView.addAlias("PM", "contactMechId");
+            dynamicView.addAlias("PM", "thruDate");
+            dynamicView.addAlias("PM", "contactMechPurposeTypeId");            
+            dynamicView.addAlias("TN", "contactNumber");
+            dynamicView.addViewLink("PT", "PM", Boolean.FALSE, ModelKeyMap.makeKeyMapList("partyId"));
+            dynamicView.addViewLink("PM", "TN", Boolean.FALSE, ModelKeyMap.makeKeyMapList("contactMechId"));
+        }
+
+            // define the main condition & expression list
+            List<EntityCondition> andExprs = FastList.newInstance();
+            EntityCondition mainCond = null;
+
+            List<String> orderBy = FastList.newInstance();
+            List<String> fieldsToSelect = FastList.newInstance();
+            // fields we need to select; will be used to set distinct
+            fieldsToSelect.add("partyId");
+            fieldsToSelect.add("lastName");
+            fieldsToSelect.add("memberId");
+            if (!onlyPhone) {
+                fieldsToSelect.add("infoString");
+            } else {
+                fieldsToSelect.add("contactNumber");
+            }
+
+            // NOTE: _must_ explicitly allow null as it is not included in a not equal in many databases... odd but true
+            // This allows to get all clients when any informations has been entered
+            andExprs.add(EntityCondition.makeCondition(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PARTY_DISABLED")));
+            andExprs.add(EntityCondition.makeCondition("partyTypeId", EntityOperator.EQUALS, "PERSON")); // Only persons for now...
+            if (UtilValidate.isNotEmpty(name)) {
+                andExprs.add(EntityCondition.makeCondition("lastName", EntityOperator.EQUALS, name));
+            }
+            if (UtilValidate.isNotEmpty(card)) {
+                andExprs.add(EntityCondition.makeCondition("memberId", EntityOperator.EQUALS, card));
+            }
+            if (UtilValidate.isNotEmpty(email)) {
+                andExprs.add(EntityCondition.makeCondition("infoString", EntityOperator.EQUALS, email));
+                andExprs.add(EntityCondition.makeCondition("contactMechPurposeTypeId", EntityOperator.EQUALS, "PRIMARY_EMAIL"));
+                andExprs.add(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null));
+            }
+            if (onlyPhone) {
+                andExprs.add(EntityCondition.makeCondition("contactNumber", EntityOperator.EQUALS, phone));
+                andExprs.add(EntityCondition.makeCondition("contactMechPurposeTypeId", EntityOperator.EQUALS, "PHONE_HOME"));
+                andExprs.add(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null));
+            } else if (UtilValidate.isEmpty(email)) {
+                andExprs.add(EntityCondition.makeCondition("infoString", EntityOperator.NOT_EQUAL, null));                
+                andExprs.add(EntityCondition.makeCondition("contactMechPurposeTypeId", EntityOperator.EQUALS, "PRIMARY_EMAIL"));
+                andExprs.add(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null));
+            }
+
+            mainCond = EntityCondition.makeCondition(andExprs, EntityOperator.AND);
+            orderBy.add("lastName");
+
+            Debug.logInfo("In searchClientProfile mainCond=" + mainCond, module);
+
+            Integer maxRows = Integer.MAX_VALUE;
+            // attempt to start a transaction
+            boolean beganTransaction = false;
+            try {
+                beganTransaction = TransactionUtil.begin();
+
+                try {
+                    // set distinct on so we only get one row per person
+                    EntityFindOptions findOpts = new EntityFindOptions(true, EntityFindOptions.TYPE_SCROLL_INSENSITIVE, EntityFindOptions.CONCUR_READ_ONLY, -1, maxRows, true);
+                    // using list iterator
+                    EntityListIterator pli = delegator.findListIteratorByCondition(dynamicView, mainCond, null, fieldsToSelect, orderBy, findOpts);
+
+                    // get the partial list for this page
+                    partyList = pli.getPartialList(1, maxRows);
+
+                    // close the list iterator
+                    pli.close();
+                    } catch (GenericEntityException e) {
+                        Debug.logError(e, module);
+                        pos.showDialog("dialog/error/exception", e.getMessage());
+                    }
+            } catch (GenericTransactionException e) {
+                Debug.logError(e, module);
+                try {
+                    TransactionUtil.rollback(beganTransaction, e.getMessage(), e);
+                } catch (GenericTransactionException e2) {
+                    Debug.logError(e2, "Unable to rollback transaction", module);
+                    pos.showDialog("dialog/error/exception", e2.getMessage());
+                }
+                pos.showDialog("dialog/error/exception", e.getMessage());
+            } finally {
+                try {
+                    TransactionUtil.commit(beganTransaction);
+                } catch (GenericTransactionException e) {
+                    Debug.logError(e, "Unable to commit transaction", module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                }
+            }
+
+            if (partyList != null) {
+                resultList = FastList.newInstance();
+                for (GenericValue party : partyList) {
+                    Map partyMap = FastMap.newInstance();
+                    partyMap.put("partyId", party.getString("partyId"));
+                    partyMap.put("lastName", party.getString("lastName"));
+                    partyMap.put("memberId", party.getString("memberId"));
+                    if (!onlyPhone) {
+                        partyMap.put("infoString", party.getString("infoString"));
+                        partyMap.put("contactNumber", "");
+                    } else {
+                        partyMap.put("contactNumber", party.getString("contactNumber"));
+                        partyMap.put("infoString", "");
+                    }
+                    resultList.add(partyMap);
+                }
+                if (!onlyPhone) {
+                    resultList = searchContactMechs(delegator, pos, resultList, phone, "TELECOM_NUMBER");
+                } else {
+                    resultList = searchContactMechs(delegator, pos, resultList, "", "EMAIL_ADDRESS"); //"" is more clear than email which is by definition here is empty
+                }
+            } else {
+            resultList = FastList.newInstance();
+        }
+        return resultList;
+    }
+
+    public String editClientProfile(String name, String email, String  phone, String card, PosScreen pos, String editType, String partyId) {
+        // We suppose here that a memberId (card number) can only belongs to one person (it's used as owned PromoCode)
+        // We use the 1st party's login (it may change and be multiple since it depends on email and card)
+        // We suppose only one email address (should be ok anyway because of the contactMechPurposeTypeId == "PRIMARY_EMAIL")
+        // we suppose only one phone number (should be ok anyway because of the contactMechPurposeTypeId == "PHONE_HOME")
+        Delegator delegator = session.getDelegator();
+        LocalDispatcher dispatcher = session.getDispatcher();
+        GenericValue userLogin = session.getUserLogin();
+        String result = null;
+
+        Map<String, Object> svcCtx = FastMap.newInstance();
+        Map svcRes = null;
+
+        if ("create".equals(editType)) {
+            // Create
+            trace("Create a client profile");
+            svcCtx.put("memberId", card);
+            svcCtx.put("lastName", name);
+            svcCtx.put("firstName", ""); // Needed by service createPersonAndUserLogin
+            svcCtx.put("userLogin", userLogin);
+            svcCtx.put("userLoginId", email);
+            svcCtx.put("currentPassword", card);
+            svcCtx.put("currentPasswordVerify", card);
+            svcCtx.put("passwordHint", "Your card number is your password");            
+
+            // createPersonAndUserLogin
+            try {
+                svcRes = dispatcher.runSync("createPersonAndUserLogin", svcCtx);
+            } catch (GenericServiceException e) {
+                Debug.logError(e, module);
+                pos.showDialog("dialog/error/exception", e.getMessage());
+               return result;
+            }
+            if (ServiceUtil.isError(svcRes)) {
+                pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                return result;
+            }
+            partyId = (String) svcRes.get("partyId");
+            GenericValue newUserLogin = (GenericValue) svcRes.get("newUserLogin");
+
+            // createPartyEmailAddress
+            svcCtx.clear();
+            svcCtx.put("userLogin", newUserLogin);
+            svcCtx.put("emailAddress", email);
+            svcCtx.put("partyId", partyId);
+            svcCtx.put("contactMechPurposeTypeId", "PRIMARY_EMAIL");
+            try {
+                svcRes = dispatcher.runSync("createPartyEmailAddress", svcCtx);
+            } catch (GenericServiceException e) {
+                Debug.logError(e, module);
+                pos.showDialog("dialog/error/exception", e.getMessage());
+                return result;
+            }
+            if (ServiceUtil.isError(svcRes)) {
+                pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                return result;
+            }
+
+            // createPartyTelecomNumber
+            svcCtx.clear();
+            svcCtx.put("userLogin", newUserLogin);
+            svcCtx.put("contactNumber", phone);
+            svcCtx.put("partyId", partyId);
+            svcCtx.put("contactMechPurposeTypeId", "PHONE_HOME");
+            try {
+                svcRes = dispatcher.runSync("createPartyTelecomNumber", svcCtx);
+            } catch (GenericServiceException e) {
+                Debug.logError(e, module);
+                pos.showDialog("dialog/error/exception", e.getMessage());
+                return result;
+            }
+            if (ServiceUtil.isError(svcRes)) {
+                pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                return result;
+            }
+            result = partyId;
+        } else {
+            trace("Update a client profile");
+            List<GenericValue>  userLogins = null;
+            try {
+                userLogins = session.getDelegator().findByAnd("UserLogin", UtilMisc.toMap("partyId", partyId));
+            } catch (GenericEntityException e) {
+                Debug.logError(e, module);
+                pos.showDialog("dialog/error/exception", e.getMessage());
+                return result;
+            }
+            GenericValue partyLogin = userLogins.get(0); // We need at least a party's login ...
+            GenericValue  person = null;
+            try {
+                person = session.getDelegator().findByPrimaryKey("Person", UtilMisc.toMap("partyId", partyId));
+            } catch (GenericEntityException e) {
+                Debug.logError(e, module);
+                pos.showDialog("dialog/error/exception", e.getMessage());
+                return result;
+            }
+            
+            if (UtilValidate.isNotEmpty(name) && !person.getString("lastName").equals(name)
+                    || UtilValidate.isNotEmpty(card) && !person.getString("memberId").equals(card)) {
+                svcCtx.put("partyId", partyId);
+                svcCtx.put("firstName", ""); // Needed by service updatePerson
+                svcCtx.put("userLogin", partyLogin);
+                if (UtilValidate.isNotEmpty(name)) {
+                    svcCtx.put("lastName", name);
+                }
+                if (UtilValidate.isNotEmpty(card)) {
+                    svcCtx.put("memberId", card);
+                    if (!person.getString("memberId").equals(card)) {
+                        // Update password
+                        UtilProperties.setPropertyValue("security.properties", "password.accept.encrypted.and.plain", "true");
+                        try {
+                            svcRes = dispatcher.runSync("updatePassword",
+                                    UtilMisc.toMap("userLogin", partyLogin,
+                                    "userLoginId", partyLogin.getString("userLoginId"),
+                                    "currentPassword", partyLogin.getString("currentPassword"),
+                                    "newPassword", card,
+                                    "newPasswordVerify", card,
+                                    "passwordHint", "Your card number is your password"));            
+                        } catch (GenericServiceException e) {
+                            Debug.logError(e, "Error calling updatePassword service", module);
+                            pos.showDialog("dialog/error/exception", e.getMessage());
+                            return result;
+                        }
+                        if (ServiceUtil.isError(svcRes)) {
+                            pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                            return result;
+                        }
+                        // This remove comments from the security.properties file. I did not find a way to keep them, so I put a word about that
+                        UtilProperties.setPropertyValue("security.properties", "password.accept.encrypted.and.plain", "false");
+                        partyLogin = (GenericValue) svcRes.get("updatedUserLogin");
+                        svcCtx.put("userLogin", partyLogin);
+                    }                    
+                }
+    
+                // Update name and card (memberId)
+                try {
+                    svcRes = dispatcher.runSync("updatePerson", svcCtx);
+                } catch (GenericServiceException e) {
+                    Debug.logError(e, module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                    return result;
+                }
+                if (ServiceUtil.isError(svcRes)) {
+                    pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                    return result;
+                }                
+            }
+
+            // Update email            
+            if (UtilValidate.isNotEmpty(email) && !partyLogin.getString("userLoginId").equals(email)) {                
+                // create a new UserLogin (Update a UserLoginId by creating a new one and expiring the old one)
+                try {
+                    svcRes = dispatcher.runSync("updateUserLoginId", UtilMisc.toMap("userLoginId", email, "userLogin", partyLogin));
+                } catch (GenericServiceException e) {
+                    Debug.logError(e, module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                   return result;
+                }
+                if (ServiceUtil.isError(svcRes)) {
+                    pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                    return result;
+                }
+                partyLogin = (GenericValue) svcRes.get("newUserLogin");
+                
+                svcCtx.clear();
+                svcCtx.put("partyId", partyId);
+                svcCtx.put("contactMechTypeId", "EMAIL_ADDRESS");                
+                svcCtx.put("thruDate", null); // last one                
+                List<GenericValue>  PartyEmails = null;
+                try {
+                    PartyEmails = session.getDelegator().findByAnd("PartyAndContactMech", svcCtx);
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                    return result;
+                }
+
+                svcCtx.clear();
+                svcCtx.put("userLogin", partyLogin);
+                svcCtx.put("emailAddress", email);
+                svcCtx.put("partyId", partyId);
+                svcCtx.put("contactMechPurposeTypeId", "PRIMARY_EMAIL");
+
+                if (UtilValidate.isNotEmpty(PartyEmails)) {
+                    svcCtx.put("contactMechId", PartyEmails.get(0).getString("contactMechId")); // We suppose only one email address (should be ok anyway because of the contactMechPurposeTypeId == "PRIMARY_EMAIL")
+                }
+                try {
+                    svcRes = dispatcher.runSync("createUpdatePartyEmailAddress", svcCtx);
+                } catch (GenericServiceException e) {
+                    Debug.logError(e, module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                    return result;
+                }
+                if (ServiceUtil.isError(svcRes)) {
+                    pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                    return result;
+                }
+            }
+
+            // Update phone
+            if (UtilValidate.isNotEmpty(phone)) {
+                svcCtx.clear();
+                svcCtx.put("partyId", partyId);
+                svcCtx.put("thruDate", null); // last one
+                List<GenericValue>  PartyTelecomNumbers = null;
+                try {
+                    PartyTelecomNumbers = session.getDelegator().findByAnd("PartyAndTelecomNumber", svcCtx);
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                    pos.showDialog("dialog/error/exception", e.getMessage());
+                    return result;
+                }
+                GenericValue PartyTelecomNumber = PartyTelecomNumbers.get(0); // we suppose only one phone number (should be ok anyway because of the contactMechPurposeTypeId == "PHONE_HOME")
+                String contactNumber = PartyTelecomNumber.getString("contactNumber");
+                if (!contactNumber.equals(phone)) {
+                    String newContactMechId = PartyTelecomNumber.getString("contactMechId");
+    
+                    svcCtx.put("userLogin", partyLogin);
+                    svcCtx.put("contactNumber", phone);
+                    svcCtx.put("contactMechPurposeTypeId", "PHONE_HOME");
+                    if (UtilValidate.isNotEmpty(PartyTelecomNumbers)) {
+                        svcCtx.put("contactMechId", newContactMechId);
+                    }
+                    
+                    try {
+                        svcRes = dispatcher.runSync("createUpdatePartyTelecomNumber", svcCtx);
+                    } catch (GenericServiceException e) {
+                        Debug.logError(e, module);
+                        pos.showDialog("dialog/error/exception", e.getMessage());
+                        return result;
+                    }
+                    if (ServiceUtil.isError(svcRes)) {
+                        pos.showDialog("dialog/error/exception", ServiceUtil.getErrorMessage(svcRes));
+                        return result;
+                    }
+                }
+            }
+        }
+        return result;
+    }
 }

Modified: ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/event/PromoEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/event/PromoEvents.java?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/event/PromoEvents.java (original)
+++ ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/event/PromoEvents.java Fri Oct  9 09:24:54 2009
@@ -47,7 +47,7 @@
         } else if ("PROMOCODE".equals(lastFunc[0])) {
             String promoCode = input.value();
             if (UtilValidate.isNotEmpty(promoCode)) {
-                String result = trans.addProductPromoCode(promoCode, pos);
+                String result = trans.addProductPromoCode(promoCode);
                 if (result != null) {
                     pos.showDialog("dialog/error/exception", result);
                     input.clearFunction("PROMOCODE");
@@ -59,4 +59,9 @@
             }
         }
     }
+    
+    public static synchronized void clientProfile(PosScreen pos) {
+        PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
+        trans.clientProfile(pos);
+    }        
 }

Added: ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/screen/ClientProfile.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/screen/ClientProfile.java?rev=823475&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/screen/ClientProfile.java (added)
+++ ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/pos/screen/ClientProfile.java Fri Oct  9 09:24:54 2009
@@ -0,0 +1,328 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.pos.screen;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.swing.DefaultComboBoxModel;
+
+import javolution.util.FastList;
+
+import net.xoetrope.swing.XButton;
+import net.xoetrope.swing.XComboBox;
+import net.xoetrope.swing.XDialog;
+import net.xoetrope.swing.XEdit;
+import net.xoetrope.swing.XLabel;
+import net.xoetrope.xui.XPage;
+import net.xoetrope.xui.events.XEventHelper;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.pos.PosTransaction;
+
+
+@SuppressWarnings("serial")
+public class ClientProfile extends XPage implements ActionListener {
+
+    /**
+     * To allow searching, creating or editing a client profile (ie for now : Name, Email Address, Phone Number, Membership Card Number)
+     */
+
+    public static final String module = ClientProfile.class.getName();
+    protected static PosScreen m_pos = null;
+    protected XDialog m_dialog = null;
+    protected XLabel m_nameLabel = null;
+    protected XEdit m_nameEdit = null;
+    protected XLabel m_emailLabel = null;
+    protected XEdit m_emailEdit = null;
+    protected XLabel m_phoneLabel = null;
+    protected XEdit m_phoneEdit = null;
+    protected XLabel m_cardLabel = null;
+    protected XEdit m_cardEdit = null;
+    protected XLabel m_clientListLabel = null;
+    protected XComboBox m_clientListCombo = null;
+    protected List<String> m_clientListBidingCombo = FastList.newInstance();
+    protected XLabel m_tipLoginPwdLabel = null;
+    protected XButton m_search = null;
+    protected XButton m_create = null;
+    protected XButton m_edit = null;
+    protected XButton m_select = null;
+    protected XButton m_cancel = null;
+    protected DefaultComboBoxModel m_comboModel = null;
+    protected static PosTransaction m_trans = null;
+    protected String m_type = null;
+    protected boolean cancelled = false;
+    private static boolean ShowKeyboardInSaveSale = UtilProperties.propertyValueEqualsIgnoreCase("parameters", "ShowKeyboardInSaveSale", "Y");
+    private static Locale locale = Locale.getDefault();
+    private String m_partyId = null;
+
+
+    //TODO : make getter and setter for members (ie m_*) if needed (extern calls). For that in Eclipse use Source/Generate Getters and setters
+
+    public ClientProfile(PosTransaction trans, PosScreen page) {
+        m_trans = trans;
+        m_pos = page;
+    }
+
+    public void openDlg() {
+        m_dialog = (XDialog) pageMgr.loadPage(m_pos.getScreenLocation() + "/dialog/ClientProfile");
+
+        m_nameEdit = (XEdit) m_dialog.findComponent("nameEdit"); // 1st for focus (still does not work)
+        m_nameLabel = (XLabel) m_dialog.findComponent("nameLabel");
+        m_emailLabel = (XLabel) m_dialog.findComponent("emailLabel");
+        m_emailEdit = (XEdit) m_dialog.findComponent("emailEdit");
+        m_phoneLabel = (XLabel) m_dialog.findComponent("phoneLabel");
+        m_phoneEdit = (XEdit) m_dialog.findComponent("phoneEdit");
+        m_cardLabel = (XLabel) m_dialog.findComponent("cardLabel");
+        m_cardEdit = (XEdit) m_dialog.findComponent("cardEdit");
+
+        m_clientListLabel = (XLabel) m_dialog.findComponent("clientListLabel");
+        m_clientListCombo = (XComboBox) m_dialog.findComponent("clientListCombo");
+
+        m_tipLoginPwdLabel = (XLabel) m_dialog.findComponent("tipLoginPwdLabel");
+
+        m_search = (XButton) m_dialog.findComponent("BtnSearch");
+        m_create = (XButton) m_dialog.findComponent("BtnCreate");
+        m_edit = (XButton) m_dialog.findComponent("BtnEdit");
+        m_select = (XButton) m_dialog.findComponent("BtnSelect");
+        m_cancel = (XButton) m_dialog.findComponent("BtnCancel");
+
+        XEventHelper.addMouseHandler(this, m_search, "search");
+        XEventHelper.addMouseHandler(this, m_create, "edit(create)");
+        XEventHelper.addMouseHandler(this, m_edit, "edit(update)");
+        XEventHelper.addMouseHandler(this, m_select, "select");
+        XEventHelper.addMouseHandler(this, m_cancel, "cancel");
+        XEventHelper.addMouseHandler(this, m_nameEdit, "editName");
+        XEventHelper.addMouseHandler(this, m_emailEdit, "editEmail");
+        XEventHelper.addMouseHandler(this, m_phoneEdit, "editPhone");
+        XEventHelper.addMouseHandler(this, m_cardEdit, "editCard");
+
+        m_comboModel = new DefaultComboBoxModel();
+        m_dialog.setCaption(UtilProperties.getMessage(PosTransaction.resource, "PosClientProfile", locale));
+        m_clientListCombo.setModel(m_comboModel);
+        m_clientListCombo.setToolTipText(UtilProperties.getMessage(PosTransaction.resource, "PosSelectClientToEdit", locale));
+        m_clientListCombo.addActionListener(this);
+
+
+        m_dialog.pack();
+        m_nameEdit.requestFocusInWindow();
+        m_dialog.showDialog(this);
+        if (!cancelled) {
+            m_trans.setPartyId(m_partyId);
+            GenericValue  person = null;
+            try {
+                person = m_trans.getSession().getDelegator().findByPrimaryKey("Person", UtilMisc.toMap("partyId", m_partyId));
+            } catch (GenericEntityException e) {
+                Debug.logError(e, module);
+            }  
+            if (UtilValidate.isNotEmpty(person)) {
+                String promoCode = person.getString("memberId");
+                if (UtilValidate.isNotEmpty(promoCode)) {          
+                    String result = m_trans.addProductPromoCode(promoCode);
+                    if(UtilValidate.isNotEmpty(result)) {
+                        m_pos.showDialog("dialog/error/exception", result);
+                    }                
+                }
+            }
+        }
+    }
+
+    public synchronized void cancel() {
+        if (wasMouseClicked()) {
+            cancelled = true;
+            m_dialog.closeDlg();
+        }
+    }
+
+    public synchronized void editName() {
+        if (wasMouseClicked() && ShowKeyboardInSaveSale) {
+            try {
+                Keyboard keyboard = new Keyboard(m_pos);
+                keyboard.setText(m_nameEdit.getText());
+                m_nameEdit.setText(keyboard.openDlg());
+            } catch (Exception e) {
+                Debug.logError(e, module);
+            }
+            m_dialog.repaint();
+        }
+        return;
+    }
+
+    public synchronized void editEmail() {
+        if (wasMouseClicked() && ShowKeyboardInSaveSale) {
+            try {
+                Keyboard keyboard = new Keyboard(m_pos);
+                keyboard.setText(m_emailEdit.getText());
+                m_emailEdit.setText(keyboard.openDlg());
+            } catch (Exception e) {
+                Debug.logError(e, module);
+            }
+            m_dialog.repaint();
+        }
+        return;
+    }
+
+    public synchronized void editPhone() {
+        if (wasMouseClicked() && ShowKeyboardInSaveSale) {
+            try {
+                NumericKeypad numericKeypad = new NumericKeypad(m_pos);
+                numericKeypad.setMinus(true);
+                numericKeypad.setPercent(false);
+                m_phoneEdit.setText(numericKeypad.openDlg());
+            } catch (Exception e) {
+                Debug.logError(e, module);
+            }
+            m_dialog.repaint();
+        }
+        return;
+    }
+
+    public synchronized void editCard() {
+        if (wasMouseClicked() && ShowKeyboardInSaveSale) {
+            try {
+                NumericKeypad numericKeypad = new NumericKeypad(m_pos);
+                numericKeypad.setMinus(true);
+                numericKeypad.setPercent(false);
+                m_cardEdit.setText(numericKeypad.openDlg());
+            } catch (Exception e) {
+                Debug.logError(e, module);
+            }
+            m_dialog.repaint();
+        }
+        return;
+    }
+
+    public synchronized void search() {
+        if (wasMouseClicked()) {
+            String name = m_nameEdit.getText().trim();
+            String email = m_emailEdit.getText().trim();
+            String phone = m_phoneEdit.getText().trim();
+            String card = m_cardEdit.getText().trim();
+            searchClientProfile(name, email, phone, card);
+        }
+    }
+
+    public synchronized void edit(String editType) {
+        if (wasMouseClicked()) {
+            String name = m_nameEdit.getText().trim();
+            String email = m_emailEdit.getText().trim();
+            String phone = m_phoneEdit.getText().trim();
+            String card = m_cardEdit.getText().trim();
+            if (UtilValidate.isNotEmpty(name)
+                    && UtilValidate.isNotEmpty(email)
+                    && UtilValidate.isNotEmpty(phone)
+                    && UtilValidate.isNotEmpty(card)
+                    ) {
+                editClientProfile(name, email, phone, card, editType, m_partyId);
+            } else {
+                m_pos.showDialog("dialog/error/exception", UtilProperties.getMessage(PosTransaction.resource, "PosAllFieldsAreRequired", locale));
+            }
+        }
+    }
+
+    private void searchClientProfile(String name, String email, String  phone, String card) {
+        final ClassLoader cl = this.getClassLoader(m_pos);
+        Thread.currentThread().setContextClassLoader(cl);
+        List<Map<String, String>> partyList = m_trans.searchClientProfile(name, email, phone, card, m_pos);
+        boolean first = true;
+        m_clientListCombo.removeAll();
+        m_clientListBidingCombo.clear();
+        if (UtilValidate.isNotEmpty(partyList)) {
+            for (Map<String, String> party : partyList) {
+                name = (String) party.get("lastName");
+                email = (String) party.get("infoString");
+                phone = (String) party.get("contactNumber");
+                String partyId = (String) party.get("partyId");
+                m_clientListBidingCombo.add(partyId);
+                card = (String) party.get("memberId");
+                name = name == null ? "" : name;
+                email = email == null ? "" : email;
+                phone = phone == null ? "" : phone;
+                card = card == null ? "" : card;
+                if (first) { // Most of the time the 1st is enough...
+                    m_nameEdit.setText(name);
+                    m_emailEdit.setText(email);
+                    m_phoneEdit.setText(phone);
+                    m_cardEdit.setText(card);
+                    m_partyId = partyId;
+                }
+                m_clientListCombo.addItem(name + " | " + email + " | " + phone + " | " + card);
+
+                first = false;
+            }
+        }
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        XComboBox clientListCombo = (XComboBox) e.getSource();
+        String client = (String) clientListCombo.getSelectedItem();
+        if (UtilValidate.isNotEmpty(client)) {
+            String[] clientInfos = client.split(" \\| ");
+            if (clientInfos.length > 0) m_nameEdit.setText(clientInfos[0]);
+            if (clientInfos.length > 1) m_emailEdit.setText(clientInfos[1]);
+            if (clientInfos.length > 2) m_phoneEdit.setText(clientInfos[2]);
+            if (clientInfos.length > 3) m_cardEdit.setText(clientInfos[3]);
+            m_partyId = m_clientListBidingCombo.get(clientListCombo.getSelectedIndex());
+        }
+    }
+
+    private void editClientProfile(String name, String email,String  phone, String card, String editType, String partyId) {
+        final ClassLoader cl = this.getClassLoader(m_pos);
+        Thread.currentThread().setContextClassLoader(cl);
+        String result = m_trans.editClientProfile(name, email, phone, card, m_pos, editType, partyId);
+        if (UtilValidate.isNotEmpty(result)) { // new party ?
+            m_partyId = result;
+        }
+        searchClientProfile(name, email, phone, card); // Only to update the combo
+    }
+
+    public synchronized void select() {
+        if (wasMouseClicked() && UtilValidate.isNotEmpty(m_partyId)) {
+            m_dialog.closeDlg();
+        }
+    }
+
+    private ClassLoader getClassLoader(PosScreen pos) {
+        ClassLoader cl = pos.getClassLoader();
+        if (cl == null) {
+            try {
+                cl = Thread.currentThread().getContextClassLoader();
+            } catch (Throwable t) {
+            }
+            if (cl == null) {
+                Debug.log("No context classloader available; using class classloader", module);
+                try {
+                    cl = this.getClass().getClassLoader();
+                } catch (Throwable t) {
+                    Debug.logError(t, module);
+                }
+            }
+        }
+        return cl;
+    }
+}

Modified: ofbiz/trunk/specialpurpose/pos/styles/posstyles.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/styles/posstyles.xml?rev=823475&r1=823474&r2=823475&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/styles/posstyles.xml (original)
+++ ofbiz/trunk/specialpurpose/pos/styles/posstyles.xml Fri Oct  9 09:24:54 2009
@@ -99,6 +99,14 @@
         <font_weight value="1"/>
         <font_italic value="0"/>
     </style>
+    <style name="tip">
+        <color_back value="ffffff"/>
+        <color_fore value="000000"/>
+        <font_face value="verdana"/>
+        <font_size value="10"/>
+        <font_weight value="1"/>
+        <font_italic value="1"/>
+    </style>
 
     <!-- dynamic button styles -->
     <style name="numButton">