Q1 2005 Results and Forecast
Shared by: yurtgc548
-
Stats
- views:
- 14
- posted:
- 3/11/2012
- language:
- English
- pages:
- 34
Document Sample


Making QAD Dance to your Tunes!
A Case study demonstrating how Culligan added functionality to QAD,
using TailorPro’s rapid enhancements and non-invasive customizations
Meera Ravindran – Culligan International
Bruce LeBel – Prostar Systems
MMUG
Sept 2009
Culligan Confidential
Introduction
Culligan has extensively utilized the TailorPro “source-free”
development engine to create significant modifications to QAD’s
Mfg/Pro screens, data structures and business logic
TailorPro has enabled us to limit the number of changes made to
Mfg/Pro.
TailorPro solutions range from support for unique business process
requirements such as Lead information captured at time of Sales
Order/Contract entry (drives sales commission), to support for audit
and security.
2
Culligan Confidential
Agenda
Who we are ?
Where we were then – a look at the QAD System, pre-TailorPro
Why did we need a change?
Examples of TailorPro usage, enabling sizeable return on investment.
Where we are now
Overview of the full set of capabilities of TailorPro
A look ahead at how Culligan intends to apply TailorPro in the future
3
Culligan Confidential
Who We Are
Founded by Emmett J. Culligan in 1936,
headquarter in Rosemont, IL
Over 1400 dealerships worldwide,
615 dealerships in US alone, of which 70 are
Company Owned Dealerships, the remainder
Franchise
5000+ employees in more than 100 countries
Market share leader and a renowned
household name for conditioned water.
Full service provider of water treatment
solutions, for homes and industries
4
Culligan Confidential
Who We Are –
Culligan Business Model
Business model similar to McDonalds – Company Owned Dealers (COD)
and Franchises
CODs and Franchises sell or rent direct to households, service and
deliver product
CODs and Franchises purchase product from Culligan Corporate
5
Culligan Confidential
Who we are - Customer Segments
Culligan delivers it’s convenience of bottled water, and the energy savings and
health benefits of water softeners to customers in a variety of applications.
6
Culligan Confidential
Who We Are –
Product Line
Household/Residential
(Water Softeners, Water Filters
& Reverse-Osmosis systems)
Commercial & Industrial
(Water Softeners, Water Filters
& Reverse-Osmosis systems)
Point-of-Use (POU)
Bottleless Water coolers
Retail Products
(Shower heads & filters, Pitchers & filters,
Faucet filters, RV filters, Icemaker & Water
Dispenser filters)
Service
(Complimentary in home analysis,
In-Store Bottle Water Dispensers Certified Sales, Installation and Service Technicians,
Full Service - Salt Delivery,
7 Full Service - Filter Exchange) Culligan Confidential
Who We Are –
Focus On Improving Efficiency
Culligan was acquired by Clayton, Dubilier & Rice, Inc (CD&R) a
private equity firm in 2004
Since that time Culligan’s strategy has been focused around improving
efficiency through re-engineering efforts
Outsourced most manufacturing
Implementing shared services
Centralizing Finance
Implementing single system to support North America
8
Culligan Confidential
Culligan Production Databases
eB2.1 Database for Culligan
North America Operations
Corporate/
Culiigan Owned
Wholesale Canada
Dealership Division
Canada (CODD)
US
9
Culligan Confidential
Ongoing customizations
In Dec 2006, already had about 400 pieces of customized codes, for business
specific requirements example: delivery route module, customized reporting,
browses etc.
There were several new application changes to be made, including –
Screen Modifications
New Screens, Browsers, Applications
New Business Rules
Logic-driven Defaults
Data Validation
User Control
Had to find a better way to make QAD enhancements in a time-efficient manner.
All changes had to be made in a manner that is upgrade-friendly.
10
Culligan Confidential
Our Approach
Invited ProStar Software to provide us with a demonstration of their TailorPro tool.
Analyzed the TailorPro tool and were impressed by the potential
Acquired TailorPro, underwent a couple days of training
Began working with the TailorPro product, got our feet wet
Brought TailorPro back in for a couple more weeks of training, and implementation
assistance
Adopted a standard rule for QAD development -
ALWAYS attempt to change with TailorPro first
TailorPro changes made in ‘character’ interface, are reflected in ‘.Net UI’ in most
cases.
11
Culligan Confidential
Example# 1 –
Item Master Maintenance
We can specify the
exact field position in
Character mode
In .Net UI, new fields
are added to end of all
fields in the frame.
12
Culligan Confidential
Example# 1
Set up anchors for Item Master new fields
13
Culligan Confidential
Example# 1
Code Sample – Item Master new fields
tpptchr09a.p tpptchr09b.p
{ crtfill.i {enable.i
&FieldName = '"pt_user1"' &FieldNames = '"pt_user1"'
&FieldRow =2 }
&FieldCol = 34
&Visible = yes {enable.i
&FrameName = '"a"' &FieldNames = '"pt__chr09"'
&DataType = '"Character"' }
&TableName = "pt_mstr"
&FieldLabel = '"RentFA"' {taborder.i
&FieldFormat = '"x(1)"' &FieldNames =
&FieldWidth =1 '"pt_um,pt_user1,pt__chr09,pt_desc1,pr_desc2"'
&FieldSensitive = no }
&PrevField = '"pt_mstr.pt_um"'
&Display = yes
}
{crtfill.i
&FieldName = '"pt__chr09"'
&FieldRow =2
&FieldCol = 49
&Visible = yes
&FrameName = '"a"'
&DataType = '"Character"'
&TableName = "pt_mstr"
&FieldLabel = '"Division"'
&FieldFormat = '"x(4)"'
&FieldWidth =4
&FieldSensitive = no
&PrevField = '"pt_mstr.pt_user1"'
&Display = yes
}
{setvalue.i
&ValueID = '"ppptmta"'
&ValueName = '"ptpart-go"'
&cValue = "Yes"
} 14
Culligan Confidential
Example# 1
Code Sample – Item Master new fields …continued
tpchr09go.p ptuser1 = if avail pt_mstr then pt_user1 else "N". {getscrn.i
{mfdeclre.i}
ptchr09 = if avail pt_mstr then pt__chr09 else "". &FieldName = '"pt__chr09"'
def var ptpart-go as char no-undo. &FrameName = '"a"'
def var ptpart as char no-undo. {scrnvalu.i &Variable = ptchr09
def var ptchr09 as char no-undo. &FieldName = '"pt_user1"' }
def var ptuser1 as char no-undo. &FrameName = '"a"' find first pt_mstr exclusive
&FieldValue = ptuser1 where pt_domain = global_domain
{getvalue.i } and pt_part = ptpart.
&ValueID = '"ppptmta"'
&ValueName = '"ptpart-go"' if (keyfunction(lastkey) = "Go" or
{scrnvalu.i keyfunction(lastkey) = "Return")
&Variable = ptpart-go &FieldName = '"pt__chr09"' and lookup(ptuser1,"Y,N") = 0
} &FrameName = '"a"' and (pt_mstr.pt_user1 <> ptuser1) then
do:
&FieldValue = ptchr09 message "Invalid RentFA. Must be Y or N.".
/* There are 2 GOs in frame A:
* 1: ptpart-go = yes } pause.
* If Go for pt_part {entry.i &FieldName = '"pt_user1"'}
* Then Display the Item Division (pt__chr09) end. /* if ptpart-go... then do */ end.
* 2: ptpart-go = no else
* If Go for pt_um, pt__chr09 (new), pt_desc1, pt_desc2 /* Update Item Division (pt__chr09) from the if (keyfunction(lastkey) = "Go" or
* Then Update pt__chr09 from the screen value screen value */ keyfunction(lastkey) = "Return")
* and lookup(ptchr09,",CORP,CODD") = 0
* ptpart-go is set to yes in tpptchr09a.p (Entry of pt_part) else do: and (pt_mstr.pt__chr09 <> ptchr09)
* ptpart-go is set to no while handling the go for pt_part then do:
* ptpart-go is set to yes while handling the go for pt__chr09 {setvalue.i message "Invalid Division. Must be CODD, CORP or
*/ &ValueID = '"ppptmta"' blank.".
pause.
/* Display Item Division (pt__chr09) */ &ValueName = '"ptpart-go"'
{entry.i &FieldName = '"pt__chr09"'}
&cValue = "No" end.
if ptpart-go = "Yes" then do: } else
if (keyfunction(lastkey) = "Go" or
{setvalue.i {getscrn.i keyfunction(lastkey) = "Return")
&ValueID = '"ppptmta"' &FieldName = '"pt_part"' then do:
&ValueName = '"ptpart-go"' pt_mstr.pt__chr09 = ptchr09.
&FrameName = '"a"' pt_mstr.pt_user1 = ptuser1.
&cValue = "No" &Variable = ptpart end.
} }
end. /* if ptpart-go... ELSE do */
ptpart = frame-value.
{getscrn.i {disable.i &FieldNames = '"pt_user1"' }
find first pt_mstr no-lock &FieldName = '"pt_user1"'
where pt_domain = global_domain &FrameName = '"a"' {disable.i &FieldNames = '"pt__chr09"' }
and pt_part = ptpart no-error. &Variable = ptuser1
} Culligan Confidential
15
Example# 1
Anchor & Code Sample to enable scrolling for Item Master new fields
tpptchr09dsp.p
def input param pt-rowid as rowid no-undo.
def var level as int init 1 no-undo.
if pt-rowid <> ? then
repeat while program-name(level) <> ?:
if program-name(level) matches "*ppptmta.*"
and program-name(level - 1) matches "*tppt_mstr.*"
then do:
find pt_mstr no-lock
where rowid(pt_mstr) = pt-rowid.
{scrnvalu.i
&FieldName = '"pt_user1"'
&FieldValue = pt_mstr.pt_user1
&FrameName = '"a"'}
{scrnvalu.i
&FieldName = '"pt__chr09"'
&FieldValue = pt_mstr.pt__chr09
&FrameName = '"a"'}
tppt_mstr.p leave.
&global-define TableName pt_mstr
end.
{getbroker.i}
{progvars.i}
{tablevar.i} level = level + 1.
&global-define AfterFind ~ end. /* repeat while */
run tpptchr09dsp.p (rowid(pt_mstr)). ~
{findrec.i}
&Undefine AfterFind
Procedure Create_Record:
end procedure.
{getrowid.i} Culligan Confidential
16
Example# 2
Sales Order Maintenance
New frame to accept
custom “lead data”
Fields that drives sales
commission calculations
17
Culligan Confidential
Example# 2
Set up anchor for SO Maintenance
18
Culligan Confidential
Example# 2
Code sample – Sales Order Maintenance
tpsotrl.p space(25) vyesno label "Do you want to continue?" {getscrn.i &fieldname = '"so_bill"'
skip
&framename = '"a"'
with side-labels title " Lead Source Validation"
{mfdeclre.i}. size-chars 80 by 9 row 5 overlay. &variable = temp-bill-to}.
DEF VAR temp-cancel-reason AS CHAR FORMAT "X(8)" define frame frm-3
INITIAL "" LABEL "Cancel Reason" NO-UNDO. skip(2) FIND so_mstr
space(25) temp-call-ctr-ref label "Call Center WHERE so_mstr.so_domain = global_domain
DEF VAR temp-cancel-date AS DATE FORMAT
Reference" AND so_mstr.so_nbr = temp-so-nbr
"99/99/99“ INITIAL ? LABEL "Cancel Date" NO-UNDO. NO-LOCK NO-ERROR.
skip
DEF VAR temp-pap AS LOG FORMAT "Yes/No" space(25) vyesno label "Do you want to continue?"
INITIAL "No" LABEL "APP" NO-UNDO. skip IF AVAILABLE so_mstr = FALSE THEN RETURN.
DEF VAR temp-bill-to AS CHAR NO-UNDO. with side-labels title " Call Center Reference Validation" ASSIGN temp-site = so_mstr.so_site.
size-chars 80 by 9 row 5 overlay. FIND si_mstr
DEF VAR temp-lead-src AS INT FORMAT ">>9"
WHERE si_mstr.si_domain = global_domain
INITIAL 0 LABEL "Lead Source" NO-UNDO. AND si_mstr.si_site = temp-site
define frame frm-4
DEF VAR temp-promo-code AS INT FORMAT ">>9" skip(2) NO-LOCK NO-ERROR.
INITIAL 0 LABEL "Promo Code" NO-UNDO. space(25) temp-lead-src label "Lead Source Value"
DEF VAR temp-lead-credit AS CHAR FORMAT "X(8)" skip IF AVAILABLE si_mstr = TRUE
space(25) temp-call-ctr-ref label "Call Center AND si_mstr.si_site >= "300"
INITIAL "" LABEL "Lead Credit" NO-UNDO.
Reference" AND si_mstr.si_site <= "900" THEN
DEF VAR temp-call-ctr-ref AS CHAR FORMAT "X(8)" DO:
skip
INITIAL "" LABEL "Call Center Ref" NO-UNDO. space(25) vyesno label "Do you want to continue?" ASSIGN temp-lead-src = 0
DEF VAR temp-so-nbr AS CHAR NO-UNDO. skip temp-promo-code = 0
DEF VAR temp-site AS CHAR NO-UNDO. with side-labels title " Lead Source & Call Center Ref temp-lead-credit = ""
Validation" temp-call-ctr-ref = ""
DEF VAR temp-run AS LOG NO-UNDO.
size-chars 80 by 9 row 5 overlay. temp-pap = NO
DEF VAR temp-level AS INT NO-UNDO. temp-cancel-reason = ""
PAUSE 0 BEFORE-HIDE.
DEF VAR vyesno as log format "Yes/No" ASSIGN temp-run = YES temp-cancel-date = ?.
init "No" no-undo. temp-level = 1. FIND xxpi_mstr
DEF VAR lblank as char init "<Blank>" no-undo. REPEAT WHILE program-name(temp-level) <> ?: WHERE xxpi_mstr.xxpi_domain = global_domain
IF program-name(temp-level) = "us/fs/fsrmamt.r" THEN AND xxpi_mstr.xxpi_nbr = temp-so-nbr
DO: EXCLUSIVE-LOCK NO-ERROR.
DEFINE FRAME frm-1
ASSIGN temp-run = NO.
temp-lead-src AT ROW 1 COLUMN 5 LEAVE. IF AVAILABLE xxpi_mstr = FALSE THEN
temp-promo-code AT ROW 2 COLUMN 6 END. /* IF program-name(temp-level) = "us/fs/fsrmamt.r" DO:
temp-lead-credit AT ROW 3 COLUMN 5 THEN */ CREATE xxpi_mstr.
ASSIGN temp-level = temp-level + 1. ASSIGN xxpi_mstr.xxpi_domain = global_domain
temp-call-ctr-ref AT ROW 4 COLUMN 1
END. /* REPEAT WHILE program-name(temp-level) <> xxpi_mstr.xxpi_nbr = temp-so-nbr
temp-pap AT ROW 5 COLUMN 13 xxpi_mstr.xxpi_lead_src = 0
?: */
temp-cancel-reason AT ROW 6 COLUMN 3 IF temp-run = YES THEN xxpi_mstr.xxpi_promo_code = 0
temp-cancel-date AT ROW 7 COLUMN 5 DO: xxpi_mstr.xxpi_lead_credit = ""
WITH SIDE-LABELS SIZE-CHARS 80 BY 9 xxpi_mstr.xxpi_call_ctr_ref = ""
{getscrn.i &fieldname='"so_nbr"'
xxpi_mstr.xxpi_pap = NO
ROW 5 OVERLAY. &framename='"a"' xxpi_mstr.xxpi_can_reason = ""
define frame frm-2 &variable=temp-so-nbr}. xxpi_mstr.xxpi_can_date = ?.
skip(2) END. /* IF AVAILABLE xxpi_mstr = FALSE THEN */
space(25) temp-lead-src label "Lead Source Value"
skip 19
Culligan Confidential
Example# 2
Code sample – Sales Order Maintenance …continued
ASSIGN temp-lead-src = xxpi_mstr.xxpi_lead_src IF AVAILABLE xxpromo_mstr = FALSE THEN
/* ERROR: Invalid lead credit */
temp-promo-code = xxpi_mstr.xxpi_promo_code DO:
{pxmsg.i &MSGNUM=9341 &ERRORLEVEL=3}.
temp-lead-credit = xxpi_mstr.xxpi_lead_credit /* ERROR: Invalid promo code */
NEXT-PROMPT temp-lead-credit WITH FRAME frm-1.
temp-call-ctr-ref = xxpi_mstr.xxpi_call_ctr_ref {pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}.
NEXT loop1.
NEXT-PROMPT temp-promo-code WITH FRAME frm-1.
temp-pap = xxpi_mstr.xxpi_pap END. /* IF NOT CAN-FIND(emp_mstr... */
NEXT loop1.
temp-cancel-reason = xxpi_mstr.xxpi_can_reason END. /* IF AVAILABLE xxpromo_mstr = FALSE THEN */
IF lookup(emp_title,"Technician,Driver,Inside Sales Rep,"
temp-cancel-date = xxpi_mstr.xxpi_can_date.
+ "Retail Supervisor,Retail Associate") = 0
loop1: IF xxpromo_mstr.xxpromo_start_date > so_mstr.so_ord_date
THEN DO:
REPEAT ON ENDKEY UNDO, RETRY: OR xxpromo_mstr.xxpromo_end_date < so_mstr.so_ord_date
/* ERROR: Invalid lead credit */
THEN
UPDATE temp-lead-src {pxmsg.i &MSGNUM=9341 &ERRORLEVEL=3}.
DO:
temp-promo-code NEXT-PROMPT temp-lead-credit WITH FRAME frm-1.
/* ERROR: Invalid promo code */
NEXT loop1.
temp-lead-credit {pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}.
END. /* IF CAN-FIND(sp_mstr... */
temp-call-ctr-ref NEXT-PROMPT temp-promo-code WITH FRAME frm-1.
END. /* IF temp-lead-credit <> "" THEN */
temp-pap NEXT loop1.
IF temp-pap = YES THEN
END. /* IF xxpromo_mstr.xxpromo_start_date >
temp-cancel-reason DO:
so_mstr.so_ord_date... */
temp-cancel-date IF NOT CAN-FIND(xxcm_pap
WHERE xxcm_pap.xxcm_domain = global_domain
WITH FRAME frm-1. IF xxpromo_mstr.xxpromo_allsites = NO THEN
AND xxcm_pap.xxcm_addr = temp-bill-to)
DO:
AND NOT CAN-FIND(xxcc_mstr
IF temp-lead-src = ? THEN temp-lead-src = 0. IF NOT CAN-FIND(xxpromosi_det
WHERE xxcc_mstr.xxcc_domain = global_domain
WHERE xxpromosi_det.xxpromosi_domain = global_domain
IF temp-promo-code = ? THEN temp-promo-code = 0. AND xxcc_mstr.xxcc_addr = temp-bill-to) THEN
AND xxpromosi_det.xxpromosi_code = temp-promo-code
IF temp-lead-credit = ? THEN temp-lead-credit = "". DO:
AND xxpromosi_det.xxpromosi_site = so_mstr.so_site
/* ERROR: Customer must have active APP account */
IF temp-call-ctr-ref = ? THEN temp-call-ctr-ref = "". AND xxpromosi_det.xxpromosi_active = YES) THEN
{pxmsg.i &MSGNUM=9337 &ERRORLEVEL=3}.
IF temp-pap = ? THEN temp-pap = NO. DO:
NEXT-PROMPT temp-pap WITH FRAME frm-1.
IF temp-cancel-reason = ? THEN temp-cancel-reason = "". /* ERROR: Invalid promo code */
NEXT loop1.
{pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}.
IF NOT CAN-FIND(code_mstr END. /* IF NOT CAN-FIND(xxcm_pap... */
NEXT-PROMPT temp-promo-code WITH FRAME frm-1.
WHERE code_mstr.code_domain = global_domain END. /* IF temp-pap = YES THEN */
NEXT loop1.
AND code_mstr.code_fldname = "temp-lead-src" END. /* IF NOT CAN-FIND(xxpromosi_det... */
IF temp-cancel-date <> ? THEN
AND code_mstr.code_value = STRING(temp-lead-src, END. /* IF xxpromo_mstr.xxpromo_allsites = NO THEN */
DO:
"999")) THEN IF temp-cancel-date < so_mstr.so_ord_date THEN
DO: IF temp-lead-credit <> "" THEN
DO:
DO:
/* ERROR: Invalid Lead Source */ /* ERROR: Invalid cancel date */
FIND emp_mstr
{pxmsg.i &MSGNUM=9283 &ERRORLEVEL=3}. {pxmsg.i &MSGNUM=9904 &ERRORLEVEL=3}.
WHERE emp_mstr.emp_domain = global_domain
NEXT-PROMPT temp-cancel-date WITH FRAME frm-1.
NEXT-PROMPT temp-lead-src WITH FRAME frm-1. AND emp_mstr.emp_addr = temp-lead-credit
NEXT loop1.
NEXT loop1. AND emp_mstr.emp_status <> "TR"
END. /* IF temp-cancel-date < lca_opn_date THEN */
END. /* IF NOT CAN-FIND(code_mstr */ NO-LOCK NO-ERROR.
IF AVAILABLE emp_mstr = FALSE THEN
FIND xxpromo_mstr DO:
WHERE xxpromo_mstr.xxpromo_domain = global_domain
AND xxpromo_mstr.xxpromo_code = temp-promo-code
NO-LOCK NO-ERROR. 20
Culligan Confidential
Example# 2
Code sample – Sales Order Maintenance …continued
IF temp-cancel-reason = "" THEN xxpi_mstr.xxpi_can_reason = temp-cancel-reason
if vyesno = no then next loop1. xxpi_mstr.xxpi_can_date = temp-cancel-date.
DO:
else do: END. /* IF si_mstr.si_site >= 300... */
/* ERROR: Reason code does not exist */ hide frame frm-1. END. /* IF temp-run = YES THEN */
{pxmsg.i &MSGNUM=534 &ERRORLEVEL=3}. leave loop1.
NEXT-PROMPT temp-cancel-reason WITH FRAME end. HIDE FRAME frm-1 NO-PAUSE.
frm-1. end. /* temp-lead-src = 0 */
NEXT loop1. else if temp-call-ctr-ref = "" and temp-lead-src <> 0
then do:
END. /* IF temp-cancel-reason = "" THEN */
END. /* IF temp-cancel-date <> ? THEN */
display lblank @ temp-call-ctr-ref with frame frm-3.
IF temp-cancel-reason <> "" THEN update vyesno with frame frm-3.
DO: hide frame frm-3.
IF NOT CAN-FIND(code_mstr if vyesno = no then next loop1.
WHERE code_mstr.code_domain = global_domain else do:
hide frame frm-1.
AND code_mstr.code_fldname = "sa_sa_type"
leave loop1.
AND code_mstr.code_value = temp-cancel-reason) end.
THEN end. /* temp-call-ctr-ref = "" */
DO: else if temp-lead-src = 0 and temp-call-ctr-ref = ""
/* ERROR: Reason code does not exist */ then do:
{pxmsg.i &MSGNUM=534 &ERRORLEVEL=3}. display temp-lead-src
lblank @ temp-call-ctr-ref
NEXT-PROMPT temp-cancel-reason WITH FRAME
with frame frm-4.
frm-1.
update vyesno with frame frm-4.
NEXT loop1. hide frame frm-4.
END. /* IF NOT CAN-FIND(code_mstr... */ if vyesno = no then next loop1.
else do:
IF temp-cancel-date = ? THEN hide frame frm-1.
leave loop1.
DO:
end.
/* ERROR: Invalid cancel date */ end. /* else if temp-lead-src = 0 and temp-call-ctr-ref = "" */
{pxmsg.i &MSGNUM=9904 &ERRORLEVEL=3}. else
NEXT-PROMPT temp-cancel-date WITH FRAME frm-1. leave loop1.
NEXT loop1.
END. /* loop1: REPEAT ON ENDKEY UNDO, RETRY: */
END. /* IF temp-cancel-date = ? THEN */
END. /* IF temp-cancel-reason <> "" THEN */ ASSIGN xxpi_mstr.xxpi_lead_src = temp-lead-src
xxpi_mstr.xxpi_promo_code = temp-promo-code
vyesno = NO. xxpi_mstr.xxpi_lead_credit = temp-lead-credit
if temp-lead-src = 0 and temp-call-ctr-ref <> "" xxpi_mstr.xxpi_call_ctr_ref = temp-call-ctr-ref
xxpi_mstr.xxpi_pap = temp-pap
then do:
display temp-lead-src with frame frm-2.
update vyesno with frame frm-2.
hide frame frm-2.
21
Culligan Confidential
Example# 2
Field Help
New frame to capture
additional data, to enable
interface to another
application.
F2 – help works with the
newly added fields, just
like it were a part of the
original QAD code.
22
Culligan Confidential
Example# 3
PO Maintenance
23
Culligan Confidential
Example# 3
Set up anchor for PO Maintenance
24
Culligan Confidential
Example# 3
Code Sample – PO Maintenance
tpvalsite.p
{mfdeclre.i}
def var vposite as char no-undo.
{getscrn.i &fieldname='"po_site"'
&variable=vposite }
if vposite = "" then do:
/*941 Blank site not allowed*/
{pxmsg.i &MSGNUM=941 &ERRORLEVEL=3}
{entry.i &fieldname='"po_site"'}
end. /* vposite = "" */
{setvalue.i &valuename='"tpvalsite"'
&cvalue=vposite
&valueid='"po"' }
25
Culligan Confidential
Example# 4
TailorPro Audit
26
Culligan Confidential
Example# 4
Set up Audit records/fields in Tailor Pro
Auto generates audit_vd_mstr.p
Creates audit records in
TailorPro’s “audittrail” table
27
Culligan Confidential
Example# 4
Audit Trail Report
xxtpauditrp.p C 001 36.12.11 Tailorpro AuditTrail Report (C) Date: 09/08/09
Page: 1 Culligan US1 - Test 07-07-09 Time: 17:36:59
Date Time User TableName FieldName Old Value New Value Record Key Field EventType
-------- ----- ------- ------------ ------------ -------------------- -------------------- ------------------------------ ---------
07/01/09 15:14 bmorgan vd_mstr 031816 Create
07/01/09 15:14 bmorgan vd_mstr vd_addr 031816 031816 Update
07/01/09 15:15 bmorgan vd_mstr vd_sort SOLOMON, SALTSMAN & 031816 Update
07/01/09 15:15 bmorgan vd_mstr vd_promo ACTIVE 031816 Update
07/01/09 15:16 bmorgan vd_mstr vd_cr_terms N0 031816 Update
07/02/09 10:41 dpatel vd_mstr 031818 Create
07/02/09 10:41 dpatel vd_mstr vd_addr 031818 031818 Update
07/02/09 10:44 dpatel vd_mstr vd_sort COLONY INC 031818 Update
07/02/09 10:44 dpatel vd_mstr vd_promo ACTIVE 031818 Update
07/02/09 10:47 dpatel vd_mstr vd_cr_terms N45 031818 Update
07/02/09 11:09 dpatel vd_mstr 031819 Create
07/02/09 11:09 dpatel vd_mstr vd_addr 031819 031819 Update
07/02/09 11:10 dpatel vd_mstr vd_sort LINDA L BERNY 031819 Update
07/02/09 11:10 dpatel vd_mstr vd_promo ACTIVE 031819 Update
07/02/09 11:11 dpatel vd_mstr vd_cr_terms N0 031819 Update
07/02/09 11:16 dpatel vd_mstr 194021 Create
07/02/09 11:16 dpatel vd_mstr vd_addr 194021 194021 Update
07/02/09 11:17 dpatel vd_mstr vd_sort BARBARA HUNTT 194021 Update
07/02/09 11:17 dpatel vd_mstr vd_promo ACTIVE 194021 Update
07/02/09 11:18 dpatel vd_mstr vd_cr_terms N30 194021 Update
07/02/09 11:20 dpatel vd_mstr 175100 Create
07/02/09 11:20 dpatel vd_mstr vd_addr 175100 175100 Update
07/02/09 11:20 dpatel vd_mstr vd_sort MILTON ZAHN 175100 Update
07/02/09 11:20 dpatel vd_mstr vd_promo ACTIVE 175100 Update
07/02/09 11:23 dpatel vd_mstr vd_cr_terms N30 175100 Update
07/02/09 11:25 dpatel vd_mstr 169725 Create
07/02/09 11:25 dpatel vd_mstr vd_addr 169725 169725 Update
07/02/09 11:28 dpatel vd_mstr vd_sort MIKE LADD 169725 Update
07/02/09 11:28 dpatel vd_mstr vd_promo ACTIVE 169725 Update
07/02/09 11:28 dpatel vd_mstr vd_cr_terms N30 169725 Update
07/02/09 15:28 dpatel vd_mstr vd_promo INACTIVE ACTIVE 187001 Update
07/02/09 15:42 dpatel vd_mstr vd_promo INACTIVE ACTIVE KINSPR01 Update
07/02/09 15:43 dpatel vd_mstr vd_cr_terms V40 N40 KINSPR01 Update
07/02/09 16:06 ekurty vd_mstr 10029996 Create
07/02/09 16:06 ekurty vd_mstr vd_addr 10029996 10029996 Update
07/02/09 16:06 ekurty vd_mstr vd_sort CHERI BATES 10029996 Update
07/02/09 16:06 ekurty vd_mstr vd_cr_terms N0 10029996 Update
07/02/09 16:06 ekurty vd_mstr vd_promo INACTIVE 10029996 Update
28
Culligan Confidential
Concerns?
TailorPro cannot affect internal program variables
TailorPro changes to screens are ignored by Mfg/Pro CIM loads
TailorPro is not designed to handle "output" (i.e. reports), so you
can't use the tool to change fields in a report
We learned to ‘think differently’ in some instances such as
Contract Start Date & End Date default values in 11.5.13.1
Contract Maintenance needed to be modified. Anchoring our
Tailorpro changes to the date field wasn’t providing the assign hfield = self:handle.
desired defaults, because QAD’s logic was overriding the
Tailorpro change. Moved the anchor to “entry” of first field /* get the CC, via handle (Tailorpro include doesn't work with this) */
on the frame and used “NEW” function prior to QAD repeat while valid-handle(hfield):
program’s use of the function to achieve the results.
if hfield:type = 'fill-in' and hfield:name = 'vod_cc' then
def var hfield as handle no-undo.
Scrolling frames do not respond as desired to the Tailorpro
includes. So, for example, in 28.1 Voucher Maintenance, we assign hfield = self:handle.
used Progress handle, instead of the getscrn.i include file.
/* get the CC, via handle (Tailorpro include doesn't work with this) */
repeat while valid-handle(hfield):
if hfield:type = 'fill-in' and hfield:name = 'vod_cc' then
assign found-cc = yes
cc = hfield:screen-value.
if hfield:type = 'fill-in' and hfield:name = 'vod_entity' then
assign found-ent = yes
ent = hfield:screen-value.
hfield = hfield:next-tab-item.
end. /*repeat*/
29
Culligan Confidential
We can do what ???
We can enable or disable display or updates to the Sales Order Maintenance without touching the code, by directly
‘anchoring’ a TailorPro code to a program.
Seq Event Field Program Tailorpro Frame Description
1 Entry sod_loc sosomt1b.p tplocreadonly1.p d
2 Entry line sosomta.p tphidesodtl.p c Hide some SO line detail fields
3 Entry sod_part sosomta.p tphidesodtl.p c Hide some SO line entry detail fields
4 Entry sngl_ln sosomta.p tplineexit.p a show order summary after exiting line entry mode
5 Entry line sosomta.p tpskipreset.p c skip frame
6 Leave sod_part sosomta.p tpsvpart.p c Capture Part Number
7 Leave sod_part sosomta.p tpycode.p c Restrict New Lines for Y code Customers.
8 Leave so_nbr sosomta1.p tpgetsonbr.p a get sonbr
9 Entry so_nbr sosomta1.p tpsetsonbr.p a frame skip
10 Go sosomta1.p valcrtord.p a Validate that user can not enter a so_nbr that doesn't exist.
11 Entry so_tax_usage sosomtb.p tpskipframe.p set_tax Skip a frame
12 Entry so_cr_init sosomtc2.p tpaskskip.p d skip frame
13 Entry so_cr_init sosomtc2.p tphidesotrl.p d hide some SO trailer fields
14 exe so_cr_init sosomtc2.p tphotkey.p d
15 Go sosomtc2.p tpsoisbupd.p d 30224
16 Go sosomtc2.p tpsostat1.p d 31205
17 Leave so_cust sosomtcm.p tpchkcusttype.p a New Warning Message when a cod customer is selected.
18 Leave so_cust sosomtcm.p tpcustsite.p a Restrict COD users from entering Orders for Corp Customers
19 Entry so_cust sosomtcm.p tpgetsonbr.p a Get sales order for new orders
20 Leave so_bill sosomtcm.p tplvbilto.p a
21 Leave so_ship sosomtcm.p tpshiptolv.p a
22 Leave so_ship sosomtcm.p tpshiptolv.p a
30
Culligan Confidential
We can do what ???
Seq Event Field Program Tailorpro Frame Description
23 Leave so_cust sosomtcm.p tpupsochr01a.p a BA 31531 flag order for Demar export
24 Leave so_cust sosomtcm.p tpycdcus.p a Capture Customer and Restrict Entry of new customers.
25 Entry sod_sob_std sosomtf8.p tphidesodtl.p bom Hide some SO line entry detail fields
26 Entry reprice_dtl sosomtla.p tphidesocrt.p line_pop Hide so_crt_int field
27 Entry sod_pr_list sosomtla.p tphidesocrt.p line_pop Hide so_crt_int field when entering new line item
28 Entry sod_list_pr sosomtla.p tphidesodtl.p c Hide some SO line detail entry fields
29 Leave sod_pr_list sosomtla.p tphidesodtl.p line_pop Hide some SO line entry detail fields
30 Leave sod_qty_ord sosomtla.p tppendob.p c Pending Obsolete - check to make sure there are enough in inventory
31 Leave sod_qty_ord sosomtla.p tpqtyordcase.p c
32 Go sosomtlb.p tpcategorylv.p d
33 Entry sod_loc sosomtlb.p tphidesodtl.p d Hide some so line detail fields
34 Go sosomtlb.p tpsodpart.p d 30224
35 Entry so_ord_date sosomtp.p tpdefremark.p b
36 Entry so_slspsn sosomtp.p tphidesoshp.p b1 Hide some SO shipment frame fields
37 Entry so_req_date sosomtp.p tpskipframe.p b skip frame
38 Entry so_slspsn sosomtp.p tpskipframe.p b1 skip frame
39 Entry so_ord_date sosomtp.p tpskipframe2.p b
40 Go sosomtp.p tpslsrp.p b1 Salesperson validation
41 Entry sosomtp.p tptaxable_so.p b Make Taxable flag “display only”
42 Entry sosomtp.p tptaxable_so.p set_tax Make Taxable flag “display only”
43 Entry so_disc_pct sosotrle.p tphidesotrl.p sotot Hide some SO trailer fields
44 exe so_disc_pct sosotrle.p tphotkey.p sotot
45 Go sosotrle.p tpsoslsupd.p sotot Update sales person from header to detail
46 Entry so_disc_pct sosotrle.p tpsotrl.p sotot new frame in sales order maintenance
31
Culligan Confidential
Where we are now
We now have a total of approximately 180 TailorPro enhancements, involving non-invasive coding
which includes:
Added fields from QAD tables or Custom Database tables
Default Field values displayed
Edited field values
Hidden fields
Fields changed to View Only
Large Sections of ‘applied’ logic
Conditional Calls to other programs
Auditing of DB table / field changes
Time spent on the changes so far –
With an average of 1 man day effort for a TailorPro program, we have spent 180 days working on
the Tailorpro enhancements.
An average of 1 week of effort for modifying the QAD code and all the related include files, we
have 1260 man days (180 * 7 days) that would’ve been spent on QAD changes.
That’s 1080 man days (1260 – 180) saved in coding time, alone.
Time spent retro-fitting the codes for a future upgrade –
Zero
32
Culligan Confidential
Conclusion
Culligan needed a better fit between business needs and the
business system.
TailorPro provides the engine to enable the required
customizations with no changes to source code or the production
database.
TailorPro could support Culligan’s need for audit compliance.
QAD’s next upgrade will not require changes to TailorPro solutions.
33
Culligan Confidential
34
34
Culligan Confidential
Get documents about "