Pocketbiz Android Sales Order Plus
ESPocketBiz – Sales Order Plus
Entersoft Business Suite® | Entersoft CRM® | Entersoft Mobile Suite®
Τεχνικό εγχειρίδιο
Περιεχόμενα
- 1 Ταυτότητα
- 2 Copyright
- 3 = Sales order Plus
- 3.1 Σχετικοί Πίνακες
- 3.2 Γενικά
- 3.3 Παραμετροποίηση
- 3.4 PocketBiz Scanning
Ταυτότητα
Έκδοση κειμένου 2.0
Τελ. ενημέρωση Ιούνιος 2021
Copyright
© Copyright 2011 Entersoft A.E. Με την επιφύλαξη όλων των νόμιμων δικαιωμάτων.
Δεν επιτρέπεται η αναδημοσίευση ή μετάδοση με οποιαδήποτε μορφή και για οποιοδήποτε λόγο μέρους ή όλου του παρόντος εγχειριδίου, χωρίς τη ρητή άδεια της Entersoft Α.Ε.
Όσον αφορά το περιεχόμενο του παρόντος…
- Μπορεί να μεταβληθεί οποιαδήποτε στιγμή.
- Εξυπηρετεί αποκλειστικά πληροφοριακούς σκοπούς.
- Δεν παρέχεται εγγύηση για την ύπαρξη τυχόν λαθών ή για τη λανθασμένη χρήση ή για μη επιθυμητά αποτελέσματα από τη χρήση των προτεινόμενων στο παρόν διαδικασιών.
= Sales order Plus
Περιγράφεται η παραμετροποίηση για τη λειτουργικότητα του νέου Sales Order
Σχετικοί Πίνακες
| Πίνακας | Περιγραφή | Article Type | Sync Type |
|---|---|---|---|
| SDT | Πίνακας παραστατικών (Πεδίο Configuration) | DOWNLOAD | PUBLIC |
Γενικά
Κατάλογος
Η αρχική οθόνη που ανοίγει για το Sales Order Plus έχει την παρακάτω μορφή:
Ουσιαστικά η καταχώρηση παραγγελίας ξεκινάει από την οθόνη του καταλόγου για καταχώρηση ειδών.
Στην αρχική οθόνη του καταλόγου έχουμε τις εξής επιλογές:
Η επιλογή του tab του καταλόγου
Η επιλογή του tab του καλαθιού
Η επιλογή του tab των στοιχείων του παραστατικού
Ο κατάλογος των ειδών με δυνατότητα καταχώρησης ποσότητας, στοκ, διανομής κτλ
Το μενού των κατηγοριών των ειδών
Το κουμπί για την ενεργοποίηση/απενεργοποίηση της γκάμας του πελάτη
Φίλτρα αναζήτησης στα αντίστοιχα πεδία των επικεφαλίδων
Επιλογές ταξινόμησης με βάση το αντίστοιχο πεδίο της επικεφαλίδας
Αναφορές μέσα στην παραγγελία
Καλάθι
Πατώντας το εικονίδιο του καλαθιού μεταβαίνουμε στο δεύτερο tab της παραγγελίας όπου βρίσκεται η σύνοψη της παραγγελίας.
Η οθόνη είναι αντίστοιχη με αυτή του καταλόγου, με τη διαφορά ότι τα είδη που εμφανίζονται είναι αυτά που έχει γίνει καταχώρηση παραγγελίας, στοκ κτλ.
Επίσης από την οθόνη του καλαθιού γίνεται η αποθήκευση της παραγγελίας.
Αποθήκευση
Σύνοψη παραγγελίας
Μενού διαγραφής παραγγελίας
Πληροφορίες
Το τρίτο tab αφορά στα στοιχεία του παραστατικού, δηλαδή τον πελάτη για την παραγγελία, σχόλια της παραγγελίας, ημερομηνία παράδοσης κτλ.
Παραμετροποίηση
Για την παραμετροποίηση των παραπάνω οθονών υπάρχει ένα XML το οποιό περιλαμβάνει όλη την παραμετροποίηση.
Το XML μπορεί να μπει είτε στον Configuration, με παράμετρο SalesConfig είτε στον πίνακα SDT στο πεδίο Configuration (με JSON format).
Το XML αποτελείται από δύο βασικά tags, του header που αφορά την οθόνη των πληροφοριών του παραστατικού και το model που αφορά τις οθόνες καταλόγου και καλαθιού.
Παραμετροποίηση Καταλόγου/Καλαθιού
SQL
Για την παραμετροποίηση του καταλόγου & του καλαθιού πρέπει αρχικά να γραφτεί το select που θα φέρει τα είδη.
Οπότε μέσα στο τμήμα του model ανοίγουμε το tag sql. Οπότε έχουμε το παρακάτω
<sql>
<query type="offline"
select=" stiname, STI.codcode,ifnull(STI.stiratiofrom,0) as stiratiofrom,ifnull(STI.stiratioto,0) as stiratioto,tblinvdetail.ssdgrossvalue,tblinvdetail.stdqtyB "
fromSTI=" "
range=""
where="STI.StiType=1"
groupby=""
orderby="" />
</sql>
Στο query type συμπληρώνουμε τον τύπο που παίζει το query (online, offline) (Σ.Σ. υποστηρίζεται προς το παρών μόνο το offline)
Στο select γράφουμε τα πεδία που θέλουμε να φέρουμε είτε για να εμφανίσουμε, είτε για να είναι editable. Με την προκαθορισμένη λειτουργία το select φέρνει πεδία χωρίς να συμπληρώσουμε κάτι εμείς π.χ. stiid, stdqtyA κτλ. Αν θέλουμε να φέρουμε επιπλέον πεδία τα γράφουμε στο select. Για τα διαθέσιμα πεδία που φέρνει μπορούμε να δούμε το database queries.
Το fromSTi περιλαμβάνει το παρακάτω select
FROM STI INNER JOIN tblInvDetail ON STI.stiid = tblInvDetail.stiid and ifnull(tblinvdetail.invmasterid, 0) = $INVMASTERID$ LEFT OUTER JOIN stp AS DefaultPriceList ON DefaultPriceList.stiid = sti.stiid and ifnull(DefaultPriceList.pstid , 0) = $pstid$ LEFT OUTER JOIN stp AS CustomerPriceList ON CustomerPriceList.stiid = sti.stiid AND ifnull(CustomerPriceList.pstid,0) = $cus.pstid$ INNER JOIN VAT ON STI.vatid = VAT.vatid
Οπότε πάνω σε αυτό το μπορούμε να κάνουμε join επιπλέον πίνακες π.χ. για προηγούμενες παραγγελίες άρα γίνεται
fromSTI=" left outer join tblSuggestAlgData on sti.stiid=tblSuggestAlgData.stiid and tblSuggestAlgData.cusid=$CUSID$ "
Το tag range περιλαμβάνει το join με τον πίνακα για τη γκάμα, για παράδειγμα
range=" inner join tblcusstirange on sti.stiid=tblcusstirange.stiid and tblcusstirange.cusid=$CUSID$ "
Στο where βάζουμε τη συνθήκη για να φιλτράρουμε τα είδη.
Groupby και orderby, σε ποια πεδία θα γίνει το γκουπάρισμα και με ποια σειρά θα εμφανιστούν τα είδη αντίστοιχα.
Field
Αφού έχουμε τελειώσει με το select προχωράμε στον προσδιορισμό του τύπου των πεδίων που θέλουμε να εμφανίσουμε. Αυτό γίνεται στο tag fields, όπως παρακάτω
<fields>
<field datamember="" databasetype="" pocketbiztype="" editable="" sql=""/>
<field datamember="" databasetype="" pocketbiztype="" editable="" sql=""/>
…
</fields>
Όπου datamember αφορά το πεδίο από το select.
Databasetype αφορά πως θα αποθηκευτεί στη βάση, με διαθέσιμες επιλογές float, int, nvarchar.
PocketbizType πως θα γίνει το format του πεδίο στην οθόνη με διαθέσιμες επιλογές sql, Boolean, price, value, discount, quantity, text
Editable, αφορά αν το πεδίο μπορεί να επεξεργαστεί από το χρήστη. Διαθέσιμες τιμές 0, 1.
SQL, το query που θα τρέξει για να φέρει τιμές αν το πεδίο είναι pocketbiztype= SQL. Για παράδειγμα SQL= "select 'InStock' as displayvalue,'InStock' as storevalue UNION ALL select 'NOOS' as displayvalue,'NOOS' as storevalue UNION ALL select 'OOS' as displayvalue,'OOS' as storevalue"
Για πεδία που ο χρήστης καταχωρεί ποσότητες (π.χ. στοκ ή διανομή) πρέπει να προστεθεί ακόμα ένα attribute το storemember που αναπαριστά το πεδίο του tblinvdetail που θα γίνει η καταχώρηση όπως το παρακάτω
<field datamember=\"cusstockqty\" storemember=\"cusstockqty\" databasetype=\"FLOAT\" pocketbiztype=\"quantity\" editable=\"1\"/>
Basket
Στο tag basket ξεκινάει ουσιαστικά η παραμετροποίηση για την οθόνη του καλαθιού
<basket>
<grid>
<headers freezecolumns="" height="" textsize="" />
<rows>
<row height="" textsize=""/>
</rows>
<columns>
<column order="" title="" datamember="" sortable="" sortmember="" filterable="" width="" widgettype="">
<widget align = ""/>
</column>
…..
</grid>
</basket>
Στο tag header το attribute freezecolumns αφορά το πόσες στήλες θα είναι ακίνητες στο οριζόντιο scrolling.
Το attribute height αφορά στο ύψος της κεφαλίδας και το textsize είναι το μέγεθος της γραμματοσειράς της κεφαλίδας.
Αντίστοιχα στο tag rows το attribute height και textsize αφορά στο ύψος της γραμμής και το μέγεθος της γραμματοσειράς αντίστοιχα.
Στη συνέχεια ξεκινάει η παραμετροποίηση για κάθε στήλη στο tag columns. Τα attribute που αφορούν το εκάστοτε column είναι τα
Order, που σχετίζεται με τη σειρά εμφάνισης της στήλης στο grid.
Title, όπου καταχωρείται ο τίτλος της στήλης
Datamember, το συμπληρώνουμε με το πεδίο που θα εμφανιστεί είτε θα είναι διαθέσιμο για επεξεργασία από το select στο SQL των ειδών.
Sortable, στο attribute αυτό ορίζουμε αν η στήλη θα έχει δυνατότητα να ταξινομήσει τον κατάλογο των ειδών. Οι τιμές που παίρνει είναι 0 και 1.
Sortmember, ορίζεται το πεδίο που θα γίνει sort με τη στήλη.
Filterable, ορίζεται αν η στήλη θα έχει δυνατότητα για αναζήτηση
Width, το πλάτος της στήλης
Widgettype, το γραφικό widget για την αναπαράσταση της στήλης. Οι διαθέσιμες τιμές είναι HTML, NUMERIC, LIST, CHECKBOX. Widgetτype χρειάζεται μόνο σε editable πεδία (εκτός από την επιλογή HTML). Η επιλογή HTML αφορά σε στήλη μη editable που έχει κάποιο html format (π.χ. χρώμα,bold, italic κτλ).
Το NUMERIC widget υποστηρίζει τις ακόλουθες ιδιότητες, σε ξεχωριστό tag, το widget:
- beforecomma: ορίζει τον αριθμό των ψηφίων που μπορούν να εισαχθούν στο ακέραιο τμήμα του αριθμού. Αν δεν οριστεί, χρησιμοποιείται η τιμή 5.
- aftercomma: ορίζει τον αριθμό των ψηφίων που μπορούν να εισαχθούν στο δεκαδικό τμήμα του αριθμού. Αν δεν οριστεί, χρησιμοποιείται η τιμή 2.
- showunderbar: με τιμή 0 δηλώνει την εμφάνιση των κουμπιών +, -. Με τιμή 1, κρύβονται τα κουμπιά αυτά και εμφανίζεται η κλασική γραμμή (underbar) του EditText.
- maxvalue: ορίζει την μέγιστη επιτρεπτή αριθμητική τιμή. Αν ο χρήστης εισαγάγει τιμή μεγαλύτερη από αυτήν, τότε αυτόματα το widget θα την αλλάξει στην μέγιστη τιμή. Μπορεί να λάβει, σαν τιμή, δεκαδικό αριθμό με διαχωριστή δεκαδικών την τελεία ".". Αν δεν οριστεί, η μέγιστη επιτρεπτή τιμή είναι αυτή που μπορεί να εισαχθεί με τον δηλωμένο συνδυασμό των τιμών beforecomma και aftercomma.
Η επιλογή που καθορίζει τη διάταξη της στήλης στο tag widget είναι το align, δηλαδή <widget align = ""/>. Λαμβάνει μία από τις τιμές "CENTER", "LEFT", "RIGHT". Αν δεν οριστεί, χρησιμοποιείται η τιμή CENTER.
Για παράδειγμα έχουμε
<column order=\"50\" title=\"Q/Case\" datamember=\"stdqtyA\" sortable=\"1\" filterable=\"1\" defaultfilter=\">0\" showzeros=\"0\" width=\"150\" widgettype=\"NUMERIC\">
<widget align = \"CENTER\" beforecomma=\"5\" aftercomma=\"0\" showunderbar=\"1\"/> </column>
Grid auto adjust
Για να πετύχουμε αυτόματη ρύθμιση του πλάτους των στηλών σε οποιαδήποτε συσκευή βάζουμε το παρακάτω:
<grid useDp=\"1\"> deprecated.
Το grid κάνει auto adjust by default. useDP = 1 disables auto adjustment
Catalogue
Όπως ορίζεται η παραμετροποίηση για το basket, με τον ίδιο τρόπο ορίζεται και η παραμετροποίηση για τον κατάλογο
<catalogue>
<grid>
<headers freezecolumns="" height="" textsize="" />
<rows>
<row height="" textsize=""/>
</rows>
<columns>
<column order="" title="" datamember="" sortable="" sortmember="" filterable="" width="" widgettype="">
<widget align = ""/>
</column>
…..
</grid>
<filters>
<filter filtername=\"RangeSetting\" selected=\"true\" visible=\"false\"/>
</filters>
</ catalogue>
Range button (enable/disable)
Με visible=false, στο <filter filtername=\"RangeSetting\" selected=\"true\" visible=\"false\"/> μπορούμε να απενεργοποιήσουμε το κουμπί της γκάμας (Range).
Φίλτρα Kαταλόγου
Από την έκδοση 8.32.0.0 και άνω, υποστηρίζονται φίλτρα στον κατάλογο, ξεχωριστά από αυτά του range και των φίλτρων στο grid. Τα φίλτρα αυτά αποτελούν υλοποίηση των αντίστοιχων που υπάρχουν στο παλιό Sales/XVan.
Ενεργοποιούνται μόνο στον κατάλογο με το κουμπί που σημειώνεται παρακάτω
Η επιλογή του κουμπιού ανοίγει ένα dialog (ExtendedFiltersDialog) από το οποίο γίνεται επιλογή των φίλτρων. Η εφαρμογή των φίλτρων αλλάζει το dataset του καταλόγου, δηλαδή τα δεδομένα που εμφανίζονται στον κατάλογο προέρχονται από το sql του xml και κάθε εφαρμογή του φίλτρου ξανατρέχει το sql με τα επιλεγμένα φίλτρα.
Στο παρακάτω dialog έχουν δημιουργηθεί τρία φίλτρα, ένα τύπου edittext, ένα τύπου drop down και ένα τύπου δένδρο. Στην έκδοση 8.32.0.0 υποστηρίζονται αυτοί οι τρεις τύποι φίλτρων. Τα κουμπιά ενεργούν ως εξής:
- Clear Filters: Καθαρίζει τα φίλτρα, κλείνει το dialog και ανανεώνει τον κατάλογο
- Discard Search: Κλείνει το dialog με φίλτρα χωρίς άλλη ενέργεια.
- Apply Filters: Εφαρμόζει τα φίλτρα, κλείνει το dialog και ανανεώνει τον κατάλογο
Η παραμετροποίηση των extended φίλτρων γίνεται από το SalesConfigXML και συγκεκριμένα στο node modelfields
<field datamember=\"ExtraFilter1\" databasetype=\"nvarchar\" pocketbiztype=\"TEXT\" editable=\"0\" useinsearch=\"1\" replacetoken=\"$CTGOUTLINE$\" filtertitle=\"\" sql=\"\"/>
<field datamember=\"ExtraFilter2\" databasetype=\"nvarchar\" pocketbiztype=\"SQL\" editable=\"0\" useinsearch=\"1\" replacetoken=\"$CTGOUTLINE$\" filtertitle=\"Second Filter\" sql=\"select ctgoutline as storevalue, ctgdescr as displayvalue from CTG\"/>
Το query έχει τη γνωστή δομή, store και display value.
<field datamember=\"ExtraFilter3\" databasetype=\"nvarchar\" pocketbiztype=\"TREE\" editable=\"0\" useinsearch=\"1\" replacetoken=\"$CTGOUTLINE$\" filtertitle=\"Tree Filter\" sql=\"select ctgid as id, ctgoutline as outline, ctgdescr as description from CTG\"/>
Για την επιλογή δενδρικού φίλτρου το πρέπει να οριστεί sql στο field της μορφής “select xxx as id, xxx as outline, xxx as description from TABLE”. Τα alias “id”, “outline”, “description” είναι υποχρεωτικό να υπάρχουν και να ονομάζονται έτσι ακριβώς.
Το κουμπί δίπλα στο edittext του δενδρικού φίλτρου εμφανίζει το popup με τα επίπεδα του δέντρου κατ’ αντιστοιχία με το popup των Κατηγοριών. Επίσης μπορεί ο χρήστης να γράψει κατευθείαν το outline της κατηγορίας που θέλει και να πατήσει apply filters.σσ
Σημείωση: Το παραπάνω παράδειγμα με 3 ίδια φίλτρα είναι αντιπροσωπευτικό αντιπαράδειγμα προς μίμηση, διότι το token “CTGOUTLINE” θα αντικατασταθεί από το πρώτο φίλτρο και τα επόμενα 2 θα αγνοηθούν, καθώς δεν θα υπάρχει token για να αλλάξουν στο query. Επομένως για φίλτρα με ίδιο token, υπερισχύει το πρώτο φίλτρο που έχει γραφτεί στο xml και τα υπόλοιπα αγνοούνται.
Σε σχέση με τις παλιότερες εκδόσεις, έχουν προστεθεί:
- useinsearch: Αν 1, τότε το field συμμετέχει στα φίλτρα
- replacetoken: Το token με τη γνωστή μορφή ($token$) το οποίο θα αντικατασταθεί στο sql του model query
- filtertitle: η περιγραφή του φίλτρου. Αν δεν δοθεί (αφεθεί κενό δηλαδή), ως περιγραφή του φίλτρου χρησιμοποιείται το datamember
Επιπρόσθετα, στο σχηματισμό των φίλτρων λαμβάνεται υπόψη και το Pocketbiztype. Αν είναι SQL, τότε το φίλτρο είναι drop down, σε οποιαδήποτε άλλη περίπτωση είναι Edittext. Το κουμπί εμφάνισης του dialog των φίλτρων εμφανίζεται αν υπάρχει τουλάχιστον ένα field που είναι χαρακτηρισμένο ως φίλτρο (useinsearch = 1).
Να σημειωθεί ότι τα φίλτρα έχουν ακριβώς τη λειτουργία του παλιού Sales/XVan, δηλαδή κάνουν απλή αντικατάσταση tokens με τιμές. Είναι ευθύνη του consultant να γράψει σωστά το query, ώστε να είναι σωστό μετά την αντικατάσταση των tokens με τις τιμές τους.
Summary
Στην οθόνη του καλαθιού υπάρχει στο κάτω μέρος μια παραμετροποιήσιμη σύνοψη της παραγγελίας, με το πλήθος των ποσοτήτων, την συνολική αξία και λοιπές πληροφορίες που μπορούμε να εμφανίσουμε.
Το section του summary έχει την παρακάτω μορφή
<summary>
<summaryitem group="" displaytext="" token="" order="" pocketbiztype="" format="" editable=""/>
<summaryitem group="" displaytext="" token="" order="" pocketbiztype="" format="" editable=""/>
… </summary>
Στο group βάζουμε τον αριθμό του group που σχετίζεται η εγγραφή Displaytext, είναι το όνομα που εμφανίζεται Token, συμπληρώνουμε με το token που θέλουμε να εμφανίσουμε Order η σειρά εμφάνισης
Παράδειγμα:
<summary> <summaryitem group=\"1\" displaytext=\"Quantity: \" token=\"$tdoqtya$\" order=\"1\" pocketbiztype=\"quantity\" format=\"###.##\" editable=\"0\"/>
<summaryitem group=\"1\" displaytext=\"Gross: \" token=\"$tdogrossvalue$\" order=\"2\" pocketbiztype=\"text\" format=\"\" editable=\"0\"/>
<summaryitem group=\"1\" displaytext=\"Discounts: \" token=\"$sumDiscountValue$\" order=\"3\" pocketbiztype=\"text\" format=\"\" editable=\"0\"/>
<summaryitem group=\"1\" displaytext=\"VAT: \" token=\"$tdovatstock$\" order=\"4\" pocketbiztype=\"text\" format=\"\" editable=\"0\"/>
<summaryitem group=\"1\" displaytext=\"Payable: \" token=\"$tdosumvalue$\" order=\"5\" pocketbiztype=\"text\" format=\"\" editable=\"0\"/>
<summaryitem group=\"2\" displaytext=\"PayWay: \" token=\"$cpmid$\" order=\"3\" visible=\"0\" pocketbiztype=\"sql\" format=\"\" editable=\"1\" sql=\"select cpmid as storevalue, cpmtitle || ' ('||cpmdiscountpcnt||'%)' as displayvalue from cpm order by cpmcode\" defaultvaluesql=\"\"/> </summary>
Παράθυρο εκπτώσεων
Το παράθυρο εκπτώσεων ενεργοποιείται με το πλήκτρο
Πλέον παίρνει τις περιγραφές των controls από το SummaryXML.
Προστέθηκε το (προαιρετικό με default τιμή "1") visible πεδίο στο xml του Summary, το οποίο καθορίζει αν το πεδίο θα φαίνεται στο Summary
Στο παραπάνω παράδειγμα το πεδίο PayWay έχει visible=0 που σημαίνει ότι δεν θα εμφανιστεί στο summary αλλά εμφανίζεται κανονικά στο παράθυρο εκπτώσεων.
Το query που θα γεμίζει το spinner των cpm (τρόπων πληρωμής) ΔΕΝ απαιτείται πλέον να είναι περιέχει το '(xx.x%)' στο display value. Αποδεκτό είναι οποιοδήποτε valid sql query για τα extra fileds (πρέπει να περιέχει storevalue και displayvalue).
Παραμετροποίηση Πληροφοριών
Για την οθόνη των στοιχείων του παραστατικού η παραμετροποίηση στο XML ορίζεται στο tag header.
<header>
<sql>
<query type="" select="" from="" where="" groupby="" orderby=""/>
</sql>
<fields>
<field datamember="" storemember="" databasetype="" mandatory="" defaultvaluesql=""/>
<field datamember="" storemember="" databasetype="" mandatory="" defaultvaluesql=""/>
…
</fields>
<UI>
<section title="" order="">
<item validation="" title="" datamember="" pocketbiztype="" format="" editable="" order ="" multiline="" spinnersql="" />
…
</section>
<section title="" order="">
…
</section>
…
</UI>
</header>
SQL
Στο query type συμπληρώνουμε τον τύπο που παίζει το query (online, offline) (Σ.Σ. υποστηρίζεται προς το παρών μόνο το offline)
Στο select γράφουμε τα πεδία που θέλουμε να φέρουμε είτε για να εμφανίσουμε, είτε για να είναι editable.
Στο from γράφουμε τους πίνακες από όπου θέλουμε να εμφανίσουμε για παράδειγμα
from="tblinvmaster inner join cus on tblinvmaster.cusid = cus.cusid inner join lee on lee.leeid = cus.leeid inner join adr on cus.adriddest=adr.adrid inner join sdt on sdt.sdtid = tblinvmaster.sdtid "
Στο where βάζουμε τη συνθήκη για να φιλτράρουμε τα πεδία.
where="tblinvmaster.invmasterid = $invmasterid$"
Groupby και orderby, σε ποια πεδία θα γίνει το γκουπάρισμα και με ποια σειρά θα εμφανιστούν τα είδη αντίστοιχα.
Fields
Αφού έχουμε τελειώσει με το select προχωράμε στον προσδιορισμό του τύπου των πεδίων που θέλουμε να εμφανίσουμε. Αυτό γίνεται στο tag fields, όπως παρακάτω
<fields>
<field datamember="" storemember="" databasetype="" mandatory="" defaultvaluesql=""/>
<field datamember="" storemember="" databasetype="" mandatory="" defaultvaluesql=""/>
…
</fields>
Όπου datamember αφορά το πεδίο από το select.
Για πεδία που ο χρήστης καταχωρεί πρέπει να προστεθεί ακόμα ένα attribute το storemember που αναπαριστά το πεδίο του tblinvmaster που θα γίνει η καταχώρηση όπως το παρακάτω
Databasetype αφορά πως θα αποθηκευτεί στη βάση, με διαθέσιμες επιλογές float, int, nvarchar.
Mandatory, αφορά αν το πεδίο είναι υποχρεωτικό. Διαθέσιμες τιμές 0, 1.
defaultvaluesql, συμπληρώνουμε με τη default τιμή που θα πάρει το πεδίο μας αν είναι τύπου SQL
UI
Στο tag UI γίνεται η παραμετροποίηση των πεδίων που θα εμφανιστούν στην οθόνη καθώς και το format τους.
<UI>
<section title="" order="">
<item validation="" title="" datamember="" pocketbiztype="" format="" editable="" order ="" multiline="" spinnersql="" />
<item validation="" title="" datamember="" pocketbiztype="" format="" editable="" order ="" multiline="" spinnersql="" />
…
</section>
<section title="" order="">
…
</section>
…
</UI>
Στο tag section μπορούμε να ομαδοποιήσουμε τα πεδία του header.
Στη συνέχεια ορίζουμε τα πεδία, με κάθε πεδίο να ορίζεται στο tag item, το οποίο περιλαμβάνει τα εξής attributes
Title, το κείμενο που θα εμφανιστεί
Datamember, το πεδίο από select
PocketbizType, SQL, SEARCHLIST, BOOLEAN, DISCOUNT, VALUE, PRICE, TEXT
Format
Editable, με διαθέσιμες τιμές 0 και 1
Order, η σειρά εμφάνισης στο εκάστοτε section
SQL, το query για τα πεδία που είναι pocketbiztype SQL
Προσθήκη παραγγελίας από pdf / Fast entry
Ο Χρήστης εναλλακτικά μπορεί να εισάγει μια παραγγελία από pdf κατάλογο ειδών. Ενώ βρίσκεται στον κατάλογο ειδών, πατάει τις 3 τελείες πάνω δεξιά και από εκεί επιλέγει «Εισαγωγή από PDF”.
Ανοίγει μια οθόνη με τις κατηγορίες/υποκατηγορίες ειδών και επιλέγουμε αυτή που επιθυμούμε, ή ακόμη και το είδος.
Το λειτουργικό αναλαμβάνει να δείξει τις διαθέσιμες εφαρμογές (pdf readers) και τελικά να το δείξει με την εφαρμογή που επιλέξει ο χρήστης.
Έτσι ανοίγει ένας κατάλογος της μορφής δεξιά (pdf), όπου υπάρχουν όλες οι φωτογραφίες των διαθέσιμων προς πώληση προϊόντων με κάποιον κωδικό δίπλα ή πάνω στην φωτογραφία.
O κατάλογος (pdf) είναι συγκεκριμένος ανάλογα με την διασύνδεση/παραμετροποίηση που έχει γίνει (π.χ. αν επιλέξουμε PARKER θα ανοίξει το Parker pdf, αν επιλέξουμε Rotring, θα ανοίξει το αντίστοιχο pdf.)
Αφού γίνει η επιλογή του είδος πατώντας πάνω στην συγκεκριμένη περιγραφή, ανοίγει ένα νέο παράθυρο όπου ανάλογα με την παραμετροποίηση μας ζητά τις επιθυμητές ποσότητες.
Οι ποσότητες που πληκτρολογούμε εκεί, θα εμφανιστούν κανονικά στο καλάθι μας.
Παραμετροποίηση
Tα δεδομένα που θα εμφανιστούν προκύπτουν από το SalesConfig XML (στο Configuration) και συγκεκριμένα από το query που υπάρχει στον κόμβο <MediaCategory>. Μπαίνει μετά τo tag model.
Στο tag MediaSql παραμετροποιούνται τα pdf από τον tblΜedia.
Παράδειγμα xml
<MediaCategory>
<MediaSql>
<MediaQuery
type="offline"
select="ctg.ctgdescr as Descr, tblMedia.MediaID, ctg.iconmediaid as IconMediaID, FileName, IsLocalFile,URI,1 as qtytype,ctgoutline as outline"
from="ctg left outer join tblMedia on ctg.mediaid=tblMedia.mediaid" where="ctg.ctgoutline like '11%' OR ctg.ctgoutline like '12%' OR ctg.ctgoutline like '13%' OR ctg.ctgoutline like '14%'"
groupby=""
orderby="ctg.ctgoutline"/>
</MediaSql>
<fastentry>
<description title="Καταχώρηση Προϊόντων" showDatamember="stinameshort"/>
<fastEntryRows>
<fastEntryRow text="Ποσότητα Α:" datamember="stdqtyA" type="int"/>
<fastEntryRow text="Ποσότητα B:" datamember="stdqtyB" type="int"/>
</fastEntryRows>
</fastentry>
</MediaCategory>
Το παραπάνω παράδειγμα αφορά αρχείο pdf σχετιζόμενο με κάποια κατηγορία (ctg). Είναι εφικτή η παρουσίαση αρχείων (tblMedia) τα οποία δεν είναι σχετισμένα με κατηγορίες. Σε αυτή την περίπτωση το xml θα έχει τη μορφή
<MediaSql>
<MediaQuery type=\"offline\" select=\"FileName as Descr, tblMedia.MediaID, NULL as IconMediaID, FileName, IsLocalFile,URI,1 as qtytype,'1' as outline\" from=\"tblMedia"\ where=\"Filetype = 'pdf'\"/>
</MediaSql>
Στο παραπάνω παράδειγμα δεν υπάρχει σύνδεση με τον ctg πίνακα, επομένως δείχνονται αρχεία που δεν σχετίζονται με κατηγορία.
Προσοχή στο query το οποίο πρέπει να ορίζει αυστηρά τις κολώνες «Descr» (αυτή θα φαίνεται στο Popup με τα αρχεία) και Outline το οποίο χρειάζεται για τη σωστή δημιουργία του popup με τα pdf.
To <fast entry> παραμετροποιεί το dialog που ανοίγει όταν επιλέγουμε έναν σύνδεσμο σε ένα pdf
Μέσα στο option tag υποστηρίζονται τα παρακάτω properties:
- Type: Επιλογές είναι τα text/float/int ο οποίος καθορίζει το τύπο του πεδίου που θα μπορεί να εισάγει ο χρήστης. ΥΠΟΧΡΕΩΤΙΚΟ
- Descr: Επιλογή που καθορίζει το τι θα φαίνεται σαν hint πάνω στο edit text για να διευκολύνει το χρήστη. ΠΡΟΑΙΡΕΤΙΚΟ (αν και πιστεύω ότι καλό θα είναι να υπάρχει)
- Datamember: Το όνομα του πεδίου που θα αποθηκευτεί στην βάση. ΥΠΟΧΡΕΩΤΙΚΟ
Πλήρες παράδειγμα salesconfig:
Ακολουθούν screenshots από τα αντίστοιχα αρχεία
Το tblMedia πρέπει να βρίσκεται στον srArticles
Μορφή hyperlink για PDF
Στο pdf, τα hyperlinks που κρύβονται στις περιγραφές πρέπει να έχουν την παρακάτω μορφή: http://pbsales/110601.0015 (στο τέλος είναι το id του είδους)
Για την επεξεργασία των PDF πρέπει να διαθέτουμε έκδοση Acrobat που να υποστηρίζει hyperlinks.
Απλό FastEntry
Για τη χρήση απλού FastEntry χρειάζεται να προστεθεί η παρακάτω παραμετροποίηση στο SalesConfigXML, έξω από το node “model”.
<fastentry>
<description title=\"Καταχώρηση Προϊόντων\" showDatamember=\"stiname\"/>
<fastEntryRows>
<fastEntryRow text=\"Κωδικός:\" datamember=\"codcode\" type=\"int\" useInSearch=\"true\"/>
<fastEntryRow text=\"Ποσότητα Α:\" datamember=\"stdqtyA\" type=\"int\"/>
</fastEntryRows>
</fastentry>
Ο αλγόριθμος θα ψάξει στα προϊόντα του καταλόγου με το πεδίο που έχει useInSearch=”true” κατά το Lost focus του πεδίου. Στο συγκεκριμένο παράδειγμα, θα ψάξει προϊόντα με codecode αυτό που έχουμε γράψει στο edittext.
Αν βρει περισσότερα από 1 προϊόντα, επιστρέφει το πρώτο πάντα. Θα γράψει το πεδίο που ορίζεται στο showDatamember στο αντίστοιχο χώρο στο dialog.
Κατόπιν περνάει την ποσότητα από το 2ο edittext στο καλάθι υπολογίζοντας ποσότητεςΒ, εκπτώσεις, αθροίσματα κτλ. (όπως θα έκανε αν τα προϊόντα προστίθεντο με το χέρι από το grid).
Φυσικά μπορείτε να προσθέσετε οσαδήποτε πεδία μέσω του xml, αλλά αυτό δε συστήνεται. Συνήθως το πεδίο αναζήτησης και το πεδίο ποσότητας (Α ή Β) είναι επαρκή.
Tag <ProductInfo>
Με την χρήση του συγκεκριμένου tag, συνδέουμε τις φωτογραφίες των ειδών και παραμετροποιούμε την οθόνη με τις πληροφορίες του είδους (
εικονίδιο Info)
<ProductInfo>
<productInfoBanner query=\"SELECT TBLMEDIA.MediaID, as DocImageID, DateModified,URI, FileName as Description,filetype as filetype, islocalfile, filename from tblmedia
INNER JOIN tblMediaFilesSTIRelation ON tblmedia.MEDIAID=tblMediaFilesSTIRelation.MEDIAID
WHERE tblMediaFilesSTIRelation.STIID=$STIID$ and ((ifnull(filetype,) like '%jpg') or (ifnull(filetype,) like '%png')) and ifnull(tblMediaFilesSTIRelation.isdefault,0)=1 \"/>
<productInfoSql>
<offline query=\"SELECT 'Code' AS title, codcode AS value, 10 AS position, 'Item details' AS [Group] FROM sti WHERE stiid = $STIID$ UNION ALL SELECT 'Item' AS title, stiname AS value, 20 AS position, 'Item details' AS [Group] FROM sti WHERE stiid = $STIID$ UNION ALL SELECT 'Price' AS title, ifnull(STPGROSSPRICE, 0) AS value, 40 AS position, 'Item details' AS [Group] FROM sti INNER JOIN STP ON STI.STIID = STP.STIID AND stp.pstid = 1 WHERE STI.stiid = $STIID$ ORDER BY position \" />
<online query=\"\" /> </productInfoSql>
<ItemsMediaSQL query=\"SELECT TBLMEDIA.MediaID, as DocImageID, DateModified, URI, FileName as Description, filetype as filetype, islocalfile, filename from tblmedia
INNER JOIN tblMediaFilesSTIRelation ON tblmedia.MEDIAID=tblMediaFilesSTIRelation.MEDIAID WHERE tblMediaFilesSTIRelation.STIID = $STIID$ \" />
</ProductInfo>
Στο tag productInfoBanner βάζουμε το select για να επιλέξουμε την εικόνα που θα εμφανιστεί σαν header στην λίστα με τις πληροφορίες είδους.
Στο tag productInfoSql για offline βάζουμε όπως στο πρότυπο για να γεμίσει η λίστα. Βασίζεται στα πρότυπα του Customer Details.
Στο tag ItemsMediaSQL βάζουμε ότι βάζαμε στην παράμετρο ITEMSMEDIASQL του configuration για την εμφάνιση των Media αρχείων.
Suggest products (Cross-selling) 
Με το tag <ProductSuggestion> παραμετροποιούμε την οθόνη με τα προτεινόμενα είδη
π.χ. STI.specialmode=1
<ProductSuggestion title=\"OPATJS\" isCloned=\"ALWAYS\">
<sql selectSuggest=\"1 as defaultQty\" innerjoin=\"\" leftjoin=\"\" where=\"STI.specialmode=1\" groupby=\"\" orderby=\"\"/>
<fields>
<field datamember=\"defaultQty\" storemember=\"defaultQty\" databasetype=\"INT\" pocketbiztype=\"quantity\" editable=\"1\" defaultvaluesql=\"\"/>
</fields>
<grid>
<headers freezecolumns=\"1\" height=\"200\" textsize=\"12\"/>
<rows>
<row height=\"150\" textsize=\"14\"/>
</rows>
<columns>
<column order=\"1\" title=\"shortCode\" datamember=\"codcode\" sortable=\"1\" filterable=\"1\" width=\"120\" widgettype=\"HTML\">
<widget align = \"LEFT\"/>
</column>
<column order=\"2\" title=\"Item name\" datamember=\"stiname\" sortable=\"1\" filterable=\"1\" width=\"250\" widgettype=\"HTML\">
<widget align = \"LEFT\"/>
</column>
<column order=\"3\" title=\"Quantity\" datamember=\"defaultQty\" sortable=\"0\" filterable=\"0\" width=\"100\" widgettype=\"QTY\">
<widget align = \"CENTER\" beforecomma=\"4\" aftercomma=\"0\" showunderbar=\"1\"/>
</column>
</columns>
</grid>
<mapping>
<datamember productsuggestion=\"defaultQty\" model=\"stdqtyA\" />
</mapping>
</ProductSuggestion>
Λίστα παραστατικών (InvoicesListActivity)
Ανοίγει είτε από shortcut στο κεντρικό μενού του dashboard, είτε από τις ενέργειες του πελάτη ή μέσα από ΝΕΑ παραγγελία. Αναλυτικά:
Dashboard shortcut
Παραμετροποιείται από την παράμετρο DashboardInvoicesListConfigXML (configuration table)
Dashboard shortcut: DOCUMENTS_LIST_SALES (dashboardXML - configuration table)
Το default query επιστρέφει τα παραστατικά με σημερινή ημερομηνία.
case"DASHBOARD":
STRFTIME('%Y-%m-%d',tblInvMaster.docekdosidate)=STRFTIME('%Y-%m-%d',date('now'))
Ενέργειες πελάτη
Παραμετροποιείται από την παράμετρο CusActionsInvoicesListConfigXML (configuration table)
tblSLMTasks.Action: DOCUMENTVIEW
το default query επιστρέφει τα παραστατικά που ανήκουν στην ίδια επίσκεψη.
case"CUSACTIONS":
ifnull(tblInvMaster.visitid,0)=$VISITID$
Νέα παραγγελία
Παραμετροποιείται από την παράμετρο CopyInvoicesListConfigXML (configuration table)
το default query επιστρέφει τα παραστατικά που ανήκουν στον πελάτη.
case"SALES":
ifnull(tblInvMaster.cusid,0)=$CUSID$
Εμφανίζεται εικονίδιο στο μενού πάνω δεξιά. Η χρησιμότητά του είναι να ανοίξει η λίστα παραστατικών και να επιλέξει ο χρήστης αυτό του οποίου ποσότητες και προϊόντα θέλει να μεταφερθούν στη τρέχουσα (ΝΕΑ) παραγγελία. Πατώντας το Copy, γίνεται η αντιγραφή στην τρέχουσα παραγγελία. Χρειάζεται μια μετάβαση από το καλάθι στον κατάλογο ή αντίστροφα, για να φανούν οι αλλαγές.
Αν στο query του xml δεν οριστεί κάποιο part (select, from, where, order) τότε υπάρχει default query το οποίο φέρνει τα σημαντικά πεδία για τη λειτουργικότητα της οθόνης, ταξινομημένα κατά LineNumber.
Select tblInvMaster.invmasterid, tblInvMaster.IsDeleted, tblInvMaster.sdtid,tblInvMaster.isSynced,tblInvMaster.REPLID,tblInvMaster.Isprinted,tblInvMaster.Docidakirotiko,tblInvMaster.Docidakiromeno,tblInvMaster.AsDraft,tblInvMaster.Blockorder,tblInvMaster.Docnumber,tblInvMaster.cusid,SDT.printoutid,SDT.Debitprintoutid,SDT.Allowprint,SDT.Allowdelete,SDT.sdtupdqty,SDT.sdtupdvalue,tblAkirotika.CancelID, SDT_Cancel.printoutid as CancelPrintoutID From tblInvMasterinnerjoinSDTonSDT.sdtid=tblInvMaster.sdtidleftjoin tblAkirotikaontblAkirotika.NormalID=sdt.sdtid LEFT JOIN SDT as SDT_Cancel ON SDT_Cancel.sdtid=tblAkirotika.CancelID
Στα xml, στο select part του query μπορεί να μπει το reportid με το οποίο θα ανοίγει το View mode μέσα από τη λίστα παραστατικών (InvoicesListActivity). Η χρησιμότητα έγκειται στο γεγονός ότι ο χρήστης μπορεί να θέλει να δει το παραστατικό προτού το αντιγράψει. Το παραστατικό ανοίγει σε report με το report module.
Αν το report δεν βρεθεί, εμφανίζεται μήνυμα.
Reportcode
DayOrdersLines
SELECT leename,ifnull(cus.sap_customercode,) as cuscode ,ifnull(doccomment,) as doccomment, dockatahorisidate, stiname, codcode, tblinvdetail.stdqtya ,tblinvmaster.invmasterid FROM tblinvmaster INNER JOIN tblinvdetail ON tblinvmaster.invmasterid = tblinvdetail.invmasterid INNER JOIN cus ON cus.cusid = tblinvmaster.cusid INNER JOIN lee ON lee.leeid = cus.leeid INNER JOIN sti ON sti.stiid = tblinvdetail.stiid WHERE strftime('%d-%m-%Y', dockatahorisidate) = strftime('%d-%m-%Y', 'now') and tblinvmaster.invmasterid ='$ActionParameter1$' ORDER BY tblinvmaster.invmasterid ,tblinvmaster.cusid ,dockatahorisidate DESC
<AndroidLayout> <columns> <column position="1" caption="Πελάτης" datamember="leename" width="220" alignment="C"/><column position="2" caption="Κωδικός" datamember="cuscode" width="100" alignment="C"/> <column position="3" caption="Ημ/νία Κατ." datamember="dockatahorisidate" width="150" alignment="C"/><column position="4" caption="Είδος" datamember="stiname" width="200" alignment="C"/> <column position="5" caption="Κωδ.Είδ" datamember="codcode" width="80" alignment="C"/> <column position="6" caption="Κιβ" datamember="stdqtya" width="50" alignment="C"/> <column position="7" caption="Αρ.Παρ." datamember="invmasterid" width="80" alignment="C"/> <column position="8" caption="Σχόλια" datamember="doccomment" width="350" alignment="C"/></columns> </AndroidLayout>
?
Xml
<AndroidLayout>
<sql>
<query type="Offline" select="tblInvmaster.dockatahorisidate" from="" where="" groupby="" orderby=""/>
</sql>
<grid>
<headers freezecolumns = "1" height="100" textsize="22"/>
<rows>
<row height="" textsize="12"/>
</rows>
<columns>
<column order="1" title="ID" datamember="dockatahorisidate" sortable="1" sortmember="tblInvmaster.dockatahorisidate" filterable="0" width="200" widgettype="TEXT">
<widget align = "LEFT"/>
</column>
<column order="1" title="Ημερομηνία" datamember="invmasterid" sortable="1" sortmember="tblInvmaster.invmasterid" filterable="0" width="200" widgettype="TEXT">
<widget align = "LEFT"/>
</column>
<column order="2" title="CusID" datamember="cusid" sortable="1" filterable="1" width="100" widgettype="NUMERIC">
<widget align = "CENTER"/>
</column>
<column order="3" title="Allowdelete" datamember="Allowdelete" sortable="0" filterable="0" width="200" widgettype="CHECKBOX">
<widget align = "CENTER" beforecomma="3" aftercomma="1" showunderbar="0" maxvalue="5"/>
</column>
</columns>
</grid>
</AndroidLayout>
Παραμετροποίηση οικονομικών
Τιμοκατάλογος
Από την έκδοση 8.14 και μετά, υποστηρίζεται άλλο ένα επίπεδο στην ιεραρχία των τιμοκαταλόγων, ο τιμοκατάλογος παραστατικού.
Ορίζεται με τη μορφή sql στο SDT.Configuration με την παρακάτω μορφή
"fiscalconfig":"<sql>
<entity name=\"PST\">
<query type=\"Offline\" select=\"pstid\" from=\"PST\" where=\"pstid = 2\" groupby=\"\" orderby=\"\"/>
</entity>
</sql>"
Παρατηρείστε ότι έχει μορφή json, όπως ακριβώς ορίζεται και το salesconfigXML στον ίδιο πίνακα.
Ο κόμβος entity αποθηκεύει το όνομα της οντότητας για την οποία έχει γραφτεί το query. To query έχει γραφτεί με τη μορφή ξεχωριστών μερών ώστε να μπορεί να γραφεί οποιοδήποτε query πολύπλοκης δομής.
Οι τιμές (αξίες) του SDTPriceList έρχονται στο query του καταλόγου/καλαθιού, όπως ακριβώς και οι αξίες και εκπτώσεις των CustomerPriceList και DefaultPriceList.
Οι αξίες στο query έχουν την παρακάτω δομή
COALESCE( tblInvDetail.ssdunitprice,SDTPriceList.stpgrossprice, CustomerPriceList.stpgrossprice, DefaultPriceList.stpgrossprice"
"COALESCE(tblInvDetail.ssditemdiscpcnt, SDTPriceList.stpitemdiscpcnt, CustomerPriceList.stpitemdiscpcnt, DefaultPriceList.stpitemdiscpcnt, sti.stidiscount) AS ssditemdiscpcnt",
"COALESCE(tblInvDetail.ssdpricelistdiscpcnt, SDTPriceList.stppricelistdiscpcnt, CustomerPriceList.stppricelistdiscpcnt, DefaultPriceList.stppricelistdiscpcnt) AS ssdpricelistdiscpcnt",
Η εντολή COALESCE επιστρέφει την πρώτη ΌΧΙ NULL τιμή από αυτές που ακολουθούν.
Οι τιμοκατάλογοι έρχονται με LEFT OUTER JOIN ώστε σε περίπτωση που κάποιος δεν βρεθεί, η αντίστοιχη αξία/έκπτωση είναι NULL και αγνοείται από την παραπάνω εντολή.
Ο κώδικας είναι γραμμένος έτσι ώστε στην περίπτωση που ο τιμοκατάλογος του SDT δεν βρεθεί (είτε λόγω απουσίας του xml ή λόγω λάθους στα δεδομένα), ο SDTPiceList συμμετέχει σε LEFT OUTER JOIN το οποίο αποτυγχάνει επίτηδες, και επομένως η αξίες του είναι NULL και δεν επηρεάζουν το query (ουσιαστικά το σύστημα λειτουργεί όπως και τη στιγμή που έγινε η αλλαγή, δηλαδή όπως στις εκδόσεις μέχρι και την 8.12).
Η ιεραρχία τψν τιμοκαταλόγων πλέον είναι
tblInvDetail SDT Customer Default
Τιμή
Επίσης από την έκδοση 8.16 και μετά υποστηρίζεται η custom τιμή στο παραστατικό. Ιδιαιτερότητα της τιμής αυτής είναι ότι δεν προκύπτει από κάποιον τιμοκατάλογο, με τη στενή έννοια του όρου, αλλά από οποιοδήποτε query. Η παραμετροποίηση γίνεται από το xml του SDT, στο node fiscalConfig. Με την προσθήκη του παρακάτω node, παραμετροποιείται η custom τιμή για το προϊόν.
<entity name=\"CustomPrice\">
<query type=\"Offline\" select=\"stiid, stpgrossprice\" from=\"STPCustom\" where=\"\" groupby=\"\" orderby=\"\"/>
</entity>
Τα πεδία που θα επιστρέφονται από το query πρέπει να είναι τα ίδια με τα παραπάνω, δηλαδή stiid και stpgrosprice. Αν έχουν διαφορετικά ονόματα, η παραμετροποίηση καθίσταται άκυρη και ενδέχεται να προκαλεί και crashαρίσματα της εφαρμογής. Επίσης και το entity name θα πρέπει να είναι το ίδιο με αυτό που φαίνεται (CustomPrice).
Κατά τα άλλα, η δομή του query υποστηρίζει τις βασικές λειτουργικότητες που υφίστανται στα query (select, from, where, groupby και orderby).
Το query αυτό θα χρησιμοποιείται με left outer join στο υπόλοιπο query του καταλόγου/καλαθιού, ώστε σε περίπτωση που δεν υπάρχει εγγραφή, να αγνοείται η null τιμή του (λόγω left outer join) από το COALESCE (δες παραπάνω, στον τιμοκατάλογο).
queryBuilder.append(" LEFT OUTER JOIN stp AS DefaultPriceList ON DefaultPriceList.stiid = sti.stiid and ifnull(DefaultPriceList.pstid , 0) = ");
queryBuilder.append(SiebenOrderApplication.getInstance().getAppBundleHolder().getConfiguration().getPstId()); //default price list
queryBuilder.append(" LEFT OUTER JOIN stp AS CustomerPriceList ON CustomerPriceList.stiid = sti.stiid AND ifnull(CustomerPriceList.pstid,0) = ");
queryBuilder.append(mCustomerEntity.getPstid()); //customer price list
//IMP-18934 PST from SDT.Configuration xml
queryBuilder.append(" LEFT OUTER JOIN stp AS SDTPriceList ON SDTPriceList.stiid = sti.stiid AND ");
if (mSdtEntity == null || TextUtils.isEmpty(mSdtEntity.getPstid())) {
queryBuilder.append("0 = 1"); //if no sdt.pstid is set, force join to failure -> SDTPriceList will be null
} else {
queryBuilder.append("ifnull(SDTPriceList.pstid,0) = ");
queryBuilder.append(mSdtEntity.getPstid()); //customer price list
}
if (TextUtils.isEmpty(mCustomPriceQuery)) {
queryBuilder.append(" LEFT OUTER JOIN STP AS CUSTOMPRICETABLE ON CUSTOMPRICETABLE.STIID = STI.STIID AND 0=1"); //if no custompricequery is present, force left outer join to fail so that COALESCE to "jump" custom price
} else {
queryBuilder.append(String.format(" LEFT OUTER JOIN (%1s) AS CUSTOMPRICETABLE ON CUSTOMPRICETABLE.STIID = STI.STIID", mCustomPriceQuery));
}
queryBuilder.append(" INNER JOIN VAT ON STI.vatid = VAT.vatid ");
Sets
Sets
Από την έκδοση 8.14.0.0 και μετά υποστηρίζονται τα sets.
Τα sets χρησιμοποιούνται από τις παρακάτω 2 οθόνες:
Για την διαχείριση των sets:
Με τα κουμπιά - & + σε κάθε γραμμή καθορίζουμε πόσα από κάθε set θα πέσουν στο καλάθι. Όταν γίνεται κάποια αλλαγή από την τιμή που έχει όταν άνοιξε η οθόνη η γραμμή χρωματίζεται για να ξέρει ο χρήστης τι θα αλλάξει όταν επιλέξει να εφαρμόσει τις αλλαγές του στο καλάθι.
Με το κουμπί i ανοίγει η δεύτερη οθόνη που δείχνει τα περιεχόμενα του set.
Αρχικές τιμές:
0 αν ανοίγει πρώτη φορά και δεν υπάρχει set στο καλάθι, διαφορετικά έχει τον αριθμό των sets που είναι ήδη στο καλάθι. Αν η δεν είναι ενεργοποιημένη η παράμετρος SETS_AS_ONE τότε όταν ανοίγει η οθόνη όλα έχουν τιμή 0.
Για την εμφάνιση των περιεχομένων του set:
Αυτή ο οθόνη δεν έχει κάποια λειτουργικότητα πέρα από το να εμφανίζει δεδομένα. Τα δεδομένα που θα εμφανίζονται ορίζονται αποκλειστικά από τον consultant.
Πίνακες στη βάση:
Τα sets του SalesXvan-newEra χρησιμοποιούν τους πίνακες tblSets και tblSetsDetail.
Παραμετροποίηση:
Την παραμετροποίηση την προσθέτουμε με xml που έχει την παρακάτω μορφή:
<sets>
<setselectionquery/>
<setdetailsquery/>
<fields/>
<grid/>
<mapping/>
</sets>
setselectionquery:
Εδώ μέσα ορίζουμε το query που θα φέρνει τα data που θα βλέπει ο χρήστης στην οθόνη διαχείρισης των sets.
Παράδειγμα:
<setselectionquery
type=\"offline\"
select=\"group_concat(product.stiname) as details\"
fromSets=\"inner join tblSetsDetail as details on details.setid = tblSets.setid inner join STI as product on product.stiid = details.stiid\"
where=\"\"
groupby=\"tblSets.setid\"
orderby=\"\"/>
type: Υποστηρίζεται μόνο το offline.
select: Στήλες που θέλουμε να χρησιμοποιήσουμε. Στο query πάντα θα προστίθενται από τον κώδικα οι στήλες tblSets.setid & tblSets.descr και μπορεί να προστεθεί από τον consultant κάτι "as details". Η στήλη tblSets.descr χρησιμοποιείται ως τίτλος για κάθε set που θα εμφανίζεται και η details θα βρίσκεται κάτω από τον τίτλο στην ίδια γραμμή και εξυπηρετεί την ανάγκη για εύκολη περιγραφή των περιεχομένων του set χωρίς να χρειάζεται ο χρήστης να μεταβεί στην αντίστοιχη οθόνη.
fromSets: Το query είναι πάντα "from tblSets" και εδώ πέρα μπορούν να συμπληρωθούν τα απαραίτητα join που πρέπει να γίνουν για να έρθει η σωστή πληροφορία "as details".
where: Κάποια τιμή που θα προστεθεί σαν where στο query.
groupby: Κάποια τιμή που θα προστεθεί σαν groupby στο query.
orderby: Κάποια τιμή που θα προστεθεί σαν orderby στο query.
setdetailsquery:
Εδώ μέσα ορίζουμε τιμές οι οποίες θα συμπληρωθούν στο query του model με όπως γίνεται στην αντίστοιχη παραμετροποίηση του "product suggestion".
Το query που προκύπτει μετά την ένωση του setdetailsquery και του query του model είναι αυτό που φέρνει τα data που θα πέφτουν στο καλάθι μετά από την προσθήκη κάποιου set αλλά και τα data που θα βλέπει ο χρήστης στην οθόνη με τα αναλυτικά στοιχεία του set.
Παράδειγμα:
<setdetailsquery
selectSet=\" tblSetsDetail.qty as setDetailQty, tblSetsDetail.Disc1 as SetDisc1, tblSetsDetail.Disc2 as SetDisc2, tblSetsDetail.isgift as SetIsGift, 0 as Setssditemdiscpcnt, 0 as Setssdpricelistdiscpcnt \"
innerjoin=\"\"
leftjoin=\" tblSetsDetail on STI.stiid = tblSetsDetail.stiid \"
where=\"\"
groupby=\"\"
orderby=\"\"/>
selectSet: Ότι μπει εδώ μέσα θα προστεθεί στο τέλος του select που έχει οριστεί στο query του model.
innerjoin: Ότι μπει εδώ μέσα θα μπει σαν inner join στο query του model.
leftjoin: Ότι μπει εδώ μέσα θα μπει σαν left join στο query του model.
where: Ότι μπει εδώ μέσα θα προστεθεί στο τέλος του where που έχει οριστεί στο query του model.
groupby: Ότι μπει εδώ μέσα θα προστεθεί στο τέλος του group by που έχει οριστεί στο query του model.
orderby: Ότι μπει εδώ μέσα θα προστεθεί στο τέλος του order by που έχει οριστεί στο query του model.
fields:
Εδώ μέσα γίνεται η αντιστοίχιση των στηλών του query που προκύπτει από την ένωση του setdetailsquery και του query του model με τις στήλες του grid που θα εμφανίζεται στην οθόνη με τα αναλυτικά στοιχεία του set. Έχει ακριβώς την ίδια δομή με τα fields που υπάρχουν στα <header/> και <model/>.
Παράδειγμα:
<fields>
<field datamember=\"setDetailQty\" databasetype=\"INT\" pocketbiztype=\"quantity\" editable=\"1\"/>
<field datamember=\"SetDisc1\" databasetype=\"FLOAT\" pocketbiztype=\"discount\" editable=\"1\"/>
<field datamember=\"SetDisc2\" databasetype=\"FLOAT\" pocketbiztype=\"discount\" editable=\"1\"/>
<field datamember=\"Setssditemdiscpcnt\" databasetype=\"FLOAT\" pocketbiztype=\"discount\" editable=\"1\"/>
<field datamember=\"Setssdpricelistdiscpcnt\" databasetype=\"FLOAT\" pocketbiztype=\"discount\" editable=\"1\"/>
</fields>
grid:
Η παραμετροποίηση του grid που θα εμφανίζεται στην οθόνη με τα αναλυτικά στοιχεία του set.
Έχει πανομοιότυπη παραμετροποίηση με όλα τα υπόλοιπα grid του sales.
Παράδειγμα:
<grid>
<headers freezecolumns=\"1\" height=\"70\" textsize=\"12\"/>
<rows>
<row height=\"70\" textsize=\"12\"/>
</rows>
<columns>
<column order=\"1\" title=\"Item\" datamember=\"stiname\" sortable=\"1\" filterable=\"1\" width=\"130\" widgettype=\"TEXT\">
<widget align = \"LEFT\"/>
</column>
<column order=\"2\" title=\"Code\" datamember=\"codcode\" sortable=\"1\" filterable=\"1\" width=\"80\" widgettype=\"TEXT\">
<widget align = \"LEFT\"/>
</column>
<column order=\"3\" title=\"Qty A\" datamember=\"setDetailQty\" sortable=\"0\" filterable=\"0\" width=\"100\" widgettype=\"QTY\">
<widget align = \"CENTER\" beforecomma=\"3\" aftercomma=\"1\" showunderbar=\"1\" maxvalue=\"999\"/>
</column>
<column order=\"4\" title=\"Set Disc1\" datamember=\"SetDisc1\" sortable=\"0\" filterable=\"0\" width=\"100\" widgettype=\"QTY\">
<widget align = \"CENTER\" beforecomma=\"3\" aftercomma=\"3\" showunderbar=\"1\" maxvalue=\"999\"/>
</column>
<column order=\"5\" title=\"Set Disc2\" datamember=\"SetDisc2\" sortable=\"0\" filterable=\"0\" width=\"100\" widgettype=\"QTY\">
<widget align = \"CENTER\" beforecomma=\"3\" aftercomma=\"2\" showunderbar=\"1\" maxvalue=\"999\"/>
</column>
</columns>
</grid>
mapping:
Εδώ ορίζουμε το mapping των τιμών που έρχονται από το query που προκύπτει από την ένωση του setdetailsquery και του query του model και την στήλη του tblInvDetail στην οποία θέλουμε να πέσει, όταν προσθέτουμε κάποιο set στο καλάθι.
Παράδειγμα:
<mapping>
<datamember editsetfield=\"setDetailQty\" model=\"stdqtyA\"/>
<datamember editsetfield=\"SetDisc1\" model=\"disc1pcnt\"/>
<datamember editsetfield=\"SetDisc2\" model=\"disc2pcnt\"/>
<datamember editsetfield=\"Setssditemdiscpcnt\" model=\"ssditemdiscpcnt\"/>
<datamember editsetfield=\"Setssdpricelistdiscpcnt\" model=\"ssdpricelistdiscpcnt\"/>
</mapping>
Για κάθε mapping που θέλουμε να γίνει προσθέτουμε ένα <datamember/>.
Όπου το datamember περιέχει τα εξής attributes:
editsetfield: Στήλη από το query
model: Πεδίο στο οποίο θέλουμε να πέσει.
Παράμετροι στον πίνακα configuration:
Εκτός από το xml που προσθέτουμε στο sales config υπάρχουν και οι παράμετροι του πίνακα configuration SETS_AS_ONE & SET_LINES_QUANTITY_PARTICIPATES_IN_DISCOUNT, οι περιγραφές των οποίων βρίσκονται στο configuration.xls.
Παρατηρήσεις
- Στο SalesOrderPlus, όταν μιλάμε για XVan, το παραστατικό παίρνει αρίθμηση μόνο όταν πατήσουμε την επιλογή "εκτύπωση"
- Παρατήρηση για troubleshooting (ΝΜ)
Κατά την αναβάθμιση πελάτη σε νέες εκδόσεις παρατηρήθηκε ότι κατά την έναρξη παραγγελίας η εφαρμογή έβγαζε μήνυμα ότι δεν υπάρχουν data για να εμφανίσει.
Συμπληρωματικά στο database queries υπήρχε η εγγραφή
select * from sdt where sdtid=-1
Η λύση του προβλήματος ήταν να ενημερώσουμε τον πίνακα Configuration, στο query που υπάρχει για την ενέργεια "sqlOffGetCustomerTasks". Η ενημέρωση του query είναι η προσθήκη του πεδίου sdtid στο select που αφορά την παραγγελία (να μην παραληφθεί να προστεθούν τα αντίστοιχα nulls στα υπόλοιπα select Που συνδέονται με Union)
PocketBiz Scanning
Περιγραφή
Η διαδικασία scanning αποτελεί έναν ακόμα τρόπο εισαγωγής γραμμών σε μια παραγγελία. Χαρακτηριστικό που την διαφοροποιεί από τις υπόλοιπες είναι ότι ο χρήστης σκανάρει ένα barcode, το οποίο αντιπροσωπεύει το προϊόν που θέλει να εισαχθεί στην παραγγελία με κάποιες (default) τιμές.
Ο χρήστης σκανάρει το barcode και η εφαρμογή είτε προσθέτει μια νέα γραμμή στο καλάθι ή την ενημερώνει, αν υπάρχει ήδη στο καλάθι. Για κάθε scan που εκτελείται, εκτελούνται μια σειρά από ενέργειες στις τιμές της γραμμής της παραγγελίας, οι οποίες ορίζονται στο xml. Ενδεικτικά μια ενέργεια που μπορεί να οριστεί στο xml είναι η πρόσθεση της ποσότητας που «έρχεται» από το query, το οποίο ορίζεται κι αυτό στο xml. Μια άλλη ενέργεια μπορεί να είναι η παράθεση των σειριακών αριθμών των προϊόντων σε κάποιο text πεδίο της παραγγελίας.
Με βάση τα παραπάνω, αν η τιμή που έρχεται για κάθε σκανάρισμα είναι «5» και οι σειριακοί αριθμοί των 5 πρώτων προϊόντων είναι «0001», «0002», «0003», «0004» και «0005», τότε εκτελώντας 5 σκαναρίσματα, η εικόνα της παραγγελίας θα είναι η παρακάτω:
- 1ο σκανάρισμα: Εισαγωγή γραμμής στην παραγγελία με ποσότητα «5» και serial numbers «0001».
- 2ο σκανάρισμα: Ενημέρωση της γραμμής. Ποσότητα «10», serial numbers “0001, 0002»
- 3ο σκανάρισμα: Ενημέρωση της γραμμής. Ποσότητα «15», serial numbers “0001, 0002, 0003»
- 4ο σκανάρισμα: Ενημέρωση της γραμμής. Ποσότητα «20», serial numbers “0001, 0002, 0003, 0004»
- 5ο σκανάρισμα: Ενημέρωση της γραμμής. Ποσότητα «25», serial numbers “0001, 0002, 0003, 0004, 0005»
Να σημειωθεί ότι μετά το πέρας κάθε σκαναρίσματος, η εφαρμογή μετακινεί το grid του καταλόγου ή του καλαθιού ώστε να είναι εμφανής η τελευταία τιμή που άλλαξε (στο παραπάνω παράδειγμα θα εμφανίζει τη στήλη serial numbers). Σε μεταγενέστερη έκδοση, το πεδίο στο οποίο θα γίνεται focus θα δίνεται στο xml.
Με το πέρας του σκαναρίσματος, η αποθήκευση ή η περαιτέρω επεξεργασία της παραγγελίας γίνεται με το γνωστό τρόπο.
Παραμετροποίηση
Η παραμετροποίηση της διαδικασίας γίνεται από το SalesConfigXML, με την προσθήκη ενός κόμβου με root element «Scan» όπως φαίνεται παρακάτω
|
<scan> <sql> <query type=\"Offline\" select=\"STI.stiid as STIID, STI.codcode as sticode, IFNULL(STI.defaultqtya,5) as defaultqty\" from=\"STI\" where=\"STI.codcode = $barcode$\" groupby=\"\" orderby=\"\"/> </sql> <mappingscan> <datamemberscan scan=\"defaultqty\" model=\"stdqtyA\" action=\"ADD\" /> <datamemberscan scan=\"sticode\" model=\"udfchar1\" action=\"APPEND\" /> </mappingscan> </scan> |
Όπως παρατηρείται, υπάρχει το query στο οποίο έρχονται τα data που θα χρησιμοποιηθούν από το επόμενο node «mappingscan». Σε αυτό το node ορίζεται ποια ενέργεια «action» θα εκτελεστεί στο datamember της γραμμής «model» με την τιμή που προκύπτει από το παραπάνω query «scan».
Συγκεκριμένα, στο παραπάνω xml ορίζουμε ότι η τιμή defaultqty θα προστίθεται (action=add) στην ποσότητα stdqtyA της γραμμής σε κάθε σκανάρισμα, ενώ αντίστοιχα, το sticode από το query θα παρατίθεται (action=append) στο πεδίο udfchar1, δίνοντας τελικά ένα string της μορφής «serialNo1, serialNo2, …, serialNoN»
Παρατηρήσεις
Να σημειωθεί ότι επειδή δεν έχει υλοποιηθεί μηχανισμός προστασίας του query (default query) σε περίπτωση που αυτό δεν έχει οριστεί στο xml, παρακαλείστε να γράφετε ΠΑΝΤΑ ένα query το οποίο περιέχει οπωσδήποτε το πεδίο «stiid» του STI με alias (επίσης) «stiid».
Ο μηχανισμός θα προστεθεί στο μέλλον.
Αναφέρθηκε παραπάνω ότι μετά από κάθε σκανάρισμα, η εφαρμογή κινεί το grid ώστε να είναι εμφανής η τελευταία τιμή που αλλάχθηκε. Υπάρχει περίπτωση το προϊόν που αντιστοιχεί στο σκαναρισμένο barcode να μην υπάρχει στον πίνακα STI. Σε αυτή την περίπτωση εμφανίζεται μήνυμα.
Επίσης ενδέχεται το προϊόν να μην υπάρχει στον κατάλογο. Είτε επειδή δεν έρχεται από το query του SalesConfigXML, ή επειδή έχουν εφαρμοστεί φίλτρα στο grid. Σε αυτή την περίπτωση εμφανίζεται μήνυμα που προτρέπει το χρήστη να καθαρίσει τα φίλτρα και να ξαναπροσπαθήσει.
Προς το παρόν υποστηρίζονται μόνο οι ενέργειες «ADD» και «APPEND». Μπορείτε ελεύθερα να προτείνετε ενέργειες οι οποίες θα σας φανούν χρήσιμες.



