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"> |
Free forum by Nabble | Edit this page |