1 / 34

MMUG Sept 2009

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. Introduction.

kassia
Download Presentation

MMUG Sept 2009

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Making QAD Dance to your Tunes!A Case study demonstrating how Culligan added functionality to QAD, using TailorPro’s rapid enhancements and non-invasive customizationsMeera Ravindran – Culligan InternationalBruce LeBel – Prostar Systems MMUG Sept 2009

  2. 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.

  3. 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

  4. 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

  5. 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

  6. 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.

  7. 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) • In-Store Bottle Water Dispensers • Service • (Complimentary in home analysis, • Certified Sales, Installation and Service Technicians, • Full Service - Salt Delivery, • Full Service - Filter Exchange)

  8. Who We Are – Focus On Improving Efficiency • Culligan was acquired by Clayton, Dubilier & Rice, Inc (CD&R) a private equity firmin 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

  9. Culligan Production Databases eB 2 . 1 Database for Culligan North America Operations Wholesale Canada Corporate/ Culiigan Owned Dealership Division (CODD) US Canada

  10. 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.

  11. 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.

  12. 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.

  13. Example# 1 Set up anchors for Item Master new fields

  14. Example# 1Code Sample – Item Master new fields tpptchr09a.p { crtfill.i &FieldName = '"pt_user1"' &FieldRow = 2 &FieldCol = 34 &Visible = yes &FrameName = '"a"' &DataType = '"Character"' &TableName = "pt_mstr" &FieldLabel = '"RentFA"' &FieldFormat = '"x(1)"' &FieldWidth = 1 &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" } tpptchr09b.p {enable.i &FieldNames = '"pt_user1"' } {enable.i &FieldNames = '"pt__chr09"' } {taborder.i &FieldNames = '"pt_um,pt_user1,pt__chr09,pt_desc1,pr_desc2"' }

  15. Example# 1Code Sample – Item Master new fields …continued {getscrn.i &FieldName = '"pt__chr09"' &FrameName = '"a"' &Variable = ptchr09 } find first pt_mstr exclusive where pt_domain = global_domain and pt_part = ptpart. if (keyfunction(lastkey) = "Go" or keyfunction(lastkey) = "Return") and lookup(ptuser1,"Y,N") = 0 and (pt_mstr.pt_user1 <> ptuser1) then do: message "Invalid RentFA. Must be Y or N.". pause. {entry.i &FieldName = '"pt_user1"'} end. else if (keyfunction(lastkey) = "Go" or keyfunction(lastkey) = "Return") and lookup(ptchr09,",CORP,CODD") = 0 and (pt_mstr.pt__chr09 <> ptchr09) then do: message "Invalid Division. Must be CODD, CORP or blank.". pause. {entry.i &FieldName = '"pt__chr09"'} end. else if (keyfunction(lastkey) = "Go" or keyfunction(lastkey) = "Return") then do: pt_mstr.pt__chr09 = ptchr09. pt_mstr.pt_user1 = ptuser1. end. end. /* if ptpart-go... ELSE do */ {disable.i &FieldNames = '"pt_user1"' } {disable.i &FieldNames = '"pt__chr09"' } ptuser1 = if avail pt_mstr then pt_user1 else "N". ptchr09 = if avail pt_mstr then pt__chr09 else "". {scrnvalu.i &FieldName = '"pt_user1"' &FrameName = '"a"' &FieldValue = ptuser1 } {scrnvalu.i &FieldName = '"pt__chr09"' &FrameName = '"a"' &FieldValue = ptchr09 } end. /* if ptpart-go... then do */ /* Update Item Division (pt__chr09) from the screen value */ else do: {setvalue.i &ValueID = '"ppptmta"' &ValueName = '"ptpart-go"' &cValue = "No" } {getscrn.i &FieldName = '"pt_part"' &FrameName = '"a"' &Variable = ptpart } {getscrn.i &FieldName = '"pt_user1"' &FrameName = '"a"' &Variable = ptuser1 } tpchr09go.p {mfdeclre.i} def var ptpart-go as char no-undo. def var ptpart as char no-undo. def var ptchr09 as char no-undo. def var ptuser1 as char no-undo. {getvalue.i &ValueID = '"ppptmta"' &ValueName = '"ptpart-go"' &Variable = ptpart-go } /* There are 2 GOs in frame A: * 1: ptpart-go = yes * If Go for pt_part * Then Display the Item Division (pt__chr09) * 2: ptpart-go = no * If Go for pt_um, pt__chr09 (new), pt_desc1, pt_desc2 * Then Update pt__chr09 from the screen value * * ptpart-go is set to yes in tpptchr09a.p (Entry of pt_part) * ptpart-go is set to no while handling the go for pt_part * ptpart-go is set to yes while handling the go for pt__chr09 */ /* Display Item Division (pt__chr09) */ if ptpart-go = "Yes" then do: {setvalue.i &ValueID = '"ppptmta"' &ValueName = '"ptpart-go"' &cValue = "No" } ptpart = frame-value. find first pt_mstr no-lock where pt_domain = global_domain and pt_part = ptpart no-error.

  16. Example# 1Anchor & 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"'} leave. end. level = level + 1. end. /* repeat while */ tppt_mstr.p &global-define TableName pt_mstr {getbroker.i} {progvars.i} {tablevar.i} &global-define AfterFind ~ run tpptchr09dsp.p (rowid(pt_mstr)). ~ {findrec.i} &Undefine AfterFind Procedure Create_Record: end procedure. {getrowid.i}

  17. Example# 2 Sales Order Maintenance New frame to accept custom “lead data” Fields that drives sales commission calculations

  18. Example# 2Set up anchor for SO Maintenance

  19. Example# 2Code sample – Sales Order Maintenance space(25) vyesno label "Do you want to continue?" skip with side-labels title " Lead Source Validation" size-chars 80 by 9 row 5 overlay. define frame frm-3 skip(2) space(25) temp-call-ctr-ref label "Call Center Reference" skip space(25) vyesno label "Do you want to continue?" skip with side-labels title " Call Center Reference Validation" size-chars 80 by 9 row 5 overlay. define frame frm-4 skip(2) space(25) temp-lead-src label "Lead Source Value" skip space(25) temp-call-ctr-ref label "Call Center Reference" skip space(25) vyesno label "Do you want to continue?" skip with side-labels title " Lead Source & Call Center Ref Validation" size-chars 80 by 9 row 5 overlay. PAUSE 0 BEFORE-HIDE. ASSIGN temp-run = YES temp-level = 1. REPEAT WHILE program-name(temp-level) <> ?: IF program-name(temp-level) = "us/fs/fsrmamt.r" THEN DO: ASSIGN temp-run = NO. LEAVE. END. /* IF program-name(temp-level) = "us/fs/fsrmamt.r" THEN */ ASSIGN temp-level = temp-level + 1. END. /* REPEAT WHILE program-name(temp-level) <> ?: */ IF temp-run = YES THEN DO: {getscrn.i &fieldname='"so_nbr"' &framename='"a"' &variable=temp-so-nbr}. {getscrn.i &fieldname = '"so_bill"' &framename = '"a"' &variable = temp-bill-to}. FIND so_mstr WHERE so_mstr.so_domain = global_domain AND so_mstr.so_nbr = temp-so-nbr NO-LOCK NO-ERROR. IF AVAILABLE so_mstr = FALSE THEN RETURN. ASSIGN temp-site = so_mstr.so_site. FIND si_mstr WHERE si_mstr.si_domain = global_domain AND si_mstr.si_site = temp-site NO-LOCK NO-ERROR. IF AVAILABLE si_mstr = TRUE AND si_mstr.si_site >= "300" AND si_mstr.si_site <= "900" THEN DO: ASSIGN temp-lead-src = 0 temp-promo-code = 0 temp-lead-credit = "" temp-call-ctr-ref = "" temp-pap = NO temp-cancel-reason = "" temp-cancel-date = ?. FIND xxpi_mstr WHERE xxpi_mstr.xxpi_domain = global_domain AND xxpi_mstr.xxpi_nbr = temp-so-nbr EXCLUSIVE-LOCK NO-ERROR. IF AVAILABLE xxpi_mstr = FALSE THEN DO: CREATE xxpi_mstr. ASSIGN xxpi_mstr.xxpi_domain = global_domain xxpi_mstr.xxpi_nbr = temp-so-nbr xxpi_mstr.xxpi_lead_src = 0 xxpi_mstr.xxpi_promo_code = 0 xxpi_mstr.xxpi_lead_credit = "" xxpi_mstr.xxpi_call_ctr_ref = "" xxpi_mstr.xxpi_pap = NO xxpi_mstr.xxpi_can_reason = "" xxpi_mstr.xxpi_can_date = ?. END. /* IF AVAILABLE xxpi_mstr = FALSE THEN */ tpsotrl.p {mfdeclre.i}. DEF VAR temp-cancel-reason AS CHAR FORMAT "X(8)" INITIAL "" LABEL "Cancel Reason" NO-UNDO. DEF VAR temp-cancel-date AS DATE FORMAT "99/99/99“ INITIAL ? LABEL "Cancel Date" NO-UNDO. DEF VAR temp-pap AS LOG FORMAT "Yes/No" INITIAL "No" LABEL "APP" NO-UNDO. DEF VAR temp-bill-to AS CHAR NO-UNDO. DEF VAR temp-lead-src AS INT FORMAT ">>9" INITIAL 0 LABEL "Lead Source" NO-UNDO. DEF VAR temp-promo-code AS INT FORMAT ">>9" INITIAL 0 LABEL "Promo Code" NO-UNDO. DEF VAR temp-lead-credit AS CHAR FORMAT "X(8)" INITIAL "" LABEL "Lead Credit" NO-UNDO. DEF VAR temp-call-ctr-ref AS CHAR FORMAT "X(8)" INITIAL "" LABEL "Call Center Ref" NO-UNDO. DEF VAR temp-so-nbr AS CHAR NO-UNDO. DEF VAR temp-site AS CHAR NO-UNDO. DEF VAR temp-run AS LOG NO-UNDO. DEF VAR temp-level AS INT NO-UNDO. DEF VAR vyesno as log format "Yes/No" init "No" no-undo. DEF VAR lblank as char init "<Blank>" no-undo. DEFINE FRAME frm-1 temp-lead-src AT ROW 1 COLUMN 5 temp-promo-code AT ROW 2 COLUMN 6 temp-lead-credit AT ROW 3 COLUMN 5 temp-call-ctr-ref AT ROW 4 COLUMN 1 temp-pap AT ROW 5 COLUMN 13 temp-cancel-reason AT ROW 6 COLUMN 3 temp-cancel-date AT ROW 7 COLUMN 5 WITH SIDE-LABELS SIZE-CHARS 80 BY 9 ROW 5 OVERLAY. define frame frm-2 skip(2) space(25) temp-lead-src label "Lead Source Value" skip

  20. Example# 2Code sample – Sales Order Maintenance …continued ASSIGN temp-lead-src = xxpi_mstr.xxpi_lead_src temp-promo-code = xxpi_mstr.xxpi_promo_code temp-lead-credit = xxpi_mstr.xxpi_lead_credit temp-call-ctr-ref = xxpi_mstr.xxpi_call_ctr_ref temp-pap = xxpi_mstr.xxpi_pap temp-cancel-reason = xxpi_mstr.xxpi_can_reason temp-cancel-date = xxpi_mstr.xxpi_can_date. loop1: REPEAT ON ENDKEY UNDO, RETRY: UPDATE temp-lead-src temp-promo-code temp-lead-credit temp-call-ctr-ref temp-pap temp-cancel-reason temp-cancel-date WITH FRAME frm-1. IF temp-lead-src = ? THEN temp-lead-src = 0. IF temp-promo-code = ? THEN temp-promo-code = 0. IF temp-lead-credit = ? THEN temp-lead-credit = "". IF temp-call-ctr-ref = ? THEN temp-call-ctr-ref = "". IF temp-pap = ? THEN temp-pap = NO. IF temp-cancel-reason = ? THEN temp-cancel-reason = "". IF NOT CAN-FIND(code_mstr WHERE code_mstr.code_domain = global_domain AND code_mstr.code_fldname = "temp-lead-src" AND code_mstr.code_value = STRING(temp-lead-src, "999")) THEN DO: /* ERROR: Invalid Lead Source */ {pxmsg.i &MSGNUM=9283 &ERRORLEVEL=3}. NEXT-PROMPT temp-lead-src WITH FRAME frm-1. NEXT loop1. END. /* IF NOT CAN-FIND(code_mstr */ FIND xxpromo_mstr WHERE xxpromo_mstr.xxpromo_domain = global_domain AND xxpromo_mstr.xxpromo_code = temp-promo-code NO-LOCK NO-ERROR. IF AVAILABLE xxpromo_mstr = FALSE THEN DO: /* ERROR: Invalid promo code */ {pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}. NEXT-PROMPT temp-promo-code WITH FRAME frm-1. NEXT loop1. END. /* IF AVAILABLE xxpromo_mstr = FALSE THEN */ IF xxpromo_mstr.xxpromo_start_date > so_mstr.so_ord_date OR xxpromo_mstr.xxpromo_end_date < so_mstr.so_ord_date THEN DO: /* ERROR: Invalid promo code */ {pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}. NEXT-PROMPT temp-promo-code WITH FRAME frm-1. NEXT loop1. END. /* IF xxpromo_mstr.xxpromo_start_date > so_mstr.so_ord_date... */ IF xxpromo_mstr.xxpromo_allsites = NO THEN DO: IF NOT CAN-FIND(xxpromosi_det WHERE xxpromosi_det.xxpromosi_domain = global_domain AND xxpromosi_det.xxpromosi_code = temp-promo-code AND xxpromosi_det.xxpromosi_site = so_mstr.so_site AND xxpromosi_det.xxpromosi_active = YES) THEN DO: /* ERROR: Invalid promo code */ {pxmsg.i &MSGNUM=9340 &ERRORLEVEL=3}. NEXT-PROMPT temp-promo-code WITH FRAME frm-1. NEXT loop1. END. /* IF NOT CAN-FIND(xxpromosi_det... */ END. /* IF xxpromo_mstr.xxpromo_allsites = NO THEN */ IF temp-lead-credit <> "" THEN DO: FIND emp_mstr WHERE emp_mstr.emp_domain = global_domain AND emp_mstr.emp_addr = temp-lead-credit AND emp_mstr.emp_status <> "TR" NO-LOCK NO-ERROR. IF AVAILABLE emp_mstr = FALSE THEN DO: /* ERROR: Invalid lead credit */ {pxmsg.i &MSGNUM=9341 &ERRORLEVEL=3}. NEXT-PROMPT temp-lead-credit WITH FRAME frm-1. NEXT loop1. END. /* IF NOT CAN-FIND(emp_mstr... */ IF lookup(emp_title,"Technician,Driver,Inside Sales Rep," + "Retail Supervisor,Retail Associate") = 0 THEN DO: /* ERROR: Invalid lead credit */ {pxmsg.i &MSGNUM=9341 &ERRORLEVEL=3}. NEXT-PROMPT temp-lead-credit WITH FRAME frm-1. NEXT loop1. END. /* IF CAN-FIND(sp_mstr... */ END. /* IF temp-lead-credit <> "" THEN */ IF temp-pap = YES THEN DO: IF NOT CAN-FIND(xxcm_pap WHERE xxcm_pap.xxcm_domain = global_domain AND xxcm_pap.xxcm_addr = temp-bill-to) AND NOT CAN-FIND(xxcc_mstr WHERE xxcc_mstr.xxcc_domain = global_domain AND xxcc_mstr.xxcc_addr = temp-bill-to) THEN DO: /* ERROR: Customer must have active APP account */ {pxmsg.i &MSGNUM=9337 &ERRORLEVEL=3}. NEXT-PROMPT temp-pap WITH FRAME frm-1. NEXT loop1. END. /* IF NOT CAN-FIND(xxcm_pap... */ END. /* IF temp-pap = YES THEN */ IF temp-cancel-date <> ? THEN DO: IF temp-cancel-date < so_mstr.so_ord_date THEN DO: /* ERROR: Invalid cancel date */ {pxmsg.i &MSGNUM=9904 &ERRORLEVEL=3}. NEXT-PROMPT temp-cancel-date WITH FRAME frm-1. NEXT loop1. END. /* IF temp-cancel-date < lca_opn_date THEN */

  21. Example# 2Code sample – Sales Order Maintenance …continued if vyesno = no then next loop1. else do: hide frame frm-1. leave loop1. end. end. /* temp-lead-src = 0 */ else if temp-call-ctr-ref = "" and temp-lead-src <> 0 then do: display lblank @ temp-call-ctr-ref with frame frm-3. update vyesno with frame frm-3. hide frame frm-3. if vyesno = no then next loop1. else do: hide frame frm-1. leave loop1. end. end. /* temp-call-ctr-ref = "" */ else if temp-lead-src = 0 and temp-call-ctr-ref = "" then do: display temp-lead-src lblank @ temp-call-ctr-ref with frame frm-4. update vyesno with frame frm-4. hide frame frm-4. if vyesno = no then next loop1. else do: hide frame frm-1. leave loop1. end. end. /* else if temp-lead-src = 0 and temp-call-ctr-ref = "" */ else leave loop1. END. /* loop1: REPEAT ON ENDKEY UNDO, RETRY: */ ASSIGN xxpi_mstr.xxpi_lead_src = temp-lead-src xxpi_mstr.xxpi_promo_code = temp-promo-code xxpi_mstr.xxpi_lead_credit = temp-lead-credit xxpi_mstr.xxpi_call_ctr_ref = temp-call-ctr-ref xxpi_mstr.xxpi_pap = temp-pap IF temp-cancel-reason = "" THEN DO: /* ERROR: Reason code does not exist */ {pxmsg.i &MSGNUM=534 &ERRORLEVEL=3}. NEXT-PROMPT temp-cancel-reason WITH FRAME frm-1. NEXT loop1. END. /* IF temp-cancel-reason = "" THEN */ END. /* IF temp-cancel-date <> ? THEN */ IF temp-cancel-reason <> "" THEN DO: IF NOT CAN-FIND(code_mstr WHERE code_mstr.code_domain = global_domain AND code_mstr.code_fldname = "sa_sa_type" AND code_mstr.code_value = temp-cancel-reason) THEN DO: /* ERROR: Reason code does not exist */ {pxmsg.i &MSGNUM=534 &ERRORLEVEL=3}. NEXT-PROMPT temp-cancel-reason WITH FRAME frm-1. NEXT loop1. END. /* IF NOT CAN-FIND(code_mstr... */ IF temp-cancel-date = ? THEN DO: /* ERROR: Invalid cancel date */ {pxmsg.i &MSGNUM=9904 &ERRORLEVEL=3}. NEXT-PROMPT temp-cancel-date WITH FRAME frm-1. NEXT loop1. END. /* IF temp-cancel-date = ? THEN */ END. /* IF temp-cancel-reason <> "" THEN */ vyesno = NO. if temp-lead-src = 0 and temp-call-ctr-ref <> "" then do: display temp-lead-src with frame frm-2. update vyesno with frame frm-2. hide frame frm-2. xxpi_mstr.xxpi_can_reason = temp-cancel-reason xxpi_mstr.xxpi_can_date = temp-cancel-date. END. /* IF si_mstr.si_site >= 300... */ END. /* IF temp-run = YES THEN */ HIDE FRAME frm-1 NO-PAUSE.

  22. New frame to capture additional data, to enable interface to another application. Example# 2Field Help F2 – help works with the newly added fields, just like it were a part of the original QAD code.

  23. Example# 3PO Maintenance

  24. Example# 3Set up anchor for PO Maintenance

  25. 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"' }

  26. Example# 4TailorPro Audit

  27. Example# 4Set up Audit records/fields in Tailor Pro • Auto generates audit_vd_mstr.p • Creates audit records in TailorPro’s “audittrail” table

  28. Example# 4Audit 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

  29. 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 desired defaults, because QAD’s logic was overriding the Tailorpro change. Moved the anchor to “entry” of first field on the frame and used “NEW” function prior to QAD program’s use of the function to achieve the results. Scrolling frames do not respond as desired to the Tailorpro includes. So, for example, in 28.1 Voucher Maintenance, we used Progress handle, instead of the getscrn.i include file. assign hfield = self:handle. /* 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 def var hfield as handle no-undo. assign hfield = self:handle. /* 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*/ Concerns?

  30. 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.

  31. We can do what ???

  32. 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

  33. 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.

More Related