[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue-contrib] r219 - / gnue-invoice/scripts gnue-pointofsale gnue-point
From: |
reinhard |
Subject: |
[gnue-contrib] r219 - / gnue-invoice/scripts gnue-pointofsale gnue-pointofsale/doc gnue-pointofsale/doc/technotes gnue-pointofsale/samples gnue-pointofsale/samples/oldtownemarket gnue-pointofsale/scripts gnue-pointofsale/src gnue-pointofsale/src/backends gnue-pointofsale/src/backends/Base gnue-pointofsale/src/backends/gnue_sb gnue-pointofsale/src/frontends gnue-pointofsale/src/frontends/Base gnue-pointofsale/src/frontends/wx gnue-pointofsale/src/hardware gnue-pointofsale/src/hardware/barcodereader gnue-pointofsale/src/hardware/cashdrawer gnue-pointofsale/src/hardware/logprinter gnue-pointofsale/src/hardware/poledisplay gnue-pointofsale/src/hardware/receiptprinter gnue-pointofsale/src/payments hotline/forms |
Date: |
Sat, 23 Apr 2005 07:05:42 -0500 (CDT) |
Author: reinhard
Date: 2005-04-23 07:05:40 -0500 (Sat, 23 Apr 2005)
New Revision: 219
Added:
gnue-pointofsale/
gnue-pointofsale/AUTHORS
gnue-pointofsale/COPYING
gnue-pointofsale/ChangeLog
gnue-pointofsale/FAQ
gnue-pointofsale/INSTALL
gnue-pointofsale/NEWS
gnue-pointofsale/README
gnue-pointofsale/ROADMAP.in
gnue-pointofsale/TODO
gnue-pointofsale/doc/
gnue-pointofsale/doc/technotes/
gnue-pointofsale/doc/technotes/00000.txt
gnue-pointofsale/doc/technotes/00001.txt
gnue-pointofsale/doc/technotes/index.html
gnue-pointofsale/doc/technotes/index.txt
gnue-pointofsale/samples/
gnue-pointofsale/samples/oldtownemarket/
gnue-pointofsale/samples/oldtownemarket/pos_backend.py
gnue-pointofsale/scripts/
gnue-pointofsale/scripts/gnue-pos.in
gnue-pointofsale/setup-cvs.py
gnue-pointofsale/setup.cfg.in
gnue-pointofsale/setup.cvs
gnue-pointofsale/setup.py
gnue-pointofsale/src/
gnue-pointofsale/src/Config.py
gnue-pointofsale/src/Handler.py
gnue-pointofsale/src/IOProxy.py
gnue-pointofsale/src/POSClient.py
gnue-pointofsale/src/__init__.py
gnue-pointofsale/src/backends/
gnue-pointofsale/src/backends/Base/
gnue-pointofsale/src/backends/Base/Driver.py
gnue-pointofsale/src/backends/Base/__init__.py
gnue-pointofsale/src/backends/__init__.py
gnue-pointofsale/src/backends/gnue_sb/
gnue-pointofsale/src/backends/gnue_sb/Driver.py
gnue-pointofsale/src/backends/gnue_sb/__init__.py
gnue-pointofsale/src/frontends/
gnue-pointofsale/src/frontends/Base/
gnue-pointofsale/src/frontends/Base/Driver.py
gnue-pointofsale/src/frontends/Base/__init__.py
gnue-pointofsale/src/frontends/__init__.py
gnue-pointofsale/src/frontends/wx/
gnue-pointofsale/src/frontends/wx/Driver.py
gnue-pointofsale/src/frontends/wx/NumberDisplay.py
gnue-pointofsale/src/frontends/wx/__init__.py
gnue-pointofsale/src/hardware/
gnue-pointofsale/src/hardware/__init__.py
gnue-pointofsale/src/hardware/barcodereader/
gnue-pointofsale/src/hardware/barcodereader/__init__.py
gnue-pointofsale/src/hardware/cashdrawer/
gnue-pointofsale/src/hardware/cashdrawer/__init__.py
gnue-pointofsale/src/hardware/cashdrawer/bell.py
gnue-pointofsale/src/hardware/cashdrawer/escpos.py
gnue-pointofsale/src/hardware/logprinter/
gnue-pointofsale/src/hardware/logprinter/plain.py
gnue-pointofsale/src/hardware/poledisplay/
gnue-pointofsale/src/hardware/poledisplay/__init__.py
gnue-pointofsale/src/hardware/receiptprinter/
gnue-pointofsale/src/hardware/receiptprinter/__init__.py
gnue-pointofsale/src/hardware/receiptprinter/escpos.py
gnue-pointofsale/src/hardware/receiptprinter/plain.py
gnue-pointofsale/src/payments/
gnue-pointofsale/src/payments/__init__.py
Modified:
gnue-invoice/scripts/setup-db.sh
hotline/forms/hotline-en.gfd
hotline/forms/kunden.gfd
Log:
Moved gnue-pointofsale from gnue to gnue-contrib repository.
Modified: gnue-invoice/scripts/setup-db.sh
===================================================================
--- gnue-invoice/scripts/setup-db.sh 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-invoice/scripts/setup-db.sh 2005-04-23 12:05:40 UTC (rev 219)
@@ -1,6 +1,6 @@
#!/bin/sh
-GNUEDIR="/home/gabor/SVN/gnue"
+GNUEDIR="/home/reinhard/prj/gnue"
PACKAGEDIR="$GNUEDIR/gnue-packages"
DATADIR=`echo -e "import gnue.paths\nprint gnue.paths.data" | gcvs`
Added: gnue-pointofsale/AUTHORS
===================================================================
--- gnue-pointofsale/AUTHORS 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/AUTHORS 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,4 @@
+Jason Cater <address@hidden>:
+ Primary Author
+
+If we've missed anyone, please let us know.
Added: gnue-pointofsale/COPYING
===================================================================
--- gnue-pointofsale/COPYING 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/COPYING 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Added: gnue-pointofsale/ChangeLog
===================================================================
Added: gnue-pointofsale/FAQ
===================================================================
Added: gnue-pointofsale/INSTALL
===================================================================
Added: gnue-pointofsale/NEWS
===================================================================
Added: gnue-pointofsale/README
===================================================================
--- gnue-pointofsale/README 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/README 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,79 @@
+GNUe Point of Sale: A tool of the GNUe Project (www.gnue.org)
+
+Introduction
+------------
+GNUe-PoS is the Point of Sale register program for the GNUe system.
+It is designed to work with your existing schema.
+
+Requirements
+------------
+ * Python 2.1+
+ * wxPython 2.4+
+ * GNUe Common
+ * GNUe Forms (w/Wx Drivers)
+ * GNUe Reports
+ * GNUe Small Business (Or a custom backend)
+ * Appropriate Hardware as needed (Receipt printers, pole displays, etc)
+
+It currently requires wxPython 2.4 or greater, so it will work on
+Win32, GTK (Linux/*BSD), and MacOSX.
+
+Installation
+------------
+Please see INSTALL for installation instructions.
+
+Features
+--------
+Short-term Goals:
+
+ Commission tracking
+ Discounts
+ * Per-item or Per-ticket
+ * Flat Reduction or Percentage
+ * Before-tax or after-tax
+ Customer support
+ * Buying on Account
+ * Automatic trade/store credit
+ Product Options
+ Non-inventoried transactions
+ * add description/department/price at time of sale
+ Mouse-less operation
+ Multiple printer support
+ Display Pole support
+ Manually keyed items
+ Tax exempt purchases
+
+Long-term Goals:
+
+ Credit Card backend support
+ Touch-screen support
+
+Hardware Support:
+
+ Input
+ * POS Keyboards
+ * Barcode Readers
+ * MICR/Check readers
+ * Toucscreen (transparent to us?)
+ Output
+ * Receipt Printers
+ * Cash Drawer
+ * Pole Display
+
+Backend Accounting:
+
+ * LanePOS
+ * GNUe Small Business
+ * GNUe Financials
+
+Payment Processing:
+
+ * Debit
+ * Credit
+ * On Account
+ * Check Guarantee
+
+License
+-------
+GNU Enterprise is free software. See the file `COPYING' for the terms and
+conditions for copying, distribution and modification.
Added: gnue-pointofsale/ROADMAP.in
===================================================================
Added: gnue-pointofsale/TODO
===================================================================
Added: gnue-pointofsale/doc/technotes/00000.txt
===================================================================
--- gnue-pointofsale/doc/technotes/00000.txt 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/doc/technotes/00000.txt 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,19 @@
+Title: GNUe Point-of-Sale Tech Note Specification
+Status: Current
+Created: 2002-07-17
+Revised: 2002-07-17
+
+This technote describes the format of technotes. A technote should be in
+plain text (ASCII) format. They should be numbered sequentially.
+
+The file consists of two sections, the header section and the text section.
+The header consists of line-delimited "field: value" pairs. Valid headers:
+
+ Title: <The title of this technote> (Required)
+ Status: <Current|Deprecated|Obsolete> (Required)
+ Created: <Creation date in YYYY-MM-DD format>
+ Revised: <Last revision date in YYYY-MM-DD format>
+
+The header section is terminated with the first non-blank line.
+
+
Added: gnue-pointofsale/doc/technotes/00001.txt
===================================================================
--- gnue-pointofsale/doc/technotes/00001.txt 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/doc/technotes/00001.txt 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,54 @@
+Title: Internal Events
+Status: Current
+Created: 2003-06-18
+
+User-Initiated Events
+=====================
+RequestBeginTicket
+RequestEndTicket
+RequestSuspendTicket
+RequestResumeTicket
+RequestCancelTicket
+RequestPriceLookup
+RequestTender
+RequestAddItem
+RequestRemoveItem
+RequestCancelLastItem
+RequestCancelItem
+RequestDuplicateLastItem
+RequestDiscount
+RequestExit
+RequestLogOut
+RequestQuantity
+RequestTaxExempt
+
+
+Data-Related Events
+===================
+UpdateTotals
+UpdateQuantity
+
+DiscountItem
+DiscountTicket
+
+BeginTicket
+EndTicket
+SuspendTicket
+ResumeTicket
+CancelTicket
+
+TenderTicket
+
+AddTicketItem
+CancelTicketItem
+
+PriceLookup
+
+BeginManualItem
+EndManualItem
+
+RequestManualDepartment
+RequestManualDescription
+RequestManualBasePrice
+RequestManualPrice
+
Added: gnue-pointofsale/doc/technotes/index.html
===================================================================
--- gnue-pointofsale/doc/technotes/index.html 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/doc/technotes/index.html 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,26 @@
+
+<html>
+<title>
+Tech Notes Index
+</title>
+<body>
+<h1>GNUe Point-of-Sale Tech Notes Index</h1>
+
+
+<h3>Current Tech Notes</h3>
+
+<table border="1" width="100%">
+<tr><th>File</th><th>Title</th></tr>
+
+<tr><td><a href="00000.txt">00000.txt</a></td><td>GNUe Point-of-Sale Tech Note
Specification</td></tr>
+<tr><td><a href="00001.txt">00001.txt</a></td><td>Internal Events</td></tr>
+</table>
+
+
+
+
+<hr>
+<p>This file automatically created by
+common/utils/create-technote-index.py</p>
+</body>
+</html>
Added: gnue-pointofsale/doc/technotes/index.txt
===================================================================
--- gnue-pointofsale/doc/technotes/index.txt 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/doc/technotes/index.txt 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,19 @@
+
+GNUe Point-of-Sale Tech Notes Index
+
+
+==============================================================================
+Current Tech Notes
+==============================================================================
+
+File Title
+---------- ------------------------------------------------------------------
+00000.txt GNUe Point-of-Sale Tech Note Specification
+00001.txt Internal Events
+---------- ------------------------------------------------------------------
+
+
+
+--------
+This file automatically created by
+common/utils/create-technote-index.py
Added: gnue-pointofsale/samples/oldtownemarket/pos_backend.py
===================================================================
--- gnue-pointofsale/samples/oldtownemarket/pos_backend.py 2005-04-19
12:09:26 UTC (rev 218)
+++ gnue-pointofsale/samples/oldtownemarket/pos_backend.py 2005-04-23
12:05:40 UTC (rev 219)
@@ -0,0 +1,241 @@
+#
+# Copyright 2003 Jason Cater
+#
+# FILE:
+# cater/pos_backend.py
+#
+# DESCRIPTION:
+# Custom backend for my schema
+#
+# NOTES:
+#
+
+from gnue.pointofsale.backends.Base.Driver import Driver as BaseDriver
+from gnue.common.datasources import GConditions
+from gnue.common.datasources.GDataSource import DataSourceWrapper
+from random import randint
+
+CONN = gConfig('BackendConnection')
+MANUAL_SKU = gConfig('ManualItemSKU')
+
+class Driver(BaseDriver):
+ def init(self):
+ self.__totals = {}
+ self.registerEventListeners({
+ 'ProcessSKU': self._ProcessSKU,
+ 'EmployeeLogin': self._EmployeeLogin,
+# 'EndManualItem': self._EndManualItem,
+ 'RequestBeginTicket': self._RequestBeginTicket,
+ 'BeginLayaway': self._BeginLayaway,
+ 'BeginTicket': self._BeginTicket,
+ 'EndTicket': self._EndTicket,
+ 'CancelTicket': self._CancelTicket,
+ 'VerifyLogin': self._VerifyLogin,
+ 'AddDiscount': self._AddDiscount,
+ 'AddTender': self._AddTender,
+ 'AddTicketItem': self._AddTicketItem,
+ 'UpdateTotal': self._UpdateTotal,
+ 'CancelTicketItem': self._CancelTicketItem,
+ 'TaxExemptionEntered': self._TaxExemptionEntered,
+ 'Receipt:GetNotice': self._GetFooter
+})
+ self.__dealermap = {}
+
+ def _EmployeeLogin(self, event):
+ self._login = event.id
+
+ def _VerifyLogin(self, event):
+
+ resultset = self._getResultSet('employees', ('id',
'first_name','last_name'),
+ conditions={'login': event.login, 'password': event.password,
'active':'Y'})
+
+ rec = resultset.firstRecord()
+ if not rec:
+ self.dispatchEvent('Warning',message='Invalid Login')
+ event.setResult(1)
+ return
+
+ self.dispatchEvent('EmployeeLogin',
+ name='%s' % (rec['first_name']),
+ id=rec['id'],
+ login=event.login)
+
+
+ def _ProcessSKU(self, event):
+ sku = event.sku
+ origEvent= event.origEvent
+ event.setResult(1)
+ if not hasattr(event,'finalEvent'):
+ event.finalEvent = 'AddTicketItem'
+
+ if sku and sku == MANUAL_SKU: # Manually Keyed Item
+ # Special item...
+ origEvent.dispatchAfter('BeginManualItem', sku=sku,
quantity=event.quantity)
+ event.setResult(0)
+
+ elif 1 <= len(sku) <= 3:
+ # Booth number...
+ rs = self._getResultSet('booths', ('dealer',), {'booth': sku})
+ rec = rs.firstRecord()
+ if not rec:
+ self.dispatchEvent('Warning',message='Invalid Dealer Code')
+ return
+
+ self.__dealermap[sku] = rec['dealer']
+
+ origEvent.dispatchAfter('BeginManualItem', sku=sku,
quantity=event.quantity)
+ event.setResult(0)
+
+ else:
+ # Regular item...
+ price = 10
+ description = 'Foobar'
+## self.dispatchEvent(event.finalEvent, sku=sku, description=description,
quantity=event.quantity, price=price, extended=round(event.quantity*price,2),
taxable=1)
+
+ if 0: # requiresQuantity
+ origEvent.dispatchAfter('RequestQuantity')
+
+
+
+ def _RequestBeginTicket(self, event):
+ datasource = DataSourceWrapper(self.instance.connections,
+ attributes={'connection': CONN,
+ 'name': 'dtsTicket',
+ 'table': 'tickets' } )
+
+ self.__ticket = serial =
datasource.extensions.getSequence('pos_ticket_id_seq')
+
+ self.dispatchEvent('BeginTicket', serial=serial)
+
+
+ def _EndTicket(self, event):
+
+ # Insert the ticket
+ ts = self._createResultSet('pos_tickets', ('id','clerk','station',
+ 'tax_exemption','subtotal',
+ 'tax','total'))
+ tr = ts.insertRecord()
+ tr['id'] = self.__ticket
+ tr['clerk'] = self._login
+ tr['station'] = self.instance.registername
+ tr['tax_exemption'] = self.__taxExempt
+ tr['subtotal'] = self.__totals['subtotal']
+ tr['tax'] = self.__totals['tax']
+ tr['total'] = self.__totals['total']
+
+
+ # Then the items...
+ irs = self._createResultSet('pos_ticket_items', ('ticket_id','quantity',
+ 'manual_item','department',
+ 'sku','description',
+
'base_amount','unit_amount',
+ 'amount','taxable'))
+ for item in self.__items.values():
+ ir = irs.insertRecord()
+ ir['ticket_id'] = self.__ticket
+ ir['quantity'] = item.quantity
+ ir['manual_item'] = len(item.sku) <= 3 and 'Y' or 'N'
+ ir['department'] = item.department
+ ir['sku'] = item.sku
+ ir['description'] = item.description
+ ir['base_amount'] = item.base
+ ir['unit_amount'] = item.each
+ ir['amount'] = item.extended
+ ir['taxable'] = item.taxable and 'Y' or 'N'
+ try:
+ ir['dealer'] = self.__dealermap[item.sku]
+ except KeyError:
+ pass
+
+ # and the payments...
+ trs = self._createResultSet('pos_ticket_payments',
('ticket_id','payment_type',
+
'payment_amount','approval_code'))
+ for tender in self.__tenders:
+ tr = trs.insertRecord()
+ tr['ticket_id'] = self.__ticket
+ tr['payment_type'] = tender.type
+ tr['payment_amount'] = tender.amount
+ try:
+ tr['approval_code'] = tender.extra
+ except:
+ pass
+
+ ts.post()
+ irs.post()
+ trs.post()
+ self.instance.connections.commitAll()
+
+ self.__ticket = 0
+
+
+ def _UpdateTotal(self, event):
+ self.__totals[event.field] = event.amount
+
+
+ def _CancelTicket(self, event):
+ self.__ticket = 0
+
+
+ def _BeginTicket(self, event):
+ self.__layaway = 0
+ self.__items = {}
+ self.__totals = {}
+ self.__tenders = []
+ self.__taxExempt = None
+
+ def _BeginLayaway(self, event):
+ self.__layaway = 1
+
+ def _TaxExemptionEntered(self, event):
+ if event.value:
+ self.__taxExempt = event.value
+ else:
+ self.__taxExempt = None
+
+ def _AddDiscount(self, event):
+ pass
+
+ def _AddTender(self, event):
+ self.__tenders.append(event)
+
+ def _AddTicketItem(self, event):
+ self.__items[event.lineitem] = event
+
+ def _CancelTicketItem(self, event):
+ del self.items[event.lineitem]
+
+
+ def _GetFooter(self, event):
+ i = randint(0, len(_FooterChoices)-1)
+ print "Quote #%s" % i
+ event.setResult(_FooterChoices[i])
+
+
+_FooterChoices = (
+"""\
+Did you know? Old Towne Market has
+a professional portrait studio. Let
+us take your next family portrait,
+senior picture, or holiday photo.""",
+"""\
+Old Towne Market has something for
+everyone! From antiques, artwork,
+reproductions, and pottery, to
+children's clothing and glassware.""",
+"""\
+Add Old Towne Market to your
+shopping list this coming holiday
+season. We offer gift certificates
+for your convenience.""",
+"""\
+Old Towne Market now carries
+Peter's Pottery. Ask about our
+custom orders.""",
+"""\
+Know a special little girl with
+an upcoming birthday? Old Towne
+Market now hosts tea parties!"""
+)
+
+
+
Added: gnue-pointofsale/scripts/gnue-pos.in
===================================================================
--- gnue-pointofsale/scripts/gnue-pos.in 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/scripts/gnue-pos.in 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003 Free Software Foundation
+#
+
+import os
+import sys
+
+__GNUEENV__
+
+if not os.environ.has_key('GNUE_CONNECTIONS'):
+ if os.path.isfile(INST_GNUE_CONNECTIONS):
+ os.environ['GNUE_CONNECTIONS'] = INST_GNUE_CONNECTIONS
+
+from gnue.pointofsale.POSClient import POSClient
+
+if __name__ == '__main__':
+ POSClient().run()
+
Property changes on: gnue-pointofsale/scripts/gnue-pos.in
___________________________________________________________________
Name: svn:executable
+ *
Added: gnue-pointofsale/setup-cvs.py
===================================================================
--- gnue-pointofsale/setup-cvs.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/setup-cvs.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,301 @@
+#!/usr/bin/env python
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+
+import sys, string, os, glob
+
+
+BASEDIR = os.path.abspath(os.path.join(os.getcwd(), '..'))
+
+rootCommands = []
+
+def createCVS (scriptdir,script,py):
+ script = "%s%s" % (script, SUFFIX)
+ print "Creating %s" % os.path.join(scriptdir, script)
+ file = open(os.path.join(scriptdir, script),'w')
+ file.write(cvsbase % py)
+ file.close()
+ os.system ('chmod 700 %s/%s/%s' % (CVSDIR,scriptdir, script))
+
+ rootCommands.append ('rm -f %s/%s' % (BINDIR, script))
+ rootCommands.append ('ln -s %s/%s/%s %s/%s' % \
+ (CVSDIR, scriptdir, script, BINDIR, script))
+ rootCommands.append ('chmod o+x %s/%s/%s' % (CVSDIR,scriptdir, script))
+
+
+def createDocs(sgmlfile, destdir):
+ sgmlfile = os.path.join(CVSDIR, sgmlfile)
+ destdir = os.path.join(DOCDIR, destdir)
+ rootCommands.append("if [ ! -d %s ]; then mkdir %s; fi" % (destdir, destdir))
+ rootCommands.append("%s --output %s %s" %
+ (DB2HTML, destdir, sgmlfile))
+
+
+def getInput(message, default, responseSet=None):
+ print ""
+ while 1:
+ if default != None:
+ print "%s [%s] " % (message, default),
+ else:
+ print "%s " % (message),
+
+ val = string.strip(sys.stdin.readline())
+ print ""
+
+ if not len(val) and default != None:
+ return default
+ elif responseSet and string.upper(val) in (responseSet):
+ return string.upper(val)
+ elif not responseSet:
+ return val
+
+
+def getYesNo(message, default=None):
+ return getInput(message,default,('Y','N')) == 'Y'
+
+
+def getBinPaths():
+ paths = string.split(os.environ['PATH'],os.pathsep)
+ if not ('/usr/local/bin' in paths or '/usr/local/bin/' in paths) and \
+ os.path.isdir('/usr/local/bin'):
+ paths.append('/usr/local/bin')
+ return(paths)
+
+
+# Returns a list containing all Python executables in the user's path.
+# List element 0 will always be the currently running executable
+def findAllPythonExes():
+ results = [sys.executable]
+
+ for path in getBinPaths():
+ for file in glob.glob('%s/python?*' % os.path.abspath(string.strip(path))):
+ base = os.path.basename(file)
+ version = base[6:]
+
+ # Do not include python 1.x files
+ if version < '2':
+ break
+
+ if os.path.samefile(file, sys.executable):
+ # If this file is the one being executed, just replace w/full name
+ if results[0] == sys.executable:
+ results[0] = file
+ else:
+ results.append(file)
+
+ return results
+
+
+def finddb2html():
+ for path in getBinPaths():
+ for file in glob.glob('%s/db2html' % os.path.abspath(string.strip(path))):
+ return(file)
+
+ # Nothing found
+ return "";
+
+
+def restartWithExecutable(exe):
+ os.system('%s %s --withNewExecutable "%s"' \
+ % (exe, sys.argv[0], string.join(sys.argv[1:],'" "')))
+ sys.exit()
+
+
+restarting = ('--withNewExecutable' in sys.argv)
+
+if not restarting:
+ print """
+GNU Enterprise Developer Setup
+
+This script will install the GNU Enterprise tools to run
+from a CVS copy. This allows GNUe to be run without a
+full installation. THIS IS PRIMARILY USEFUL TO DEVELOPERS.
+ """
+
+# First of all, make sure this is a current enough Python release.
+try:
+ if sys.hexversion < 0x02000000:
+ raise AttributeError
+except AttributeError:
+
+ print "-" * 70
+ print """
+ You are running Python %s.
+
+ GNU Enterprise requires at least Python 2.0 (recommended: 2.1+).
+ If you have a later version installed, you should run setup.py
+ against that version. For example, if you have Python 2.1
+ installed, you may need to run:
+
+ python2.1 %s
+""" % (string.split(sys.version)[0], sys.argv[0])
+ print "-" * 70
+
+ exes = findAllPythonExes()
+
+ if len(exes) == 1:
+ sys.exit()
+ else:
+
+ # There are better versions of Python installed...
+
+ exes.pop(0)
+ print "\n"
+ print "I have found the following Python executables. "
+ print "Choose another version of Python to run."
+ print ""
+
+ validOptions = []
+ i = 0
+
+ for file in exes:
+ i = i + 1 # Do not change this to i += 1 as that's >= py2.x
+ validOptions.append(str(i))
+ print " [%s] %s" % (i, file)
+
+ validOptions.append ('Q')
+ selection = getInput(
+ "Please enter the number of the Python executable to\n"
+ 'use [1-%s] or enter "q" to quit.' % i, '1', validOptions)
+
+ if selection == 'Q':
+ sys.exit()
+
+ restartWithExecutable(exes[int(selection)-1])
+
+
+
+
+try:
+ import posixpath
+except ImportError:
+ print "This CVS setup script will currently only install on a POSIX-based"
+ print "system. To install on non-POSIX systems, you will have to install"
+ print "each individual tool using it's 'setup.py install' script."
+ sys.exit()
+
+while 1:
+ BASEDIR = os.path.abspath(
+ getInput ("Where is your cvs install of the GNUe tools located?",
BASEDIR))
+ _BASEDIR = BASEDIR
+
+ try:
+ f = open(os.path.join(BASEDIR,'.cvs-config'))
+ break
+ except:
+ print """\
+I am unable to find the .cvs-config file created by the GNUe Tools'
+setup-cvs.py script. Have you run this script (recently)?
+"""
+text = f.read()
+f.close()
+exec(text)
+
+# Reset CVSDIR
+CVSDIR = os.path.abspath(os.getcwd())
+
+newdirs = [ ]
+for dir in newdirs:
+ rootCommands.append("if [ ! -d %s ]; then mkdir %s; fi" % (dir,dir))
+
+
+cvsbase = """#!/bin/sh
+ if [ "z$GNUE_CONNECTIONS" = "z" ]
+ then
+ if [ -f %(CONFDIR)s/etc/connections.conf ]
+ then
+ GNUE_CONNECTIONS=%(CONFDIR)s/etc/connections.conf
+ export GNUE_CONNECTIONS
+ fi
+ fi
+ if [ "z$INSTALL_PREFIX" = "z" ]
+ then
+ INSTALL_PREFIX=%(CONFDIR)s
+ export INSTALL_PREFIX
+ fi
+ PYTHONPATH=%(BASEDIR)s:$PYTHONPATH; export PYTHONPATH
+ SCRIPT="%%s"
+ if [ "$SCRIPT" != "" ]
+ then
+ %(PYTHONBIN)s %(GNUEDIR)s/${SCRIPT} "$@"
+ else
+ %(PYTHONBIN)s "$@"
+ fi
+ """ % globals()
+
+
+
+os.system ("""
+ cd %(GNUEDIR)s
+ rm -f pointofsale
+ ln -s %(CVSDIR)s/src pointofsale
+""" % globals() )
+
+
+rootCommands.append("""
+
+#rm -f %(CONFDIR)s/shared/images/pointofsale
+#ln -s %(CVSDIR)s/pointofsale/images %(CONFDIR)s/shared/images/pointofsale
+""" % globals() )
+
+
+createCVS ('scripts','gnue-pos-cvs','pointofsale/POSClient.py')
+
+
+if ROOTINSTALL:
+
+ out = open("setup-root.sh",'w')
+ out.write("#!/bin/sh\n")
+ out.write(string.join(rootCommands,"\n"))
+ out.write("\n")
+ out.close()
+
+ print ""
+ print "All the commands that need to be run as root have been written"
+ print "to setup-root.sh . In order for your setup to be complete, this"
+ print "file must be run. This setup script can run setup-root.sh for"
+ print "you. If you choose to run the script now and are not currently"
+ print "logged in as root, you will be prompted for the root password."
+ if getYesNo('Run "/bin/sh setup-root.sh" as root?','Y'):
+ os.system('su root -c "/bin/sh setup-root.sh"')
+ else:
+ print ""
+ print 'Do not forget to run "/bin/sh setup-root.sh" as root'
+ print ""
+
+else:
+
+ out = open("setup.log",'w')
+ out.write(string.join(rootCommands,"\n"))
+ out.write("\n")
+ out.close()
+
+ os.system(string.join(rootCommands,'\n'))
+
+
+#
+# Save our config settings
+#
+from pprint import pformat
+c = open (os.path.join(CVSDIR,'.cvs-config'),'w')
+for key, val in globals().items():
+ if key[0].isupper():
+ c.write('%s=%s\n\n' % (key, pformat(val)))
Property changes on: gnue-pointofsale/setup-cvs.py
___________________________________________________________________
Name: svn:executable
+ *
Added: gnue-pointofsale/setup.cfg.in
===================================================================
--- gnue-pointofsale/setup.cfg.in 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/setup.cfg.in 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,46 @@
+#
+# Copyright 2001-2003 Free Software Foundation
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+[install]
+
+
+# Where to install GNUe's application files...
+prefix = /usr/local/gnue
+
+# Where to install GNUe executable symlinks...
+exec_prefix = /usr/local/bin
+
+
+
+###############################################
+#
+# We recommend you do not change anything below
+# this line unless you know what you are doing
+#
+###############################################
+
+install_lib=%(prefix)s/lib/python
+install_data=%(prefix)s
+install_scripts=%(exec_prefix)s
+
+[bdist_rpm]
+doc_files = README, README.curses, samples
+
Added: gnue-pointofsale/setup.cvs
===================================================================
--- gnue-pointofsale/setup.cvs 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/setup.cvs 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,30 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2001-2003 Free Software Foundation
+#
+# ********************
+# NOTE:
+# This file is parsed/run by gnue-common's setup-cvs.py script.
+# If you are attempting to set up a CVS install environment, please
+# run that file. This file is not a standalone script.
+# ********************
+#
+
+linkModule('src/','pointofsale')
+
Added: gnue-pointofsale/setup.py
===================================================================
--- gnue-pointofsale/setup.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/setup.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+
+import sys
+import string
+import os
+import os.path
+
+from src import VERSION
+
+try:
+ import py2exe
+except:
+ pass
+
+
+#
+# hack to deal w/ fact distutils won't
+# allow us to set absolute path prefix
+# on windows
+#
+
+if not 'sdist' in sys.argv:
+ if sys.platform != 'win32' and '--prefix' not in sys.argv and '--root' not
in sys.argv:
+ os.system ("""cp setup.cfg.in setup.cfg""")
+ else:
+ try:
+ os.remove('setup.cfg')
+ except:
+ pass
+
+
+
+
+
+try:
+ from distutils.core import setup
+ from distutils.command.build_scripts import build_scripts
+except ImportError:
+ print """
+Setup requires that python's distutils be
+installed. You can get a copy of it from
+http://www.python.org/sigs/distutils-sig/
+ """
+ sys.exit()
+
+
+if 'sdist' in sys.argv:
+
+ print "Now, we are going to create the man pages for our tools."
+ os.system( """
+if [ ! -e man ]
+then
+mkdir man
+fi
+cd man
+../scripts/gnue-pos-cvs --generate-man-page
+""")
+
+
+# Site config stuff
+try:
+ index = sys.argv.index('--cfg-file')
+ site_config = os.path.join(os.path.abspath(sys.argv[index+1]))
+ sys.argv.pop(index)
+ sys.argv.pop(index)
+ config_line = "os.environ['GNUE_INSTALLED_SITE_CFG']='%s'\n" % site_config
+
+except ValueError:
+ config_line = ""
+
+#if ('build' in sys.argv) or ('install' in sys.argv):
+# # Verify that gnue-common is installed
+# try:
+# print "Checking for GNUe-Common....",
+# from gnue import common
+# if common.__dict__.has_key('VERSION'):
+# print "OK (version %s)" % common.VERSION
+# else:
+# print "OK"
+# except ImportError:
+# print """
+#You will need to install gnue-common
+#before gnuef will function. You can
+#obtain a copy from
+#
+#http://www.gnuenterprise.org/download.php
+#"""
+# sys.exit()
+
+
+
+class my_build_scripts(build_scripts):
+ def finalize_options(self):
+
+ build_scripts.finalize_options(self)
+
+ if self.finalized:
+ return
+
+
+ if sys.platform != 'win32':
+ dict = self.distribution.get_option_dict("install")
+ install_prefix = dict['prefix'][1]
+
+ gnue_env = \
+ "#######\n" \
+ + "# The following variable were set when GNUe was installed\n" \
+ + "import os, sys\n" \
+ + "sys.path.append('%s')\n" % dict['install_lib'][1] \
+ + "INST_GNUE_CONNECTIONS='%s/etc/connections.conf'\n" %
dict['prefix'][1] \
+ + "os.environ['INSTALL_LIB']='%s'\n" % dict['install_lib'][1] \
+ + "os.environ['INSTALL_PREFIX']='%s'\n" % dict['prefix'][1] \
+ + config_line \
+ + "#######\n"
+ else:
+ gnue_env = \
+ "#######\n" \
+ + "# The following variables were set when GNUe was installed\n"
\
+ + "# (Generated for a Win32 system)\n" \
+ + "import os, sys\n" \
+ + "if __name__ == '__main__': \n" \
+ + " _BASE =
os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),'..'))\n" \
+ + " try:\n" \
+ + " os.environ['PATH']=
os.path.abspath(os.path.dirname(sys.argv[0])) + ';' + os.environ['PATH']\n" \
+ + " except KeyError:\n" \
+ + " os.environ['PATH']=
os.path.abspath(os.path.dirname(sys.argv[0]))\n" \
+ + "else: \n" \
+ + " _BASE =
os.path.abspath(os.path.join(os.path.dirname(__file__),'..'))\n" \
+ +
"INST_GNUE_CONNECTIONS=os.path.join(_BASE,'etc','connections.conf')\n" \
+ + "os.environ['INSTALL_PREFIX']=_BASE\n" \
+ + "os.environ['INSTALL_LIB']=_BASE\n" \
+ + "os.putenv('PYTHONCASEOK','1')\n" \
+ + config_line \
+ + "if os.path.isdir(os.path.join(_BASE,'extras')):\n" \
+ + " sys.path.append(os.path.join(_BASE,'extras'))\n" \
+ + "#######\n\n"
+
+ for script in self.scripts:
+ print "Building %s..."% (script),
+
+
+ fin = open(script+".in", "r")
+ fout = open(script, "w")
+
+ print "Generating script %s from %s.in" % (script,script)
+
+ lines = fin.readlines()
+
+ for i in range(0, len(lines)):
+ if string.strip(lines[i]) == "__GNUEENV__":
+ lines[i] = gnue_env
+
+ fout.writelines(lines)
+ fin.close()
+ fout.close()
+ print "OK"
+
+
+docfiles = []
+##for file in ('doc/ReportingConcepts.txt',
+## 'doc/ReportingConcepts.pdf'):
+## if os.path.isfile(file):
+## docfiles.append(file)
+## else:
+## print "WARNING: File %s does not exist... not installing!" % file
+
+manfiles = []
+for file in ('man/gnue-pos.1',):
+ if os.path.isfile(file):
+ manfiles.append(file)
+ else:
+ print "WARNING: File %s does not exist... not installing!" % file
+
+
+#
+# You can run:
+# $ GNUE_VERSION_SUFFIX=-pre1 ./setup.py sdist
+# and the packages will be created as GNUe-App-0.x.x-pre1.tar.gz
+#
+try:
+ suffix = os.environ['GNUE_VERSION_SUFFIX']
+except KeyError:
+ suffix = ""
+
+
+setup (name = "GNUe Point-of-Sale",
+ version = VERSION+suffix,
+ description = "GNUe Point-of-Sale",
+ long_description = "",
+ author = "GNUe Team",
+ author_email = "address@hidden",
+ url = "http://www.gnue.org",
+
+ # Override certain command classes with our own ones
+ cmdclass = {'build_scripts':my_build_scripts},
+
+ data_files = [ ('doc/pointofsale', docfiles),
+ ('man/man1', manfiles) ],
+
+ packages = ["gnue.pointofsale",
+ "gnue.pointofsale.backends",
+ "gnue.pointofsale.backends.Base",
+ "gnue.pointofsale.backends.gnue_sb",
+ "gnue.pointofsale.frontends",
+ "gnue.pointofsale.frontends.Base",
+ "gnue.pointofsale.frontends.wx",
+ "gnue.pointofsale.hardware",
+ "gnue.pointofsale.hardware.cashdrawer",
+ "gnue.pointofsale.hardware.barcodereader",
+ "gnue.pointofsale.hardware.receiptprinter",
+ "gnue.pointofsale.hardware.poledisplay",
+ "gnue.pointofsale.payments",
+ ],
+
+ package_dir = {"gnue.pointofsale" : "src"},
+
+ scripts = ["scripts/gnue-pos"]
+ )
+
+if 'install' in sys.argv:
+ print """
+ Note:
+ Warnings about the files not being installed in pythons search path can be
ignored.
+
+ Make sure you have a default gnue.conf file (typically in
/usr/local/gnue/etc.
+ A sample is provided in that directory that you can typically just copy
over.
+ """
+
+if not 'sdist' in sys.argv:
+ if sys.platform != 'win32':
+ os.system (""" /bin/rm -rf setup.cfg""")
Property changes on: gnue-pointofsale/setup.py
___________________________________________________________________
Name: svn:executable
+ *
Added: gnue-pointofsale/src/Config.py
===================================================================
--- gnue-pointofsale/src/Config.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/Config.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,137 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# GRConfig.py
+#
+# DESCRIPTION:
+#
+# NOTES:
+#
+from gnue.common.formatting import GTypecast
+
+ConfigOptions = (
+
+ { 'Name' : 'BackendConnection',
+ 'Type' : 'Setting',
+ 'Comment' : 'The connection name to use for sales data.',
+ 'Description': 'The connection name to use for sales data.',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'gnuesb' },
+
+ { 'Name' : 'BackendProvider',
+ 'Type' : 'Setting',
+ 'Comment' : 'The backend provider to use for data.',
+ 'Description': 'The backend provider to use for data.',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'gnue_sb' },
+
+ { 'Name' : 'FrontendUI',
+ 'Type' : 'Setting',
+ 'Comment' : 'The frontend user interface.',
+ 'Description': 'The frontend user interface.',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'wx' },
+
+ { 'Name' : 'ManualItemSKU',
+ 'Type' : 'Setting',
+ 'Comment' : 'The SKU to use for manually keyed items.',
+ 'Description': 'The SKU to use for manually keyed items. (Can be empty to
disable)',
+ 'Typecast' : GTypecast.text,
+ 'Default' : '9999' },
+
+ { 'Name' : 'ManualItemSKUisDepartment',
+ 'Type' : 'Setting',
+ 'Comment' : 'The SKU to use for manually keyed items.',
+ 'Description': 'The SKU to use for manually keyed items. (Can be empty to
disabled)',
+ 'Typecast' : GTypecast.boolean,
+ 'Default' : 1 },
+
+ { 'Name' : 'ManualItemRequestBasePrice',
+ 'Type' : 'Setting',
+ 'Comment' : 'The SKU to use for manually keyed items.',
+ 'Description': 'The SKU to use for manually keyed items. (Can be empty to
disabled)',
+ 'Typecast' : GTypecast.boolean,
+ 'Default' : 1 },
+
+ { 'Name' : 'TaxRate',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.number,
+ 'Default' : 7.00 },
+
+ { 'Name' : 'TaxState',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'MS' },
+
+ { 'Name' : 'SKULabel',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'Item Code' },
+
+ { 'Name' : 'CompanyName',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'GNU Enterprise' },
+
+ { 'Name' : 'CompanyPhone',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : '' },
+
+ { 'Name' : 'CompanyLogo',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : '' },
+
+ { 'Name' : 'ReceiptHeader',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'My Sample Store\\n123 N Main St\\nMy Town, MS
38654\\n800-555-1234' },
+
+ { 'Name' : 'ReceiptFooter',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : 'Thank you for your purchase.\\nPlease Come Again!' },
+
+ { 'Name' : 'ReceiptLogo',
+ 'Type' : 'Setting',
+ 'Comment' : '',
+ 'Description': '',
+ 'Typecast' : GTypecast.text,
+ 'Default' : '' },
+)
+
Added: gnue-pointofsale/src/Handler.py
===================================================================
--- gnue-pointofsale/src/Handler.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/Handler.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,515 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# Handler.py
+#
+# DESCRIPTION:
+#
+# NOTES:
+#
+
+import os, sys, types
+
+from gnue.common.apps import GDebug
+from gnue.common.apps import GConfig
+from gnue.common import events
+
+
+class Handler(events.EventAware):
+
+ def __init__(self, client):
+ events.EventAware.__init__(self, client)
+
+ self._ManualItemSKUisDepartment = gConfig('ManualItemSKUisDepartment')
+ self._ManualItemRequestBasePrice = gConfig('ManualItemRequestBasePrice')
+ self._TaxRate = float(gConfig('TaxRate'))/100
+
+ self._loggedin = 0
+ self._quantityRequestedFlag = 0
+ self._ticket = 0
+ self._quantity = 1
+
+ self.registerEventListeners( {
+ 'BeginTicket': self._BeginTicket,
+ 'EndTicket': self._EndTicket,
+ 'CancelTicket': self._CancelTicket,
+ 'ClearTicket': self._ClearTicket,
+
+ 'BeginLayaway': self._BeginLayaway,
+ 'EndLayaway': self._EndLayaway,
+ 'RequestBeginLayaway': self._RequestBeginLayaway,
+ 'RequestEndLayaway': self._RequestEndLayaway,
+
+ 'AddDiscount': self._AddDiscount,
+ 'AddTender': self._AddTender,
+ 'AddTicketItem': self._AddTicketItem,
+ 'CancelTicketItem': self._CancelTicketItem,
+
+ 'LoginEntered': self._LoginEntered,
+ 'PasswordEntered': self._PasswordEntered,
+ 'SKUEntered': self._SKUEntered,
+ 'QuantityEntered': self._QuantityEntered,
+ 'CancelItemEntered': self._CancelItemEntered,
+
+ 'RequestLogin': self._RequestLogin,
+ 'RequestPassword': self._RequestPassword,
+
+ 'RequestSKU': self._RequestSKU,
+ 'RequestQuantity': self._RequestQuantity,
+ 'RequestSuspendTicket': self._RequestSuspendTicket,
+ 'RequestResumeTicket': self._RequestResumeTicket,
+ 'RequestCancelTicket': self._RequestCancelTicket,
+ 'RequestPriceLookup': self._RequestPriceLookup,
+ 'RequestRemoveItem': self._RequestRemoveItem,
+ 'RequestCancelItem': self._RequestCancelItem,
+ 'RequestDuplicateLastItem': self._RequestDuplicateLastItem,
+ 'RequestDiscount': self._RequestDiscount,
+ 'RequestLogOut': self._RequestLogOut,
+ 'RequestExit': self._RequestExit,
+
+ 'RequestTender:Cash': self._RequestTenderCash,
+ 'RequestTender:Check': self._RequestTenderCheck,
+ 'RequestTender:CreditCard': self._RequestTenderCreditCard,
+ 'RequestTender:Gift': self._RequestTenderGift,
+ 'TenderEntered': self._TenderEntered,
+ 'TenderExtraEntered': self._TenderExtraEntered,
+
+ 'BeginManualItem': self._BeginManualItem,
+ 'RequestEndManualItem': self._RequestEndManualItem,
+ 'ManualDepartmentEntered': self._ManualDepartmentEntered,
+ 'ManualDescriptionEntered': self._ManualDescriptionEntered,
+ 'ManualBasePriceEntered': self._ManualBasePriceEntered,
+ 'ManualPriceEntered': self._ManualPriceEntered,
+ 'RequestManualDepartment': self._RequestManualDepartment,
+ 'RequestManualDescription': self._RequestManualDescription,
+ 'RequestManualBasePrice': self._RequestManualBasePrice,
+ 'RequestManualPrice': self._RequestManualPrice,
+
+ 'RequestTaxExemption': self._RequestTaxExemption,
+ 'TaxExemptionEntered': self._TaxExemptionEntered,
+ })
+
+ def run(self):
+ self._RequestLogin(None)
+
+
+ def _LoginEntered(self, event):
+ self._login = event.value
+ self.dispatchEvent('RequestPassword')
+
+ def _RequestPassword(self, event):
+ self.dispatchEvent('Prompt',
+ label='Enter Password:',
+ field='Password',
+ response="PasswordEntered")
+
+ def _PasswordEntered(self, event):
+ rs = self.dispatchEvent('VerifyLogin', login=self._login,
password=event.value)
+ if rs:
+ self.dispatchEvent('RequestLogin')
+ return
+ self._loggedin = 1
+ self.dispatchEvent('RequestSKU')
+
+
+ def _SKUEntered(self, event):
+ if not hasattr(event,'next'):
+ event.next = 'RequestSKU'
+
+ if event.next == 'RequestQuantity':
+ rs = 0
+ if not self._ticket:
+ self.dispatchEvent('RequestBeginTicket')
+ self.dispatchEvent('RequestQuantity')
+
+ elif event.value:
+ if not self._ticket:
+ self.dispatchEvent('RequestBeginTicket')
+ rs = self.dispatchEvent('ProcessSKU', sku=event.value, origEvent=event,
quantity=self._quantity)
+ else:
+ if not self._ticket and event.next in ('RequestTaxExemption',):
+ self.dispatchEvent('RequestBeginTicket')
+
+ rs = 1
+
+ if rs:
+ event.dispatchAfter(event.next)
+
+
+ def _QuantityEntered(self, event):
+ if not event.value or event.value == '0':
+ self.dispatchEvent('RequestSKU')
+
+ try:
+ self._quantity = float(event.value)
+ if self._quantity < 0:
+ raise ValueError
+ self.dispatchEvent('RequestSKU')
+ except ValueError:
+ self.dispatchEvent('Warning',message='Quantity must be entered')
+ self.dispatchEvent('RequestQuantity')
+ return
+
+ def _CancelItemEntered(self, event):
+ if not event.value:
+ self.dispatchEvent('RequestSKU')
+ return
+ v = int(event.value) - 1
+ if v >= len(self._items):
+ self.dispatchEvent('RequestCancelItem')
+ elif not hasattr(self._items[v],'CANCELED'):
+ attrs = {}
+ for attr, value in event.__dict__.items():
+ if attr[0] != '_' and type(value) != types.MethodType:
+ attrs[attr] = value
+ attrs['origlineitem'] = v + 1
+ attrs['lineitem'] = len(self._items)
+ attrs['extended'] *= -1
+ attrs['each'] *= -1
+ self._items[v].CANCELED = 1
+ self.dispatchEvent('CancelItem', **attrs)
+
+
+ def _BeginManualItem(self, event):
+ self._manualSKU = event.sku
+ if self._ManualItemSKUisDepartment:
+ self._manualDepartment = event.sku
+ self._manualEvents = ['RequestManualDescription']
+ else:
+ self._manualEvents =
['RequestManualDepartment','RequestManualDescription']
+
+ if self._ManualItemRequestBasePrice:
+ self._manualEvents += ['RequestManualBasePrice','RequestManualPrice']
+ self._manualBasePrice = 0
+ else:
+ self._manualEvents += ['RequestManualPrice']
+
+ self._manualEvents.append('RequestEndManualItem')
+
+ event.dispatchAfter(self._manualEvents.pop(0))
+
+ def _ManualDepartmentEntered(self, event):
+ if not len(event.value):
+ self.dispatchEvent('Warning',message='Department must be entered')
+ self.dispatchEvent('RequestManualDepartment')
+ return
+ self._manualDepartment = event.value
+ self.dispatchEvent(self._manualEvents.pop(0))
+
+ def _ManualDescriptionEntered(self, event):
+ if not len(event.value):
+ self.dispatchEvent('Warning',message='Description must be entered')
+ self.dispatchEvent('RequestManualDescription')
+ return
+ self._manualDescription = event.value
+ self.dispatchEvent(self._manualEvents.pop(0))
+
+ def _ManualBasePriceEntered(self, event):
+ try:
+ self._manualBasePrice = float(event.value)
+ if self._manualBasePrice < 0:
+ raise ValueError
+ except ValueError:
+ self.dispatchEvent('Warning',message='Base price must be entered')
+ self.dispatchEvent('RequestManualBasePrice')
+ return
+
+ v = self._manualEvents.pop(0)
+ if v == 'RequestManualPrice':
+ self.dispatchEvent(v, default=self._manualBasePrice)
+ else:
+ self.dispatchEvent(v)
+
+ def _ManualPriceEntered(self, event):
+ try:
+ self._manualPrice = float(event.value)
+ if self._manualPrice < 0:
+ raise ValueError
+ except ValueError:
+ self.dispatchEvent('Warning',message='Item price must be entered')
+ self.dispatchEvent('RequestManualPrice')
+ return
+
+ self.dispatchEvent(self._manualEvents.pop(0))
+
+
+ def _RequestBeginLayaway(self, event):
+ pass
+
+ def _RequestEndLayaway(self, event):
+ pass
+
+ #
+ #
+ #
+
+ def _RequestLogin(self, event):
+ print "Requested"
+ self.dispatchEvent('Prompt',
+ label='Enter User ID:',
+ response="LoginEntered")
+
+
+ def _RequestSKU(self, event):
+ endingEvents = [ 'RequestQuantity',
+ 'RequestPriceLookup',
+ 'RequestResumeTicket',
+ 'RequestTaxExemption',
+ 'RequestLogOut',
+ 'RequestExit' ]
+
+ if self._ticket:
+ endingEvents += ['RequestSuspendTicket',
+ 'RequestCancelTicket',
+ 'RequestTender:Cash',
+ 'RequestTender:Check',
+ 'RequestTender:CreditCard',
+ 'RequestTender:Gift',
+ 'RequestRemoveItem',
+ 'RequestCancelItem',
+ 'RequestDuplicateLastItem',
+ 'RequestDiscount']
+
+ self.dispatchEvent('Prompt', label='Enter %s:' % gConfig('SKULabel'),
response='SKUEntered',
+ endingEvents=endingEvents)
+
+ def _RequestQuantity(self, event):
+ self.dispatchEvent('Prompt', response='QuantityEntered', label='Enter
Quantity:')
+
+ def _RequestSuspendTicket(self, event):
+ pass
+
+ def _RequestResumeTicket(self, event):
+ pass
+
+ def _RequestCancelTicket(self, event):
+ self.dispatchEvent('CancelTicket', serial=self._ticket)
+
+ def _RequestPriceLookup(self, event):
+ pass
+
+ ##
+ ##
+ ##
+
+ def _RequestTenderCash(self, event):
+ self.__tender = 'CASH'
+ self.dispatchEvent('Prompt', label='Enter Cash Amount',
response='TenderEntered')
+
+ def _RequestTenderCreditCard(self, event):
+ self.__tender = 'CREDIT'
+ self.dispatchEvent('Prompt', label='Enter Credit Card Amount',
response='TenderEntered')
+
+ def _RequestTenderCheck(self, event):
+ self.__tender = 'CHECK'
+ self.dispatchEvent('Prompt', label='Enter Check Amount',
response='TenderEntered')
+
+ def _RequestTenderGift(self, event):
+ self.__tender = 'GIFT'
+ self.dispatchEvent('Prompt', label='Enter Gift Certificate Amount',
response='TenderEntered')
+
+ def _TenderEntered(self, event):
+ try:
+ self.__tenderamount = float(event.value)
+ if self.__tenderamount < 0:
+ raise ValueError
+ except ValueError:
+ self.dispatchEvent('Warning',message='Tender amount must be entered')
+ self.dispatchEvent('RequestTender' %
{'CASH':'Cash','CREDIT':'CreditCard','CHECK':'Check','GIFT':'Gift'}[self.__tender])
+ return
+
+ if self.__tender == 'GIFT':
+ self.dispatchEvent('Prompt', label='Enter Gift Certificate Number',
response='TenderExtraEntered')
+ elif self.__tender == 'CHECK':
+ self.dispatchEvent('Prompt', label='Enter Check Number',
response='TenderExtraEntered')
+ elif self.__tender == 'CREDIT':
+ self.dispatchEvent('Prompt', label='Enter Approval Response Code',
response='TenderExtraEntered')
+ else:
+ self.__endTender()
+
+ def _TenderExtraEntered(self, event):
+ self.__endTender(event.value)
+
+ def __endTender(self, extra=None):
+ self.dispatchEvent('AddTender', type=self.__tender,
amount=self.__tenderamount, extra=extra)
+
+ ##
+ ##
+ ##
+
+ def _RequestRemoveItem(self, event):
+ pass
+
+ def _RequestCancelItem(self, event):
+ self.dispatchEvent('Prompt', response='CancelItemEntered', label='Enter
Line # to Cancel:', default=len(self._items))
+
+ def _RequestDuplicateLastItem(self, event):
+ pass
+
+ def _RequestDiscount(self, event):
+ pass
+
+ def _RequestLogOut(self, event):
+ if self._ticket:
+ self.dispatchEvent('Warning',message='Cannot log out until ticket is
canceled or completed')
+ else:
+ self._login = None
+ self.dispatchEvent('RequestLogin')
+
+ def _RequestExit(self, event):
+ if self._ticket:
+ self.dispatchEvent('Warning',message='Cannot exit until ticket is
canceled or completed')
+ else:
+ sys.exit()
+
+ def _RequestTaxExemption(self, event):
+ self.dispatchEvent('Prompt', label='Enter Tax Exemption Number:',
response='TaxExemptionEntered')
+
+ ##
+ ##
+ ##
+
+ def _RequestManualDepartment(self, event):
+ self.dispatchEvent('Prompt', label='Enter Department:',
response='ManualDepartmentEntered')
+
+ def _RequestManualDescription(self, event):
+ self.dispatchEvent('Prompt', label='Enter Item Description:',
response='ManualDescriptionEntered')
+
+ def _RequestManualBasePrice(self, event):
+ self.dispatchEvent('Prompt', label='Enter Base Price:',
response='ManualBasePriceEntered')
+
+ def _RequestManualPrice(self, event):
+ if hasattr(event,'default'):
+ self.dispatchEvent('Prompt', label='Enter Sales Price:',
response='ManualPriceEntered', default=event.default)
+ else:
+ self.dispatchEvent('Prompt', label='Enter Sales Price:',
response='ManualPriceEntered')
+
+
+ def _RequestEndManualItem(self, event):
+ self.dispatchEvent('EndManualItem', sku=self._manualSKU,
+ description=self._manualDescription,
+ department=self._manualDepartment,
+ baseprice=self._manualBasePrice,
+ quantity=self._quantity,
+ price=self._manualPrice,
+ extended = self._quantity * self._manualPrice,
+ taxable=1)
+
+ self.dispatchEvent('AddTicketItem', department=self._manualDepartment,
+ sku=self._manualSKU,
+ quantity=self._quantity,
+ description=self._manualDescription,
+ base=self._manualBasePrice,
+ each=self._manualPrice,
+ extended=round(self._manualPrice *
self._quantity,2),
+ taxable=1,
+ lineitem=len(self._items))
+ self._quantity = 1
+ self.dispatchEvent('RequestSKU')
+
+ ##
+ ##
+ ##
+
+ def _BeginTicket(self, event):
+ self._ticket = event.serial
+ self._taxTotal = 0
+ self._subTotal = 0
+ self._payments = 0
+ self._taxExempt = 0
+ self._layaway = 0
+ self._items = []
+ self.dispatchEvent('UpdateTotal', field="subtotal", amount=0.0)
+ self.dispatchEvent('UpdateTotal', field="tax", amount=0.0)
+ self.dispatchEvent('UpdateTotal', field="total", amount=0.0)
+ self.dispatchEvent('UpdateTotal', field="balance", amount=0.0)
+
+ def _EndTicket(self, event):
+ event.dispatchAfter('ClearTicket')
+
+ def _CancelTicket(self, event):
+ event.dispatchAfter('ClearTicket')
+
+ def _ClearTicket(self, event):
+ self._ticket = 0
+ event.dispatchAfter('RequestSKU')
+
+ def _AddTicketItem(self, event):
+ self._subTotal += event.extended
+ if event.taxable:
+ self._taxTotal += event.extended
+ self._items.append(event)
+ event.lineitem=len(self._items)+1
+ self._updateTotals()
+
+ def _BeginLayaway(self, event):
+ self._layaway = 1
+
+ def _EndLayaway(self, event):
+ self._layaway = 0
+ self.dispatchEvent('EndTicket', serial=self._ticket)
+
+ def _AddTender(self, event):
+ self._payments += event.amount
+ if self._payments > self.total():
+ print self._payments-self.total()
+ event.dispatchAfter('AddTender', type='CHANGE',
+ amount=round(self._payments-self.total(),2))
+
+ elif round(self._subTotal + self.taxes() - self._payments,2) == 0:
+ event.dispatchAfter('EndTicket', serial=self._ticket)
+ else:
+ event.dispatchAfter('RequestSKU')
+
+ self._updateTotals()
+
+
+ def _AddDiscount(self, event):
+ pass
+
+ def _CancelTicketItem(self, event):
+ pass
+
+ def _UpdateQuantity(self, event):
+ pass
+
+ def _TaxExemptionEntered(self, event):
+ if event.value:
+ self._taxExempt = 1
+ else:
+ self._taxExempt = 0
+ self._updateTotals()
+ self.dispatchEvent('RequestSKU')
+
+
+ def _updateTotals(self):
+ tax = self.taxes()
+ self.dispatchEvent('UpdateTotal', field="subtotal", amount=self._subTotal)
+ self.dispatchEvent('UpdateTotal', field="tax", amount=tax)
+ self.dispatchEvent('UpdateTotal', field="total", amount=self.total())
+ self.dispatchEvent('UpdateTotal', field="balance", amount=self.total() -
self._payments)
+
+
+ def taxes(self):
+ return round(self._taxTotal* self._TaxRate,2) * (self._taxExempt == 0)
+
+ def total(self):
+ return self._subTotal + self.taxes()
Added: gnue-pointofsale/src/IOProxy.py
===================================================================
--- gnue-pointofsale/src/IOProxy.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/IOProxy.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,112 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# IOProxy.py
+#
+# DESCRIPTION:
+# Device/File/Command IO Proxy
+# This module proxies IO for the various hardware drivers
+# so the individual drivers don't have to worry about whether
+# they are writing to a file, a serial device, or piping
+# data to an external command.
+#
+# NOTES:
+# Somewhat crude and I'm not sure if the use of popen creates
+# a race condition... I have to guess not since I don't check
+# for success/fail.
+#
+
+__all__ = ['simpleOpen']
+
+import os
+from cStringIO import StringIO
+
+# This is a multiplexor of sorts
+# It returns the correct type of IOProxy
+def simpleOpen(*args, **parms):
+ if len(args) == 1 and type(args) == type({}) and not len(parms):
+ parms = args[0]
+ try:
+ tp = parms['type'].lower()
+ except:
+ tp = 'file'
+
+ rs = _ProxyMap[tp](*args, **parms)
+ rs.open()
+ return rs
+
+
+#
+# Base IOProxy
+#
+class _IOProxy:
+ def __init__(self, *args, **parms):
+ self.__dict__.update(parms)
+ if len(args):
+ self.__dict__.update(args[0])
+
+ def open(self):
+ pass
+
+ def close(self):
+ pass
+
+ def write(self, text):
+ self._stream.write(text)
+
+
+#
+# IOProxy for OS files/devices
+#
+class _FileProxy(_IOProxy):
+ def open(self):
+ print "Opening %s" % self.dest
+ self._stream = open(self.dest,'w')
+
+ def close(self):
+ print "Closing %s" % self.dest
+ self._stream.close()
+
+
+#
+# IOProxy for external commands
+#
+class _CommandProxy(_IOProxy):
+ def open(self):
+ self._stream = StringIO()
+
+ def close(self):
+ b = os.popen(self.dest,'w')
+ self._stream.seek(0)
+ b.write(self._stream.read())
+ b.close()
+ self._stream.close()
+ self._stream = None
+
+
+
+
+_ProxyMap = { 'file': _FileProxy,
+ 'serial': _FileProxy,
+ 'parallel': _FileProxy,
+ 'device': _FileProxy,
+ 'command': _CommandProxy }
+
Added: gnue-pointofsale/src/POSClient.py
===================================================================
--- gnue-pointofsale/src/POSClient.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/POSClient.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,185 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# POSClient.py
+#
+# DESCRIPTION:
+# Command line client startup file that parses args,
+# and imports the required UI.
+#
+# NOTES:
+#
+
+import os, sys
+
+from gnue.common.apps.GClientApp import *
+from gnue.common.apps import GDebug
+from gnue.common.apps import GConfig
+from gnue.common.datasources import GDataObjects, GConnections
+from gnue.common.utils.FileUtils import dyn_import
+from gnue.common import events
+
+from gnue.pointofsale import VERSION
+from gnue.pointofsale.Config import ConfigOptions
+
+from Handler import Handler
+
+class POSClient(GClientApp, events.EventAware):
+ #
+ # GClientApp() overrides
+ #
+ VERSION = VERSION
+ COMMAND = "gnue-pos"
+ NAME = "GNUe Point-of-Sale"
+ USAGE = GClientApp.USAGE + " <register name>"
+ COMMAND_OPTIONS = [ ]
+ SUMMARY = \
+ _("GNUe Point-of-Sale is a point of sale (cash register) program for the
GNUe project.")
+
+ def __init__(self, connections=None):
+ self.eventController = events.EventController()
+ events.EventAware.__init__(self, self.eventController)
+
+ GClientApp.__init__(self, connections,'point-of-sale',ConfigOptions)
+ self.configurationManager.registerAlias('gConfigForms', 'forms')
+
+ #
+ # Run the client application
+ #
+ def run(self):
+
+ self.handler = Handler(self)
+
+ #
+ # Initialize interfaces
+ #
+ self.frontend = dyn_import("gnue.pointofsale.frontends.wx").Driver(self)
+ try:
+ self.backend = dyn_import("gnue.pointofsale.backends.%s" %
gConfig('BackendProvider')).Driver(self)
+ except ImportError, mesg1:
+ try:
+ self.backend = dyn_import(gConfig('BackendProvider')).Driver(self)
+ except ImportError, mesg2:
+ self.handleStartupError('Unable to load backend provider:\n\n%s\n\n%s'
% (mesg1, mesg2))
+
+
+ if hasattr(self.frontend,'handleStartupError') and not
self.OPTIONS['debug-level']:
+ self.handleStartupError = self.frontend.handleStartupError
+
+## if hasattr(self.frontend,'handleUncaughtException'):
+## sys._orig_excepthook = sys.excepthook
+## sys.excepthook = self.frontend.handleUncaughtException
+
+
+ #
+ # assign register name from 1st free argument
+ #
+ try:
+ self.registername = registername = self.ARGUMENTS[0]
+ except:
+ try:
+ import socket
+ self.registername = registername = socket.gethostname().split('.')[0]
+ if registername:
+ print "No register name specified; Assuming '%s'" % registername
+ except:
+ self.handleStartupError (_("No Register Name Specified."))
+
+ self._initHardware(registername)
+
+ #
+ # Get the user supplied parameters
+ #
+ ##userParameters = self.getCommandLineParameters(self.ARGUMENTS[1:])
+
+ self.handler.run()
+
+ #
+ # Testing stuff....
+ #
+## self.dispatchEvent('BeginTicket', serial=100000)
+## self.dispatchEvent('AddTicketItem', sku=123355, description='A Tale of
Two Cities (Dickens, Charles) USED', department=20,
+## quantity=1, each=5.95, extended=5.95)
+## self.dispatchEvent('AddTicketItem', sku=123356, description='Harry
Potter and the Order of the Phoenix (Rowling, J.K.)', department=20,
+## quantity=2, each=29.99, extended=59.98)
+## self.dispatchEvent('AddTicketItem', description='Gift Certificate',
department=999,
+## quantity=1, each=30.00, extended=30.00)
+## self.dispatchEvent('UpdateTotal', field="subtotal", amount=95.93)
+## self.dispatchEvent('UpdateTotal', field="tax", amount=6.72)
+## self.dispatchEvent('UpdateTotal', field="total", amount=102.65)
+## self.dispatchEvent('Prompt', label='Enter User ID:', field="login")
+## self.dispatchEvent('EndTicket')
+
+ self.frontend.run()
+
+
+
+ #
+ # Load all the hardware from the config file
+ #
+ def _initHardware(self, registername):
+ options = gConfigDict()
+ mapping = {}
+
+ for key in options.keys():
+ try:
+ p1, p2 = key.split("_",1)
+ except:
+ continue
+
+ if p1.lower()[:6] == 'device':
+ try:
+ num = int(p1[6:])
+ except ValueError:
+ continue
+
+ try:
+ mp = mapping[num]
+ except KeyError:
+ mp = {}
+ mapping[num] = mp
+
+ mp[p2.lower()] = options[key]
+
+
+ srt = list(mapping.items())
+ srt.sort()
+
+ for device, params in srt:
+ dr = params['driver'].lower().replace('/','.')
+ try:
+ module = dyn_import('gnue.pointofsale.hardware.%s' % dr)
+ except ImportError, mesg:
+ GDebug.printMesg(5, mesg)
+ try:
+ module = dyn_import(dr)
+ except ImportError, mesg:
+ GDebug.printMesg(5, mesg)
+ self.handleStartupError('Unable to load device #%2d (%s) -- Driver
not found' % (device, params['driver']))
+
+ print "Loading hardware driver: %s" % params['driver']
+ module.Driver(self, params)
+
+
+if __name__ == '__main__':
+ POSClient().run()
+
+
Added: gnue-pointofsale/src/__init__.py
===================================================================
--- gnue-pointofsale/src/__init__.py 2005-04-19 12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/__init__.py 2005-04-23 12:05:40 UTC (rev 219)
@@ -0,0 +1,60 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+
+
+#
+# CREATING A RELEASE:
+# 1. Change _version to be the current version number
+# 2. Set _release to 1
+#
+# AFTER THE RELEASE:
+# 3. Increase the minor number
+# 4. Set _release = 0
+# 5. Commit to CVS
+
+_version = (0,0,1)
+_release = 0
+
+# Version will be of the form "1.1.2" if a release or "1.1.1.99" if in CVS
+if _release:
+ VERSION="%s.%s.%s" % _version
+else:
+ _t = (("%08d" % (int("%02d%02d%02d00" % _version)-1) ).replace('99','') +
'99') + '0000000'
+ if _t[6:8] != '00':
+ extra = '.99'
+ else:
+ extra = ''
+ VERSION = "%s.%s.%s%s" % (int(_t[:2]), int(_t[2:4]), int(_t[4:6]), extra)
+
+# Hex Version will be an integer in which version 1.2.15 is represented
+# as 0x010215FF (for a release) or 0x01021500 (for a CVS snapshot)
+# This allows numeric testing of version numbers
+# (e.g., HEXVERSION >= 0x01020000)
+HEXVERSION = eval('0x%s%s' % ('%02d%02d%02d' % _version,
+ _release and 'FF' or '00') )
+
+# Sigh... For Python compatability
+__version__ = VERSION
+__hexversion__ = HEXVERSION
+
+
+PACKAGE="GNUe-POS"
+TITLE="GNUe Point-of-Sale"
Added: gnue-pointofsale/src/backends/Base/Driver.py
===================================================================
--- gnue-pointofsale/src/backends/Base/Driver.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/backends/Base/Driver.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,79 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# Base/Driver.py
+#
+# DESCRIPTION:
+# Base driver file for GNUe POS backends
+#
+# NOTES:
+#
+
+from gnue.common.events.EventAware import EventAware
+from gnue.common.datasources import GConditions
+from gnue.common.datasources.GDataSource import DataSourceWrapper
+
+CONN = gConfig('BackendConnection')
+
+class Driver(EventAware):
+
+ ##########################################################
+ #
+ # TO BE REPLACED BY ACTUAL DRIVERS
+ #
+
+ def init(self):
+ pass
+
+
+ ##########################################################
+ #
+ # INTERNAL METHODS NOT TO BE
+ # REPLACED BY ACTUAL DRIVERS
+ #
+
+ def __init__(self, instance):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+
+ self.init()
+
+
+ def _getResultSet(self, table, fields, conditions={}):
+ datasource = DataSourceWrapper(self.instance.connections,
+ fields=fields,
+ attributes={'connection': CONN,
+ 'name': 'dts%s' % table,
+ 'table': table } )
+ resultset = datasource.createResultSet(
+ conditions=conditions,
+ readOnly=1)
+ return resultset
+
+ def _createResultSet(self, table, fields):
+ datasource = DataSourceWrapper(self.instance.connections,
+ fields=fields,
+ attributes={'connection': CONN,
+ 'name': 'dts%s' % table,
+ 'table': table } )
+ resultset = datasource.createEmptyResultSet()
+ return resultset
+
Added: gnue-pointofsale/src/backends/Base/__init__.py
===================================================================
Added: gnue-pointofsale/src/backends/__init__.py
===================================================================
Added: gnue-pointofsale/src/backends/gnue_sb/Driver.py
===================================================================
--- gnue-pointofsale/src/backends/gnue_sb/Driver.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/backends/gnue_sb/Driver.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,67 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# wx/Driver.py
+#
+# DESCRIPTION:
+# wxPython driver file for GNUe POS frontends.
+# Borrows/integrates heavily with the GNUe-Forms wxPython driver.
+#
+# NOTES:
+#
+
+from gnue.pointofsale.backends.Base.Driver import Driver as BaseDriver
+from gnue.common.datasources import GConditions
+from gnue.common.datasources.GDataSource import DataSourceWrapper
+
+CONN = gConfig('BackendConnection')
+
+class Driver(BaseDriver):
+ def init(self):
+ self.registerEventListeners({
+ 'ProcessSKU': self._ProcessSKU,
+ 'EndManualItem': self._EndManualItem,
+ 'RequestBeginTicket': self._RequestBeginTicket,
+## 'EndTicket': self._EndTicket,
+## 'CancelTicket': self._CancelTicket
+})
+
+ def _ProcessSKU(self, event):
+ sku = event.sku
+ origEvent= event.origEvent
+ event.setResult(1)
+
+ if 1: # Manually Keyed Item
+ origEvent.dispatchAfter('BeginManualItem', sku=sku,
quantity=event.quantity)
+ event.setResult(0)
+ else:
+ self.dispatchEvent('AddItem', sku=123, description='Foobar',
quantity=event.quantity, price=10, taxable=1)
+
+ if 0: # requiresQuantity
+ origEvent.dispatchAfter('RequestQuantity')
+
+
+ def _RequestBeginTicket(self, event):
+ self.dispatchEvent('BeginTicket', serial=123456)
+
+
+ def _EndManualItem(self, event):
+ pass
Added: gnue-pointofsale/src/backends/gnue_sb/__init__.py
===================================================================
--- gnue-pointofsale/src/backends/gnue_sb/__init__.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/backends/gnue_sb/__init__.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1 @@
+from Driver import Driver
Added: gnue-pointofsale/src/frontends/Base/Driver.py
===================================================================
--- gnue-pointofsale/src/frontends/Base/Driver.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/frontends/Base/Driver.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,53 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# Base/Driver.py
+#
+# DESCRIPTION:
+# Base driver file for GNUe POS frontends
+#
+# NOTES:
+#
+
+from gnue.common.events.EventAware import EventAware
+
+class Driver(EventAware):
+
+ ##########################################################
+ #
+ # TO BE REPLACED BY ACTUAL DRIVERS
+ #
+
+ def init(self):
+ pass
+
+
+ ##########################################################
+ #
+ # INTERNAL METHODS NOT TO BE
+ # REPLACED BY ACTUAL DRIVERS
+ #
+
+ def __init__(self, instance):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+
+ self.init()
Added: gnue-pointofsale/src/frontends/Base/__init__.py
===================================================================
Added: gnue-pointofsale/src/frontends/__init__.py
===================================================================
Added: gnue-pointofsale/src/frontends/wx/Driver.py
===================================================================
--- gnue-pointofsale/src/frontends/wx/Driver.py 2005-04-19 12:09:26 UTC (rev
218)
+++ gnue-pointofsale/src/frontends/wx/Driver.py 2005-04-23 12:05:40 UTC (rev
219)
@@ -0,0 +1,391 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# wx/Driver.py
+#
+# DESCRIPTION:
+# wxPython driver file for GNUe POS frontends.
+# Borrows/integrates heavily with the GNUe-Forms wxPython driver.
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from gnue.pointofsale.frontends.Base.Driver import Driver as BaseDriver
+from gnue.forms.uidrivers.wx import UIdriver as FormsDriver
+from gnue.forms.uidrivers.wx.GFwxApp import getWxApp
+
+from wxPython.wx import *
+from wxPython.gizmos import *
+from NumberDisplay import NumberDisplay, bigFont
+import string
+
+dollarFormat = '$%.02f'
+
+STATUS_USER = 2
+STATUS_TICKET = 1
+
+BASE_COLOR = wxNamedColour("ivory")
+LOGIN_COLOR = wxColour(255,220,220)
+LOGIN_EVENTS = ('LoginEntered','PasswordEntered')
+SPECIAL_COLOR = wxColour(220,255,220)
+SPECIAL_EVENTS = ('TaxExemptionEntered','CancelItemEntered', 'QuantityEntered')
+
+
+class Driver(BaseDriver):
+ def init(self):
+ self.totalFields = ( ('subtotal',_('Subtotal')),
+ ('tax','%s Sales Tax' % (gConfig('TaxState'))),
+ ('total',_('Total')),
+ ('balance',_('Balance')) )
+
+ self.receiptColumns = ( ('lineitem',_('#'), '%s', 1, 1),
+ ('department',_('Dept'), '%s', 0, 0),
+ ('sku',_('Code'), '%s', 0, 0),
+ ('quantity',_('Units'), '%s', 0, 0),
+ ('description',_('Description'), '%s', 0, 0),
+ ('base',_('Base Price'), dollarFormat, 1, 0),
+ ('each',_('Price/Unit'), dollarFormat, 1, 0),
+ ('extended',_('Extended'), dollarFormat, 1, 0),
+ ('taxable',_('Tax?'), 'bool', 0, 1) )
+
+ self.totalFieldMapping = {}
+
+ self._buildUI()
+
+ self.registerEventListeners( {
+ 'Prompt': self._Prompt,
+ 'Warning': self._Warning,
+ 'EmployeeLogin': self._EmployeeLogin,
+ 'BeginTicket': self._BeginTicket,
+ 'ClearTicket': self._ClearTicket,
+ 'AddTicketItem': self._AddTicketItem,
+ 'CancelTicketItem': self._CancelTicketItem,
+ 'UpdateTotal': self._UpdateTotal } )
+
+
+ def run(self):
+ app = getWxApp()
+ app.MainLoop()
+
+ def _Prompt(self, event):
+ self.inputLabel.SetLabel(event.label)
+ self.inputField.Clear()
+ self.inputField.SetFocus()
+ self.__event = event.response
+ try:
+ self.statusbar.SetStatusText (event.help)
+ except AttributeError:
+ pass
+
+ if event.response in LOGIN_EVENTS:
+ self.inputField.SetBackgroundColour(LOGIN_COLOR)
+ elif event.response in SPECIAL_EVENTS:
+ self.inputField.SetBackgroundColour(SPECIAL_COLOR)
+ else:
+ self.inputField.SetBackgroundColour(BASE_COLOR)
+
+ try:
+ default = str(event.default)
+ except:
+ default = ""
+
+ try:
+ self.__endingEvents = event.endingEvents
+ except AttributeError:
+ self.__endingEvents = ()
+
+ self.inputField.SetValue(default)
+ self.inputField.SetSelection(0, len(default))
+
+ def _BeginTicket(self, event):
+ print "Beginning ticket # %s" % event.serial
+ self.statusbar.SetStatusText("Ticket # %s" % event.serial, STATUS_TICKET)
+ self.receiptList.DeleteAllItems()
+
+ def _ClearTicket(self, event):
+ print "Ending ticket"
+ self.statusbar.SetStatusText("No Current Ticket", STATUS_TICKET)
+
+ def _AddTicketItem(self, event):
+ # Insert a new row
+ i = self.receiptList.GetItemCount()
+ self.receiptList.InsertStringItem(i,"")
+
+ # And set each column
+ j = 0
+ for field, foo, format, bar, none in self.receiptColumns:
+ try:
+ v = event.__dict__[field]
+ if format == 'bool':
+ format = '%s'
+ v = v and 'Yes' or 'No'
+ self.receiptList.SetStringItem(i, j, format % v)
+ except KeyError:
+ pass
+ j += 1
+
+ self.receiptList.SetItemState(i,
wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED,
wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED)
+
+ def _CancelTicketItem(self, event):
+ pass
+
+ def _UpdateTotal(self, event):
+ self.totalFieldMapping[event.field].SetValue(dollarFormat % event.amount)
+
+ def _buildUI(self):
+ app = getWxApp()
+ self.frame = frame = wxFrame(None, -1, "GNUe Point-of-Sale",
style=wxDEFAULT_FRAME_STYLE & (wxRESIZE_BORDER | wxRESIZE_BOX | wxMAXIMIZE_BOX))
+ frameSizer = wxBoxSizer(wxVERTICAL)
+ frame.SetSizer(frameSizer)
+ frame.SetAutoLayout(1)
+ EVT_SIZE(frame, self.__OnSize)
+
+ self.statusbar = frame.CreateStatusBar(3)
+ self.statusbar.SetStatusText ('Not Logged In', STATUS_USER)
+
+ topPanel = wxPanel(frame, -1)
+ topSizer = wxBoxSizer(wxHORIZONTAL)
+ topPanel.SetSizer(topSizer)
+ topPanel.SetAutoLayout(1)
+
+ bottomPanel = wxPanel(frame, -1)
+ bottomSizer = wxBoxSizer(wxHORIZONTAL)
+ bottomPanel.SetSizer(bottomSizer)
+ bottomPanel.SetAutoLayout(1)
+
+ self.receiptList = receiptList = wxListCtrl(frame, -1,
+
style=wxLC_REPORT|wxLC_HRULES|wxLC_VRULES|wxLC_SINGLE_SEL|wxSIMPLE_BORDER)
+
+ # Add the columns for our receipt list
+ i = 0
+ for field, description, format, rightJustify, small in self.receiptColumns:
+ self.receiptList.InsertColumn(i, description,
+ format = wxLIST_FORMAT_RIGHT and rightJustify or wxLIST_FORMAT_LEFT)
+ if small:
+ self.receiptList.SetColumnWidth(i,
self.receiptList.GetColumnWidth(i)/2)
+
+ i += 1
+
+ totalPanel2 = wxPanel(bottomPanel, -1, style=wxSIMPLE_BORDER)
+ totalSizer2 = wxBoxSizer(wxVERTICAL)
+ totalPanel2.SetSizer(totalSizer2)
+ totalPanel2.SetAutoLayout(1)
+
+ totalPanel = wxPanel(totalPanel2, -1)
+ totalSizer = wxFlexGridSizer(len(self.totalFields), 2, 2, 2)
+ totalPanel.SetSizer(totalSizer)
+ totalPanel.SetAutoLayout(1)
+
+ for name, descr in self.totalFields:
+ totalSizer.Add(wxStaticText(totalPanel, -1, descr + ': '), 0,
wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 2)
+ field = NumberDisplay(totalPanel, name=='total')
+ totalSizer.Add(field, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 2)
+ self.totalFieldMapping[name] = field
+
+ entryPanel = wxPanel(bottomPanel, -1)
+ entrySizer = wxBoxSizer(wxVERTICAL)
+ entryPanel.SetSizer(entrySizer)
+ entryPanel.SetAutoLayout(1)
+ self.inputLabel = wxStaticText(entryPanel, -1, "Enter Product Code:")
+ self.inputField = wxTextCtrl(entryPanel, -1)
+ self.inputLabel.SetFont(bigFont)
+ self.inputField.SetFont(bigFont)
+ self.inputField.SetSize((self.inputField.GetSizeTuple()[0],30))
+ entrySizer.Add(self.inputLabel, 0, wxEXPAND|wxALIGN_LEFT)
+ entrySizer.Add(self.inputField, 0, wxEXPAND|wxALIGN_LEFT)
+
+ entryPanel.Fit()
+ totalPanel.Fit()
+ totalSizer2.Add(totalPanel, 1, wxALL|wxEXPAND, 10)
+ totalPanel2.Fit()
+
+# bottomSizer.Add(wxPanel(bottomPanel,-1), 1, wxEXPAND)
+ bottomSizer.Add(entryPanel, 1, wxALIGN_CENTER|wxALL, 30)
+# bottomSizer.Add(wxPanel(bottomPanel,-1), 1, wxEXPAND)
+ bottomSizer.Add(totalPanel2, 0,
wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 20)
+ bottomPanel.Fit()
+
+ frameSizer.Add(topPanel, 0, wxEXPAND)
+ frameSizer.Add(receiptList, 3, wxEAST|wxWEST|wxEXPAND, 20)
+ frameSizer.Add(bottomPanel, 0, wxEXPAND)
+
+
+ totalSizer.Layout()
+ totalPanel.Fit()
+ topSizer.Layout()
+ bottomSizer.Layout()
+
+ frameSizer.Layout()
+# self.frame.ShowFullScreen(1)
+ frame.SetSize((800,600)) # TODO: Maximize to screen?
+ frame.Show(1)
+
+ EVT_KEY_DOWN(self.inputField, self.__keypress)
+ self.__intext = 1
+ EVT_CHAR(self.inputField, self.__ontext)
+
+
+ def _EmployeeLogin(self, event):
+ self.statusbar.SetStatusText ('Clerk: %s (%s)' % (event.name,
event.login), STATUS_USER)
+
+ def _Warning(self, event):
+ self.statusbar.SetStatusText(event.message)
+ wxBell();
+
+ def __OnSize(self, event):
+ self.frame.Layout()
+ w = self.receiptList.GetClientSizeTuple()[0]
+ pos = 0
+ for i in range(len(self.receiptColumns)):
+ if self.receiptColumns[i][0] == 'description':
+ pos = i
+ else:
+ w -= self.receiptList.GetColumnWidth(i)
+ self.receiptList.SetColumnWidth(pos, w)
+
+ def __keypress(self, event):
+ key = event.GetKeyCode()
+
+## print _specialKeys, key, self.__endingEvents
+## print key
+
+ if key in (WXK_RETURN,WXK_NUMPAD_ENTER):
+ self.dispatchEvent(self.__event, value=self.inputField.GetValue())
+ elif key == WXK_ESCAPE:
+ self.inputField.Clear()
+ elif _specialKeys.has_key(key) and _specialKeys[key] in
self.__endingEvents:
+ self.dispatchEvent(self.__event, value=self.inputField.GetValue(),
next=_specialKeys[key])
+ elif self.__event == 'CancelItemEntered' and key in (WXK_UP, WXK_DOWN):
+ c = self.receiptList.GetItemCount()
+ for r in range(c):
+ if self.receiptList.GetItemState(r,wxLIST_STATE_SELECTED):
+ break
+
+ st = ""
+
self.receiptList.SetItemState(r,0,wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED)
+ if key == WXK_UP:
+ if r > 0:
+ st = "%d" % (r)
+ else:
+ st = "1"
+ elif key == WXK_DOWN:
+ if r < c - 1:
+ st = "%d" % (r + 2)
+ else:
+ st = "%d" % (c)
+ if len(st):
+ self.inputField.SetValue(st)
+ self.inputField.SetSelection(0, len(st))
+
self.receiptList.SetItemState(int(st)-1,wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED,wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED)
+
+ else:
+ event.Skip()
+
+ def __ontext(self, event):
+ key = event.GetKeyCode()
+ if key != 32:
+ wxCallAfter(self.__fixtext)
+ event.Skip()
+
+
+ def __fixtext(self):
+ ip = self.inputField.GetInsertionPoint()
+ self.inputField.SetValue(string.capwords(self.inputField.GetValue()))
+ self.inputField.SetInsertionPoint(ip)
+
+
+
+_specialKeys = {
+
+ WXK_F1: 'RequestTender:Cash',
+ WXK_F2: 'RequestTender:Check',
+ WXK_F3: 'RequestTender:CreditCard',
+ WXK_F4: 'RequestTender:Gift',
+
+ WXK_F5: 'RequestBeginLayaway',
+ WXK_F6: 'RequestLayawayPayment',
+ WXK_F7: 'RequestEndLayaway',
+
+ WXK_F9: 'RequestCancelTicket',
+ WXK_F12: 'RequestTaxExemption',
+
+ WXK_MULTIPLY: 'RequestQuantity',
+ WXK_DIVIDE: 'RequestCancelItem',
+ WXK_SUBTRACT: 'RequestCancelLastItem',
+ WXK_ADD: 'RequestDuplicateLastItem',
+
+ # Grrrrr.... WX's keymaps above don't seem to be right
+ 391: 'RequestQuantity',
+ 396: 'RequestCancelItem',
+ 394: 'RequestCancelLastItem',
+ 392: 'RequestDuplicateLastItem',
+
+ #
+ 310: 'RequestLogOut',
+ 321: 'RequestReprint',
+
+ }
+
+
+_keyButtons = (
+ ('F1','Tender Cash'),
+ ('F2','Tender Check'),
+ ('F3','Tender Credit'),
+ ('F4','Tender Gift'),
+ ('F5','New Layaway'),
+ ('F6','Layaway Payment'),
+ ('F7','Complete Layaway'),
+ ('F9','Cancel Ticket'),
+ ('F12','Tax Exempt Order'),
+ ('Print','Reprint Ticket'),
+ ('Break', 'Log Out'),
+ ('/','Cancel Item'),
+ ('*','Enter Quantity'),
+ ('+','Duplicate Item') )
+
+
+class ButtonPanel(wxPanel):
+ def __init__(self, parent, driver):
+ self.driver = driver
+ wxPanel.__init__(self, parent, -1)
+
+
+
+# F1 = Tender Cash
+# F2 = Tender Check
+# F3 = Tender Credit Card
+# F4 = Tender Gift Cert
+#
+# F5 = Begin Layaway
+# F6 = Make Layaway Payment
+# F7 = End Layaway
+#
+# F9 = Cancel Ticket
+# F12 = Tax Exemption
+#
+# PrnScrn = Reprint Ticket
+# Break = Log Out
+#
+# / = Cancel Item
+# * = Enter Quantity
+# + = Duplicate Last Item
Added: gnue-pointofsale/src/frontends/wx/NumberDisplay.py
===================================================================
--- gnue-pointofsale/src/frontends/wx/NumberDisplay.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/frontends/wx/NumberDisplay.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,62 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# wx/NumberDisplay.py
+#
+# DESCRIPTION:
+# class that displays numbers (dollars) in bolded, right-aligned fields
+#
+# NOTES:
+#
+
+from wxPython.wx import *
+
+bigFont = wxFont(16, wxSWISS, wxNORMAL, wxBOLD)
+#bigFont = wxSystemSettings_GetFont(wxSYS_SYSTEM_FONT)
+bigFont.SetWeight(wxBOLD)
+bigFont.SetPointSize(18)
+bigFont.SetStyle(wxNORMAL)
+
+class NumberDisplay(wxPanel):
+ def __init__(self, parent, reversed=0):
+ wxPanel.__init__(self, parent, -1, style=wxSIMPLE_BORDER)
+ sizer = wxBoxSizer(wxHORIZONTAL)
+## self.SetSizer(sizer)
+## self.SetAutoLayout(1)
+# EVT_SIZE(frame, self.__OnSize)
+ self.text = wxStaticText(self,-1,"$0.00",(4,4),style =
wxALIGN_RIGHT|wxST_NO_AUTORESIZE)
+## sizer.Add(self.text, 0, wxALIGN_RIGHT)
+ self.SetValue = self.text.SetLabel
+
+ light = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHILIGHT)
+ dark =
wxColour(0)#wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW)
+ if reversed:
+ self.SetBackgroundColour(dark)
+ self.text.SetForegroundColour(light)
+ else:
+ self.SetBackgroundColour(light)
+ self.text.SetForegroundColour(dark)
+
+ self.text.SetFont(bigFont)
+ self.text.Refresh()
+
+ self.text.SetSize((150,20))
+ self.SetSize((160,30))
Added: gnue-pointofsale/src/frontends/wx/__init__.py
===================================================================
--- gnue-pointofsale/src/frontends/wx/__init__.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/frontends/wx/__init__.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,33 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# wx/__init__.py
+#
+# DESCRIPTION:
+# wxPython driver file for GNUe POS frontends.
+# Borrows/integrates heavily with the GNUe-Forms wxPython driver.
+#
+# NOTES:
+#
+
+from Driver import Driver
+
+
Added: gnue-pointofsale/src/hardware/__init__.py
===================================================================
Added: gnue-pointofsale/src/hardware/barcodereader/__init__.py
===================================================================
Added: gnue-pointofsale/src/hardware/cashdrawer/__init__.py
===================================================================
Added: gnue-pointofsale/src/hardware/cashdrawer/bell.py
===================================================================
--- gnue-pointofsale/src/hardware/cashdrawer/bell.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/hardware/cashdrawer/bell.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,52 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# cashdrawers/bell.py
+#
+# DESCRIPTION:
+# Cash Drawer driver (for all cash drawers using ASCII 7 (BELL)
+# as the code to open the drawer. These drawers usually are
+# connected to a parallel or serial port.
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from gnue.common.events.EventAware import EventAware
+from gnue.pointofsale.IOProxy import simpleOpen
+
+class Driver(EventAware):
+
+ def __init__(self, instance, params):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+ self.__dict__.update(params)
+ self.device_params = params
+
+ self.registerEventListeners({'EndTicket': self._open})
+
+
+ def _open(self, event):
+ p = simpleOpen(self.device_params)
+ p.write('\007')
+ p.close()
+
Added: gnue-pointofsale/src/hardware/cashdrawer/escpos.py
===================================================================
--- gnue-pointofsale/src/hardware/cashdrawer/escpos.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/hardware/cashdrawer/escpos.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,51 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# cashdrawers/escpos.py
+#
+# DESCRIPTION:
+# Cash Drawer driver for all cash drawers using Epson ESC/POS
+# codes. These drawers usually are connected to a receipt printer
+# via a phone cable-type jack.
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from gnue.common.events.EventAware import EventAware
+from gnue.pointofsale.IOProxy import simpleOpen
+
+class Driver(EventAware):
+
+ def __init__(self, instance, params):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+ self.__dict__.update(params)
+ self.device_params = params
+ self.registerEventListeners({'EndTicket': self.open})
+
+
+ def open(self, event):
+ p = simpleOpen(self.device_params)
+ p.write('\x1bp\x002\xfa')
+ p.close()
+
Added: gnue-pointofsale/src/hardware/logprinter/plain.py
===================================================================
--- gnue-pointofsale/src/hardware/logprinter/plain.py 2005-04-19 12:09:26 UTC
(rev 218)
+++ gnue-pointofsale/src/hardware/logprinter/plain.py 2005-04-23 12:05:40 UTC
(rev 219)
@@ -0,0 +1,311 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# receiptprinters/plain.py
+#
+# DESCRIPTION:
+# Receipt Printer driver (plain-text)
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from gnue.common.events.EventAware import EventAware
+from gnue.common.utils.TextUtils import *
+from gnue.pointofsale.IOProxy import simpleOpen
+from cStringIO import StringIO
+import time
+
+try:
+ import Image
+except:
+ Image = None
+
+dollarFormat = '$%.02f'
+
+BLACK = 0
+RED = 1
+
+
+class Driver(EventAware):
+
+ ##########################################################
+ #
+ #
+
+ def init(self):
+ pass
+
+
+ ##########################################################
+ #
+ #
+
+ def __init__(self, instance, params):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+ self.__dict__.update(params)
+ self.device_params = params
+ self.output = ""
+ self.totals = {}
+ self.newline = "\n"
+
+ print self.dest
+
+ # Get the logo
+ logo = gConfig("ReceiptLogo")
+
+ # TODO: Disabling until I get the ESC/POS stuff worked out
+ if 0: # logo and Image:
+ self.logo = Image.open(logo)
+ else:
+ self.logo = None
+
+ self.width = hasattr(self,'width') and self.width or 40
+
+ self.totalFields = ( ('subtotal',_('Subtotal')),
+ ('tax','MS Sales Tax (7%)'),
+ ('total',_('Total')) )
+
+ self.totalFieldMapping = {}
+
+ self.registerEventListeners( {
+ 'BeginTicket': self._BeginTicket,
+ 'ReprintTicket': self.printTicket,
+ 'EndTicket': self._EndTicket,
+ 'CancelTicket': self._CancelTicket,
+ 'AddTender': self._AddTender,
+ 'AddTicketItem': self._AddTicketItem,
+ 'CancelTicketItem': self._CancelTicketItem,
+ 'UpdateTotal': self._UpdateTotal,
+ 'ReceiptPrinter:ReceiptTorn': self._ReceiptTorn } )
+
+ self.init()
+
+ #
+ #
+ #
+ def printTicket(self, event=None):
+ if not self.output:
+ return
+
+ d = simpleOpen(self.device_params)
+ self.output.seek(0)
+ d.write(self.output.read())
+ d.close()
+
+
+ def printHeader(self):
+ self.output.write(self.reset())
+ if self.logo:
+ self.write(self.drawImage(self.logo))
+ self.write( gConfig("ReceiptHeader").replace('\\n','\n'),
alignment=ALIGN_CENTER)
+
+
+ def printFooter(self):
+ self.write( gConfig("ReceiptFooter").replace('\\n','\n'),
alignment=ALIGN_CENTER, color=RED)
+
+ shouter = self.dispatchEvent('Receipt:GetNotice')
+ shouter = """\
+Did you know? Old Towne Market has
+a professional portrait studio. Let
+us take your next family portrait,
+senior picture, or holiday photo."""
+
+ if shouter:
+ self.write('\n***************************************', indent=1,
color=1)
+ self.write(shouter, indent=2)
+ self.write('***************************************', indent=1, color=1)
+
+ #
+ #
+ #
+ def _BeginTicket(self, event):
+ try:
+ self.output.close()
+ except:
+ pass
+
+ self.tenders = []
+
+ self.output = StringIO()
+ self.doublespace = 0
+ self.totals = {}
+
+ self.printHeader()
+ self.write("\nSALES RECEIPT", double=1, alignment=ALIGN_CENTER)
+ self.write("""
+----------------------------------------
+Trans #%s %s %s
+""" % (event.serial, time.strftime("%m/%d/%y
%H:%M:%S",time.localtime(time.time())),self.instance.handler._login))
+
+ def _CancelTicket(self, event):
+ self.write('\n**** CANCELED ****\n', color=RED, double=1,
alignment=ALIGN_CENTER)
+ self.output.write(self.formfeed())
+ self.printTicket()
+
+ def _EndTicket(self, event):
+ self.output.write(" ----------\n")
+ for field, display in self.totalFields:
+ try:
+ amt = self.totals[field]
+ except KeyError:
+ amt = 0
+
+ self.write((display + ":").ljust(28)[:28]+ " " + comify(amt).rjust(10))
+
+ self.output.write(" ----------\n")
+ for tender in self.tenders:
+ self.write(tender)
+## self.write("\n----------------------------------------")
+ self.write("")
+ self.printFooter()
+ self.output.write(self.formfeed())
+ self.printTicket()
+
+
+ def _AddTicketItem(self, event):
+
+ self.write(str(event.department or "").ljust(3)[:3] + " " + \
+ str(event.description or "").upper().ljust(24)[:24] + " " + \
+ comify(event.extended,2).rjust(10) + \
+ (event.taxable and '*' or ' '))
+
+
+ def _AddTender(self, event):
+ # TODO
+
+ self.tenders.append (string.capwords('TENDER ' +
event.type).ljust(28)[:28] + " " + \
+ comify(event.amount).rjust(10))
+
+ def _CancelTicketItem(self, event):
+ pass
+
+ def _UpdateTotal(self, event):
+ self.totals[event.field] = event.amount
+
+ def write(self, text, double=0, bold=0, color=BLACK, underline=0,
+ doubleheight=0, alignment=ALIGN_LEFT, eol=1, width=0, indent=0):
+
+ splittext = str(text).split('\n')
+ i = 0
+ linehead = ""
+
+ for line in splittext:
+ divisor = 1
+
+ if underline:
+ self.output.write(self.beginUnderline())
+ if doubleheight:
+ self.output.write(self.beginDoubleHeight())
+ if double:
+ self.output.write(self.beginDouble())
+ if color:
+ self.output.write(self.beginColor(color))
+ if bold:
+ self.output.write(self.beginBold())
+
+ if self.doublespace:
+ l = ""
+ for char in tuple(line):
+ l += char + ' '
+ line = l[:-1]
+ elif double:
+ divisor = 2
+
+ self.output.write(' '*indent + lineWrap(line, alignment=alignment,
eol=0, maxWidth=int((width or self.width)/divisor)-indent).replace('\n','\n' +
' '* indent))
+
+ if bold:
+ self.output.write(self.endBold())
+ if color:
+ self.output.write(self.endColor(color))
+ if double:
+ self.output.write(self.endDouble())
+ if doubleheight:
+ self.output.write(self.endDoubleHeight())
+ if underline:
+ self.output.write(self.endUnderline())
+
+ if i < len(splittext)-1:
+ self.output.write(self.newline)
+
+ i += 1
+
+ if eol:
+ self.output.write(self.newline)
+
+ def writeTuple(self, list):
+ i = 0
+ for set in list:
+ if i != len(list) - 1:
+ list['eol'] = 0
+ self.write(**list)
+
+ def reset(self):
+ return ""
+
+ def formfeed(self):
+ return '\n\n\n\n\n\n\n'
+
+ def beginColor(self):
+ return ""
+
+ def endColor(self):
+ return ""
+
+ def beginBold(self):
+ return ""
+
+ def endBold(self):
+ return ""
+
+ def beginDouble(self):
+ self.doublespace = 1
+ return ""
+
+ def endDouble(self):
+ self.doublespace = 0
+ return ""
+
+ def beginDoubleHeight(self):
+ return ""
+
+ def endDoubleHeight(self):
+ return ""
+
+ def beginUnderline(self):
+ return ""
+
+ def endUnderline(self):
+ return ""
+
+ def drawImage(self, image):
+ return ""
+
+ def cutBetweenSheets(self):
+ self.__receiptTorn = 0
+ self.dispatchEvent('Prompt', label='Tear off receipt and press enter:',
response='ReceiptPrinter:ReceiptTorn')
+ while not self.__receiptTorn:
+ pass
+
+ def _ReceiptTorn(self, event):
+ self.__receiptTorn = 1
Added: gnue-pointofsale/src/hardware/poledisplay/__init__.py
===================================================================
Added: gnue-pointofsale/src/hardware/receiptprinter/__init__.py
===================================================================
Added: gnue-pointofsale/src/hardware/receiptprinter/escpos.py
===================================================================
--- gnue-pointofsale/src/hardware/receiptprinter/escpos.py 2005-04-19
12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/hardware/receiptprinter/escpos.py 2005-04-23
12:05:40 UTC (rev 219)
@@ -0,0 +1,123 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# receiptprinters/escpos.py
+#
+# DESCRIPTION:
+# Receipt Printer driver (Epson ESC/POS-based)
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from plain import Driver as BaseDriver
+
+class Driver(BaseDriver):
+
+ ##########################################################
+ #
+ #
+
+ def init(self):
+ self.colors = hasattr(self,'colors') and self.colors or 1
+ self.__double = 0
+ self.__underline = 0
+ self.__doubleheight = 0
+ self.__bold = 0
+
+ def reset(self):
+ return "\x1B@"
+
+ def formfeed(self):
+ return '\n\n\n\n\n\n\n\n'
+
+ def beginColor(self, color):
+ if self.colors == 1:
+ return ""
+ else:
+ return "\x1Br" + chr(color)
+
+ def endColor(self, color):
+ if self.colors == 1:
+ return ""
+ else:
+ return "\x1Br\x00"
+
+ def beginBold(self):
+ self.__bold = 1
+ return self.__setPrintMode()
+
+ def endBold(self):
+ self.__bold = 0
+ return self.__setPrintMode()
+
+ def beginDouble(self):
+ self.__double = 1
+ return self.__setPrintMode()
+
+ def endDouble(self):
+ self.__double = 0
+ return self.__setPrintMode()
+
+ def beginDoubleHeight(self):
+ self.__doubleheight = 1
+ return self.__setPrintMode()
+
+ def endDoubleHeight(self):
+ self.__doubleheight = 0
+ return self.__setPrintMode()
+
+ def beginUnderline(self):
+ self.__underline = 1
+ return self.__setPrintMode()
+
+ def endUnderline(self):
+ self.__underline = 0
+ return self.__setPrintMode()
+
+ def __setPrintMode(self):
+ return "\x1B!" + chr(self.__bold * 8 | self.__doubleheight * 16 | \
+ self.__double * 32 | self.__underline * 128)
+
+ def drawImage(self, image):
+ logoOffset = 0
+
+ lw, lh = image.size
+ vw = min(round(lw/8.0+.5),45)
+ vh = min(round(lh/8.0+.5),24)
+ uw = vw * 8
+ uh = vh * 8
+
+ rs = "\x1D\x2A" + chr(vw) + chr(vh) + "\x00"
+
+ for y in range(vh):
+ for x in range(uw):
+ byte = 0
+ for bit in range(8):
+ try:
+ byte |= 2**bit and (image.getpixel((x, (y+1)*8 - (bit+1)*8)) > 0)
+ except IndexError:
+ pass
+ rs += chr(byte)
+
+ return rs + "\x1D\x2F\x00"
+
Added: gnue-pointofsale/src/hardware/receiptprinter/plain.py
===================================================================
--- gnue-pointofsale/src/hardware/receiptprinter/plain.py 2005-04-19
12:09:26 UTC (rev 218)
+++ gnue-pointofsale/src/hardware/receiptprinter/plain.py 2005-04-23
12:05:40 UTC (rev 219)
@@ -0,0 +1,320 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2003-2005 Free Software Foundation
+#
+# FILE:
+# receiptprinters/plain.py
+#
+# DESCRIPTION:
+# Receipt Printer driver (plain-text)
+#
+# NOTES:
+#
+
+__all__ = ['Driver']
+
+from gnue.common.events.EventAware import EventAware
+from gnue.common.utils.TextUtils import *
+from gnue.pointofsale.IOProxy import simpleOpen
+from cStringIO import StringIO
+import time
+
+try:
+ import Image
+except:
+ Image = None
+
+dollarFormat = '$%.02f'
+
+BLACK = 0
+RED = 1
+
+
+class Driver(EventAware):
+
+ ##########################################################
+ #
+ #
+
+ def init(self):
+ pass
+
+
+ ##########################################################
+ #
+ #
+
+ def __init__(self, instance, params):
+ EventAware.__init__(self, instance)
+ self.instance = instance
+ self.__dict__.update(params)
+ self.device_params = params
+ self.output = ""
+ self.totals = {}
+ self.newline = "\n"
+
+ # Get the logo
+ logo = gConfig("ReceiptLogo")
+
+ # TODO: Disabling until I get the ESC/POS stuff worked out
+ if 0: # logo and Image:
+ self.logo = Image.open(logo)
+ else:
+ self.logo = None
+
+ self.width = hasattr(self,'width') and self.width or 40
+
+ self.totalFields = ( ('subtotal',_('Subtotal')),
+ ('tax','MS Sales Tax (7%)'),
+ ('total',_('Total')) )
+
+ self.totalFieldMapping = {}
+
+ self.registerEventListeners( {
+ 'BeginTicket': self._BeginTicket,
+ 'ReprintTicket': self.printTicket,
+ 'EndTicket': self._EndTicket,
+ 'CancelTicket': self._CancelTicket,
+ 'AddTender': self._AddTender,
+ 'AddTicketItem': self._AddTicketItem,
+ 'CancelTicketItem': self._CancelTicketItem,
+ 'UpdateTotal': self._UpdateTotal,
+ 'ReceiptPrinter:ReceiptTorn': self._ReceiptTorn } )
+
+ self.init()
+
+ #
+ #
+ #
+ def printTicket(self, event=None):
+ if not self.output:
+ return
+
+ try:
+ copies = int(self.device_params['copies'])
+ except:
+ copies = 1
+
+ while copies:
+ d = simpleOpen(**self.device_params)
+ self.output.seek(0)
+ d.write(self.output.read())
+ d.close()
+ copies -= 1
+ if copies:
+ self.cutBetweenSheets()
+
+
+
+ def printHeader(self):
+ self.output.write(self.reset())
+ if self.logo:
+ self.write(self.drawImage(self.logo))
+ self.write( gConfig("ReceiptHeader").replace('\\n','\n'),
alignment=ALIGN_CENTER)
+
+
+ def printFooter(self):
+ self.write( gConfig("ReceiptFooter").replace('\\n','\n'),
alignment=ALIGN_CENTER, color=RED)
+
+ shouter = self.dispatchEvent('Receipt:GetNotice')
+## shouter = """\
+##Did you know? Old Towne Market has
+##a professional portrait studio. Let
+##us take your next family portrait,
+##senior picture, or holiday photo."""
+
+ if shouter:
+ self.write('\n***************************************', indent=1,
color=1)
+ self.write(shouter, indent=2)
+ self.write('***************************************', indent=1, color=1)
+
+ #
+ #
+ #
+ def _BeginTicket(self, event):
+ try:
+ self.output.close()
+ except:
+ pass
+
+ self.tenders = []
+
+ self.output = StringIO()
+ self.doublespace = 0
+ self.totals = {}
+
+ self.printHeader()
+ self.write("\nSALES RECEIPT", double=1, alignment=ALIGN_CENTER)
+ self.write("""
+----------------------------------------
+Trans #%s %s %s
+""" % (event.serial, time.strftime("%m/%d/%y
%H:%M:%S",time.localtime(time.time())),self.instance.handler._login))
+
+ def _CancelTicket(self, event):
+ self.write('\n**** CANCELED ****\n', color=RED, double=1,
alignment=ALIGN_CENTER)
+ self.output.write(self.formfeed())
+ self.printTicket()
+
+ def _EndTicket(self, event):
+ self.output.write(" ----------\n")
+ for field, display in self.totalFields:
+ try:
+ amt = self.totals[field]
+ except KeyError:
+ amt = 0
+
+ self.write((display + ":").ljust(28)[:28]+ " " + comify(amt).rjust(10))
+
+ self.output.write(" ----------\n")
+ for tender in self.tenders:
+ self.write(tender)
+## self.write("\n----------------------------------------")
+ self.write("")
+ self.printFooter()
+ self.output.write(self.formfeed())
+ self.printTicket()
+
+
+ def _AddTicketItem(self, event):
+ if event.quantity > 1:
+ self.output.write(' %s x $%.02f ea\n' % (event.quantity, event.each))
+ self.write(str(event.department or "").ljust(3)[:3] + " " + \
+ str(event.description or "").upper().ljust(24)[:24] + " " + \
+ comify(event.extended,2).rjust(10) + \
+ (event.taxable and '*' or ' '))
+
+
+ def _AddTender(self, event):
+ # TODO
+
+ self.tenders.append (string.capwords('TENDER ' +
event.type).ljust(28)[:28] + " " + \
+ comify(event.amount).rjust(10))
+
+ def _CancelTicketItem(self, event):
+ pass
+
+ def _UpdateTotal(self, event):
+ self.totals[event.field] = event.amount
+
+ def write(self, text, double=0, bold=0, color=BLACK, underline=0,
+ doubleheight=0, alignment=ALIGN_LEFT, eol=1, width=0, indent=0):
+
+ splittext = str(text).split('\n')
+ i = 0
+ linehead = ""
+
+ for line in splittext:
+ divisor = 1
+
+ if underline:
+ self.output.write(self.beginUnderline())
+ if doubleheight:
+ self.output.write(self.beginDoubleHeight())
+ if double:
+ self.output.write(self.beginDouble())
+ if color:
+ self.output.write(self.beginColor(color))
+ if bold:
+ self.output.write(self.beginBold())
+
+ if self.doublespace:
+ l = ""
+ for char in tuple(line):
+ l += char + ' '
+ line = l[:-1]
+ elif double:
+ divisor = 2
+
+ self.output.write(' '*indent + lineWrap(line, alignment=alignment,
eol=0, maxWidth=int((width or self.width)/divisor)-indent).replace('\n','\n' +
' '* indent))
+
+ if bold:
+ self.output.write(self.endBold())
+ if color:
+ self.output.write(self.endColor(color))
+ if double:
+ self.output.write(self.endDouble())
+ if doubleheight:
+ self.output.write(self.endDoubleHeight())
+ if underline:
+ self.output.write(self.endUnderline())
+
+ if i < len(splittext)-1:
+ self.output.write(self.newline)
+
+ i += 1
+
+ if eol:
+ self.output.write(self.newline)
+
+ def writeTuple(self, list):
+ i = 0
+ for set in list:
+ if i != len(list) - 1:
+ list['eol'] = 0
+ self.write(**list)
+
+ def reset(self):
+ return ""
+
+ def formfeed(self):
+ return '\n\n\n\n\n\n\n'
+
+ def beginColor(self):
+ return ""
+
+ def endColor(self):
+ return ""
+
+ def beginBold(self):
+ return ""
+
+ def endBold(self):
+ return ""
+
+ def beginDouble(self):
+ self.doublespace = 1
+ return ""
+
+ def endDouble(self):
+ self.doublespace = 0
+ return ""
+
+ def beginDoubleHeight(self):
+ return ""
+
+ def endDoubleHeight(self):
+ return ""
+
+ def beginUnderline(self):
+ return ""
+
+ def endUnderline(self):
+ return ""
+
+ def drawImage(self, image):
+ return ""
+
+ def cutBetweenSheets(self):
+ self.__receiptTorn = 0
+ self.dispatchEvent('Prompt', label='Tear off receipt and press enter:',
response='ReceiptPrinter:ReceiptTorn')
+ while not self.__receiptTorn:
+ pass
+
+ def _ReceiptTorn(self, event):
+ self.__receiptTorn = 1
Added: gnue-pointofsale/src/payments/__init__.py
===================================================================
Modified: hotline/forms/hotline-en.gfd
===================================================================
--- hotline/forms/hotline-en.gfd 2005-04-19 12:09:26 UTC (rev 218)
+++ hotline/forms/hotline-en.gfd 2005-04-23 12:05:40 UTC (rev 219)
@@ -196,10 +196,10 @@
</block>
<block name="blkSelect">
- <field name="fldMitarbeiter" field="hotline_mitarbeiter" fk_key="gnue_id"
- fk_description="hotline_name" fk_source="dtsContributor"/>
+ <field name="fldMitarbeiter" fk_source="dtsContributor" fk_key="gnue_id"
+ fk_description="hotline_name" />
<field name="fldStart"/>
- <field name="fldKunde" field="hotline_kunde" case="upper"/>
+ <field name="fldKunde" case="upper"/>
<field name="fldName"/>
</block>
Modified: hotline/forms/kunden.gfd
===================================================================
--- hotline/forms/kunden.gfd 2005-04-19 12:09:26 UTC (rev 218)
+++ hotline/forms/kunden.gfd 2005-04-23 12:05:40 UTC (rev 219)
@@ -27,7 +27,11 @@
<form title="Kunden / Kontakte">
<options/>
<datasource name="dtsHotlineKunde" connection="hotline"
- table="hotline_kunde"/>
+ table="hotline_kunde">
+ <sortorder>
+ <sortfield name="hotline_nummer"/>
+ </sortorder>
+ </datasource>
<datasource name="dtsHotlineLand" connection="hotline"
table="hotline_land" prequery="Y"/>
<datasource name="dtsHotlineKontakt" connection="hotline"
@@ -147,39 +151,39 @@
<entry name="entHotlineBemerkung" Char:height="1" Char:width="50"
Char:x="20" Char:y="13" block="blkHotlineKunde"
field="fldHotlineBemerkung" label=""/>
- </page>
- <page name="Kontakte">
+
+ <!-- Contacts -->
<label name="lblName" Char:height="1" Char:width="4" Char:x="1"
- Char:y="1" text="Name"/>
+ Char:y="14" text="Name"/>
<label name="lblBemerkung" Char:height="1" Char:width="9" Char:x="37"
- Char:y="1" text="Bemerkung"/>
+ Char:y="14" text="Bemerkung"/>
<entry name="entHotlineName" Char:height="1" Char:width="35" Char:x="1"
- Char:y="2" block="blkHotlineKontakt" field="fldHotlineName" label=""
+ Char:y="15" block="blkHotlineKontakt" field="fldHotlineName" label=""
rows="10"/>
<entry name="entHotlineBemerkung" Char:height="1" Char:width="35"
- Char:x="37" Char:y="2" block="blkHotlineKontakt"
+ Char:x="37" Char:y="15" block="blkHotlineKontakt"
field="fldHotlineBemerkung" label="" rows="10"/>
<label name="lblTelefon" Char:height="1" Char:width="7" Char:x="1"
- Char:y="13" text="Telefon"/>
+ Char:y="26" text="Telefon"/>
<entry name="entHotlineTelefon" Char:height="1" Char:width="62"
- Char:x="10" Char:y="13" block="blkHotlineKontakt"
+ Char:x="10" Char:y="26" block="blkHotlineKontakt"
field="fldHotlineTelefon" label=""/>
<label name="lblHandy" Char:height="1" Char:width="5" Char:x="1"
- Char:y="14" text="Handy"/>
+ Char:y="27" text="Handy"/>
<entry name="entHotlineHandy" Char:height="1" Char:width="62" Char:x="10"
- Char:y="14" block="blkHotlineKontakt" field="fldHotlineHandy"
+ Char:y="27" block="blkHotlineKontakt" field="fldHotlineHandy"
label=""/>
<label name="lblTelefax" Char:height="1" Char:width="7" Char:x="1"
- Char:y="15" text="Telefax"/>
+ Char:y="28" text="Telefax"/>
<entry name="entHotlineTelefax" Char:height="1" Char:width="62"
- Char:x="10" Char:y="15" block="blkHotlineKontakt"
+ Char:x="10" Char:y="28" block="blkHotlineKontakt"
field="fldHotlineTelefax" label=""/>
<label name="lblEMail" Char:height="1" Char:width="6" Char:x="1"
- Char:y="16" text="E-Mail"/>
+ Char:y="29" text="E-Mail"/>
<entry name="entHotlineEmail" Char:height="1" Char:width="62" Char:x="10"
- Char:y="16" block="blkHotlineKontakt" field="fldHotlineEmail"
+ Char:y="29" block="blkHotlineKontakt" field="fldHotlineEmail"
label=""/>
</page>
</layout>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue-contrib] r219 - / gnue-invoice/scripts gnue-pointofsale gnue-pointofsale/doc gnue-pointofsale/doc/technotes gnue-pointofsale/samples gnue-pointofsale/samples/oldtownemarket gnue-pointofsale/scripts gnue-pointofsale/src gnue-pointofsale/src/backends gnue-pointofsale/src/backends/Base gnue-pointofsale/src/backends/gnue_sb gnue-pointofsale/src/frontends gnue-pointofsale/src/frontends/Base gnue-pointofsale/src/frontends/wx gnue-pointofsale/src/hardware gnue-pointofsale/src/hardware/barcodereader gnue-pointofsale/src/hardware/cashdrawer gnue-pointofsale/src/hardware/logprinter gnue-pointofsale/src/hardware/poledisplay gnue-pointofsale/src/hardware/receiptprinter gnue-pointofsale/src/payments hotline/forms,
reinhard <=