001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.module.ld.batch.service.impl;
017    
018    import static org.kuali.kfs.module.ld.LaborConstants.DestinationNames.ORIGN_ENTRY;
019    
020    import java.io.BufferedReader;
021    import java.io.File;
022    import java.io.FileNotFoundException;
023    import java.io.FileReader;
024    import java.io.IOException;
025    import java.io.PrintStream;
026    import java.sql.Date;
027    import java.util.ArrayList;
028    import java.util.HashMap;
029    import java.util.List;
030    import java.util.Map;
031    
032    import org.apache.commons.lang.StringUtils;
033    import org.kuali.kfs.gl.GeneralLedgerConstants;
034    import org.kuali.kfs.gl.batch.service.PostTransaction;
035    import org.kuali.kfs.gl.batch.service.VerifyTransaction;
036    import org.kuali.kfs.gl.report.LedgerSummaryReport;
037    import org.kuali.kfs.gl.report.TransactionListingReport;
038    import org.kuali.kfs.gl.service.OriginEntryGroupService;
039    import org.kuali.kfs.module.ld.LaborConstants;
040    import org.kuali.kfs.module.ld.LaborConstants.Poster;
041    import org.kuali.kfs.module.ld.batch.LaborPosterStep;
042    import org.kuali.kfs.module.ld.batch.service.LaborPosterService;
043    import org.kuali.kfs.module.ld.businessobject.LaborOriginEntry;
044    import org.kuali.kfs.module.ld.document.validation.impl.TransactionFieldValidator;
045    import org.kuali.kfs.module.ld.service.LaborOriginEntryService;
046    import org.kuali.kfs.module.ld.service.LaborTransactionDescriptionService;
047    import org.kuali.kfs.module.ld.util.LaborLedgerUnitOfWork;
048    import org.kuali.kfs.module.ld.util.LaborOriginEntryFileIterator;
049    import org.kuali.kfs.sys.KFSConstants;
050    import org.kuali.kfs.sys.Message;
051    import org.kuali.kfs.sys.MessageBuilder;
052    import org.kuali.kfs.sys.service.ReportWriterService;
053    import org.kuali.rice.kns.service.DateTimeService;
054    import org.kuali.rice.kns.service.ParameterService;
055    import org.kuali.rice.kns.util.ObjectUtils;
056    import org.springframework.transaction.annotation.Transactional;
057    
058    /**
059     * The Labor Ledger Poster accepts pending entries generated by Labor Ledger e-docs (such as Salary Expense Transfer and Benefit
060     * Expense Transfer), and combines them with entries from external systems. It edits the entries for validity. Invalid entries can
061     * be marked for Labor Ledger Error Correction process. The Poster writes valid entries to the Labor Ledger Entry table, updates
062     * balances in the Labor Ledger Balance table, and summarizes the entries for posting to the General Ledger.
063     */
064    @Transactional
065    public class LaborPosterServiceImpl implements LaborPosterService {
066        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LaborPosterServiceImpl.class);
067    
068        private LaborOriginEntryService laborOriginEntryService;
069        private OriginEntryGroupService originEntryGroupService;
070        private LaborTransactionDescriptionService laborTransactionDescriptionService;
071    
072        private ReportWriterService reportWriterService;
073        private ReportWriterService errorListingReportWriterService;
074        private ReportWriterService ledgerSummaryReportWriterService;
075        private ReportWriterService laborGlEntryStatisticsReportWriterService;
076    
077        private DateTimeService dateTimeService;
078        private VerifyTransaction laborPosterTransactionValidator;
079        private ParameterService parameterService;
080    
081        private PostTransaction laborLedgerEntryPoster;
082        private PostTransaction laborLedgerBalancePoster;
083        private PostTransaction laborGLLedgerEntryPoster;
084    
085        private int numberOfErrorOriginEntry;
086    
087        private String batchFileDirectoryName;
088        private PrintStream POSTER_OUTPUT_ERR_FILE_ps;
089        
090        /**
091         * @see org.kuali.kfs.module.ld.batch.service.LaborPosterService#postMainEntries()
092         */
093        public void postMainEntries() {
094            LOG.info("postMainEntries() started");
095    
096            Date runDate = dateTimeService.getCurrentSqlDate();
097            this.postLaborLedgerEntries(runDate);
098        }
099    
100        /**
101         * post the qualified origin entries into Labor Ledger tables
102         * 
103         * @param validGroup the origin entry group that holds the valid transactions
104         * @param invalidGroup the origin entry group that holds the invalid transactions
105         * @param runDate the data when the process is running
106         */
107        protected void postLaborLedgerEntries(Date runDate) {
108            LOG.info("postLaborLedgerEntries() started..........................");
109            numberOfErrorOriginEntry = 0;
110            // change file name to FIS
111    
112            String postInputFileName = batchFileDirectoryName + File.separator + LaborConstants.BatchFileSystem.POSTER_INPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION;
113            String postErrFileName = batchFileDirectoryName + File.separator + LaborConstants.BatchFileSystem.POSTER_ERROR_OUTPUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION;
114    
115            FileReader INPUT_GLE_FILE = null;
116            try {
117                INPUT_GLE_FILE = new FileReader(postInputFileName);
118            }
119            catch (FileNotFoundException e) {
120                throw new RuntimeException(e);
121            }
122    
123            try {
124                POSTER_OUTPUT_ERR_FILE_ps = new PrintStream(postErrFileName);
125            }
126            catch (IOException e) {
127                LOG.error("postLaborLedgerEntries cannot open file: " + e.getMessage(), e);
128                throw new RuntimeException(e);
129            }
130    
131            int lineNumber = 0;
132            int loadedCount = 0;
133    
134            int numberOfSelectedOriginEntry = 0;
135            LaborLedgerUnitOfWork laborLedgerUnitOfWork = new LaborLedgerUnitOfWork();
136    
137            LedgerSummaryReport ledgerSummaryReport = new LedgerSummaryReport();
138    
139            Map<String, Integer> reportSummary = this.constructPosterReportSummary();
140            Map<String, Integer> glEntryReportSummary = this.constructGlEntryReportSummary();
141    
142            try {
143                BufferedReader INPUT_GLE_FILE_br = new BufferedReader(INPUT_GLE_FILE);
144                String currentLine = INPUT_GLE_FILE_br.readLine();
145    
146                while (currentLine != null) {
147                    try {
148                        lineNumber++;
149                        if (!StringUtils.isEmpty(currentLine) && !StringUtils.isBlank(currentLine.trim())) {
150                            LaborOriginEntry laborOriginEntry = new LaborOriginEntry();
151    
152                            // checking parsing process and stop poster when it has errors.
153                            List<Message> parsingError = new ArrayList<Message>();
154                            parsingError = laborOriginEntry.setFromTextFileForBatch(currentLine, lineNumber);
155                            if (parsingError.size() > 0) {
156                                throw new RuntimeException("Exception happened from parsing process");
157                            }
158    
159                            loadedCount++;
160                            if (loadedCount % 1000 == 0) {
161                                LOG.info(loadedCount + " " + laborOriginEntry.toString());
162                            }
163    
164                            boolean isPostable = this.postSingleEntryIntoLaborLedger(laborOriginEntry, reportSummary, runDate, currentLine);
165                            if (isPostable) {
166                                this.updateReportSummary(glEntryReportSummary, ORIGN_ENTRY, KFSConstants.OperationType.READ);
167                                this.writeLaborGLEntry(laborOriginEntry, laborLedgerUnitOfWork, runDate, lineNumber, glEntryReportSummary);
168    
169                                ledgerSummaryReport.summarizeEntry(laborOriginEntry);
170    
171                                numberOfSelectedOriginEntry++;
172                                laborOriginEntry = null;
173                            }
174                        }
175    
176                        currentLine = INPUT_GLE_FILE_br.readLine();
177                    }
178                    catch (RuntimeException ioe) {
179                        // catch here again, it should be from postSingleEntryIntoLaborLedger
180                        LOG.error("postLaborLedgerEntries stopped due to: " + ioe.getMessage() + " on line number : " + loadedCount, ioe);
181                        throw new RuntimeException("Unable to execute: " + ioe.getMessage() + " on line number : " + loadedCount, ioe);
182                    }
183                }
184    
185                this.writeLaborGLEntry(null, laborLedgerUnitOfWork, runDate, lineNumber, glEntryReportSummary);
186    
187                INPUT_GLE_FILE_br.close();
188                INPUT_GLE_FILE.close();
189                POSTER_OUTPUT_ERR_FILE_ps.close();
190    
191                this.fillPosterReportWriter(lineNumber, reportSummary, glEntryReportSummary);
192                this.fillGlEntryReportWriter(glEntryReportSummary);
193    
194                // Generate Error Listing Report
195                ledgerSummaryReport.writeReport(ledgerSummaryReportWriterService);
196                new TransactionListingReport().generateReport(errorListingReportWriterService, new LaborOriginEntryFileIterator(new File(postErrFileName)));
197            }
198            catch (IOException ioe) {
199                LOG.error("postLaborLedgerEntries stopped due to: " + ioe.getMessage(), ioe);
200                throw new RuntimeException("Unable to execute: " + ioe.getMessage() + " on line number : " + loadedCount, ioe);
201            }
202        }
203    
204        /**
205         * post the given entry into the labor ledger tables if the entry is qualified; otherwise report error
206         * 
207         * @param originEntry the given origin entry, a transaction
208         * @param reportSummary the report summary object that need to be update when a transaction is posted
209         * @param runDate the data when the process is running
210         * @return true if the given transaction is posted into ledger tables; otherwise, return false
211         */
212        protected boolean postSingleEntryIntoLaborLedger(LaborOriginEntry originEntry, Map<String, Integer> reportSummary, Date runDate, String line) {
213            // reject the invalid entry so that it can be available for error correction
214            List<Message> errors = new ArrayList<Message>();
215            try {
216                errors = this.validateEntry(originEntry);
217            }
218            catch (Exception e) {
219                errors.add(new Message(e.toString() + " occurred for this record.", Message.TYPE_FATAL));
220            }
221    
222            if (errors != null && !errors.isEmpty()) {
223                reportWriterService.writeError(originEntry, errors);
224                numberOfErrorOriginEntry += errors.size();
225                writeErrorEntry(line);
226                return false;
227            }
228    
229            String operationOnLedgerEntry = postAsLedgerEntry(originEntry, runDate);
230            updateReportSummary(reportSummary, laborLedgerEntryPoster.getDestinationName(), operationOnLedgerEntry);
231    
232            String operationOnLedgerBalance = updateLedgerBalance(originEntry, runDate);
233            updateReportSummary(reportSummary, laborLedgerBalancePoster.getDestinationName(), operationOnLedgerBalance);
234    
235            return true;
236        }
237    
238        /**
239         * validate the given entry, and generate an error list if the entry cannot meet the business rules
240         * 
241         * @param originEntry the given origin entry, a transcation
242         * @return error message list. If the given transaction is invalid, the list has message(s); otherwise, it is empty
243         */
244        protected List<Message> validateEntry(LaborOriginEntry originEntry) {
245            return laborPosterTransactionValidator.verifyTransaction(originEntry);
246        }
247    
248        /**
249         * post the given entry to the labor entry table
250         * 
251         * @param originEntry the given origin entry, a transaction
252         * @param postDate the data when the transaction is processes return the operation type of the process
253         */
254        protected String postAsLedgerEntry(LaborOriginEntry originEntry, Date postDate) {
255            return laborLedgerEntryPoster.post(originEntry, 0, postDate, null);
256        }
257    
258        /**
259         * update the labor ledger balance for the given entry
260         * 
261         * @param originEntry the given origin entry, a transaction
262         * @param postDate the data when the transaction is processes return the operation type of the process
263         */
264        protected String updateLedgerBalance(LaborOriginEntry originEntry, Date postDate) {
265            return laborLedgerBalancePoster.post(originEntry, 0, postDate, null);
266        }
267    
268        /**
269         * determine if the given origin entry can be posted back to Labor GL entry
270         * 
271         * @param originEntry the given origin entry, atransaction
272         * @return a message list. The list has message(s) if the given origin entry cannot be posted back to Labor GL entry; otherwise,
273         *         it is empty
274         */
275        protected List<Message> isPostableForLaborGLEntry(LaborOriginEntry originEntry) {
276            List<Message> errors = new ArrayList<Message>();
277            MessageBuilder.addMessageIntoList(errors, TransactionFieldValidator.checkPostablePeridCode(originEntry, getPeriodCodesNotProcessed()));
278            MessageBuilder.addMessageIntoList(errors, TransactionFieldValidator.checkPostableBalanceTypeCode(originEntry, getBalanceTypesNotProcessed()));
279            MessageBuilder.addMessageIntoList(errors, TransactionFieldValidator.checkZeroTotalAmount(originEntry));
280            return errors;
281        }
282    
283        // construct a poster report summary object
284        protected void fillPosterReportWriter(int lineNumber, Map<String, Integer> reportSummary, Map<String, Integer> glEntryReportSummary) {
285            reportWriterService.writeStatisticLine("SEQUENTIAL RECORDS READ                    %,9d", lineNumber);
286            reportWriterService.writeStatisticLine("LLEN RECORDS INSERTED (LD_LDGR_ENTR_T)     %,9d", reportSummary.get(laborLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT));
287            reportWriterService.writeStatisticLine("LLBL RECORDS INSERTED (LD_LDGR_BAL_T)      %,9d", reportSummary.get(laborLedgerBalancePoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT));
288            reportWriterService.writeStatisticLine("LLBL RECORDS UPDATED  (LD_LDGR_BAL_T)      %,9d", reportSummary.get(laborLedgerBalancePoster.getDestinationName() + "," + KFSConstants.OperationType.UPDATE));
289            reportWriterService.writeStatisticLine("LLGL RECORDS INSERTED (LD_LBR_GL_ENTRY_T)  %,9d", glEntryReportSummary.get(laborGLLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT));
290            reportWriterService.writeStatisticLine("WARNING RECORDS WRITTEN                    %,9d", numberOfErrorOriginEntry);
291        }
292    
293        // fill the poster report writer with the collected data
294        protected Map<String, Integer> constructPosterReportSummary() {
295            Map<String, Integer> reportSummary = new HashMap<String, Integer>();
296            reportSummary.put(laborLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT, 0);
297            reportSummary.put(laborLedgerBalancePoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT, 0);
298            reportSummary.put(laborLedgerBalancePoster.getDestinationName() + "," + KFSConstants.OperationType.UPDATE, 0);
299            reportSummary.put(laborGLLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT, 0);
300            return reportSummary;
301        }
302    
303        // construct a gl entry report summary object
304        protected Map<String, Integer> constructGlEntryReportSummary() {
305            Map<String, Integer> glEntryReportSummary = new HashMap<String, Integer>();
306            glEntryReportSummary.put(ORIGN_ENTRY + "," + KFSConstants.OperationType.READ, 0);
307            glEntryReportSummary.put(ORIGN_ENTRY + "," + KFSConstants.OperationType.BYPASS, 0);
308            glEntryReportSummary.put(ORIGN_ENTRY + "," + KFSConstants.OperationType.SELECT, 0);
309            glEntryReportSummary.put(ORIGN_ENTRY + "," + KFSConstants.OperationType.REPORT_ERROR, 0);
310            glEntryReportSummary.put(laborGLLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT, 0);
311    
312            return glEntryReportSummary;
313        }
314    
315        // fill the gl entry report writer with the collected data
316        protected void fillGlEntryReportWriter(Map<String, Integer> glEntryReportSummary) {
317            laborGlEntryStatisticsReportWriterService.writeStatisticLine("NUMBER OF RECORDS READ              %,9d", glEntryReportSummary.get(ORIGN_ENTRY + "," + KFSConstants.OperationType.READ));
318            laborGlEntryStatisticsReportWriterService.writeStatisticLine("NUMBER OF RECORDS BYPASSED          %,9d", glEntryReportSummary.get(ORIGN_ENTRY + "," + KFSConstants.OperationType.BYPASS));
319            laborGlEntryStatisticsReportWriterService.writeStatisticLine("NUMBER OF RECORDS SELECTED          %,9d", glEntryReportSummary.get(ORIGN_ENTRY + "," + KFSConstants.OperationType.SELECT));
320            laborGlEntryStatisticsReportWriterService.writeStatisticLine("NUMBER OF RECORDS IN ERROR          %,9d", glEntryReportSummary.get(ORIGN_ENTRY + "," + KFSConstants.OperationType.REPORT_ERROR));
321            laborGlEntryStatisticsReportWriterService.writeStatisticLine("NUMBER OF RECORDS INSERTED          %,9d", glEntryReportSummary.get(laborGLLedgerEntryPoster.getDestinationName() + "," + KFSConstants.OperationType.INSERT));
322        }
323    
324        /**
325         * summary the valid origin entries for the General Ledger
326         * 
327         * @param laborOriginEntry the current entry to check for summarization
328         * @param laborLedgerUnitOfWork the current (in process) summarized entry for the GL
329         * @param runDate the data when the process is running
330         * @param lineNumber the line in the input file (used for error message only)
331         */
332        protected LaborOriginEntry summarizeLaborGLEntries(LaborOriginEntry laborOriginEntry, LaborLedgerUnitOfWork laborLedgerUnitOfWork, Date runDate, int lineNumber, Map<String, Integer> glEntryReportSummary) {
333            // KFSMI-5308: Description update moved here due to requirement for this to happen before consolidation
334            if(ObjectUtils.isNotNull(laborOriginEntry)) {
335                String description = laborTransactionDescriptionService.getTransactionDescription(laborOriginEntry);
336                if(StringUtils.isNotEmpty(description)) {
337                    laborOriginEntry.setTransactionLedgerEntryDescription(description);
338                }
339            }
340            
341            LaborOriginEntry summarizedEntry = null;
342            if (laborLedgerUnitOfWork.canContain(laborOriginEntry)) {
343                laborLedgerUnitOfWork.addEntryIntoUnit(laborOriginEntry);
344                updateReportSummary(glEntryReportSummary, ORIGN_ENTRY, KFSConstants.OperationType.SELECT);
345            }
346            else {
347                summarizedEntry = laborLedgerUnitOfWork.getWorkingEntry();
348                laborLedgerUnitOfWork.resetLaborLedgerUnitOfWork(laborOriginEntry);
349            }
350    
351            return summarizedEntry;
352        }
353    
354        protected void writeLaborGLEntry(LaborOriginEntry laborOriginEntry, LaborLedgerUnitOfWork laborLedgerUnitOfWork, Date runDate, int lineNumber, Map<String, Integer> glEntryReportSummary) {
355            LaborOriginEntry summarizedEntry = summarizeLaborGLEntries(laborOriginEntry, laborLedgerUnitOfWork, runDate, lineNumber, glEntryReportSummary);
356            if (summarizedEntry == null) {
357                return;
358            }
359    
360            try {
361                List<Message> errors = this.isPostableForLaborGLEntry(summarizedEntry);
362                if (errors == null || errors.isEmpty()) {
363                    String operationType = laborGLLedgerEntryPoster.post(summarizedEntry, 0, runDate, null);
364                    updateReportSummary(glEntryReportSummary, laborGLLedgerEntryPoster.getDestinationName(), operationType);
365                }
366                else {
367                    updateReportSummary(glEntryReportSummary, ORIGN_ENTRY, KFSConstants.OperationType.BYPASS);
368                }
369            }
370            catch (RuntimeException ioe) {
371                // catch here again, it should be from postSingleEntryIntoLaborLedger
372                LOG.error("postLaborGLEntries stopped due to: " + ioe.getMessage() + " on line number : " + lineNumber, ioe);
373                throw new RuntimeException("Unable to execute: " + ioe.getMessage() + " on line number : " + lineNumber, ioe);
374            }
375        }
376    
377        protected void updateReportSummary(Map<String, Integer> reportSummary, String destination, String operation) {
378            String key = destination + "," + operation;
379    
380            if (reportSummary.containsKey(key)) {
381                Integer count = reportSummary.get(key);
382                reportSummary.put(key, count + 1);
383            }
384            else {
385                reportSummary.put(key, 1);
386            }
387        }
388    
389        protected void writeErrorEntry(String line) {
390            try {
391                POSTER_OUTPUT_ERR_FILE_ps.printf("%s\n", line);
392            }
393            catch (Exception e) {
394                LOG.error("postAsProcessedOriginEntry stopped due to: " + e.getMessage(), e);
395                throw new RuntimeException("Unable to execute: " + e.getMessage(), e);
396            }
397        }
398    
399        /**
400         * Get a set of the balance type codes that are bypassed by Labor Poster
401         * 
402         * @return a set of the balance type codes that are bypassed by Labor Poster
403         */
404        public List<String> getBalanceTypesNotProcessed() {
405            return parameterService.getParameterValues(LaborPosterStep.class, Poster.BALANCE_TYPES_NOT_PROCESSED);
406        }
407    
408        /**
409         * Get a set of the fiscal period codes that are bypassed by Labor Poster
410         * 
411         * @return a set of the fiscal period codes that are bypassed by Labor Poster
412         */
413        public List<String> getPeriodCodesNotProcessed() {
414            return parameterService.getParameterValues(LaborPosterStep.class, Poster.PERIOD_CODES_NOT_PROCESSED);
415        }
416    
417        /**
418         * Sets the dateTimeService attribute value.
419         * 
420         * @param dateTimeService The dateTimeService to set.
421         */
422        public void setDateTimeService(DateTimeService dateTimeService) {
423            this.dateTimeService = dateTimeService;
424        }
425    
426    
427        /**
428         * Sets the laborLedgerBalancePoster attribute value.
429         * 
430         * @param laborLedgerBalancePoster The laborLedgerBalancePoster to set.
431         */
432        public void setLaborLedgerBalancePoster(PostTransaction laborLedgerBalancePoster) {
433            this.laborLedgerBalancePoster = laborLedgerBalancePoster;
434        }
435    
436        /**
437         * Sets the laborGLLedgerEntryPoster attribute value.
438         * 
439         * @param laborGLLedgerEntryPoster The laborGLLedgerEntryPoster to set.
440         */
441        public void setLaborGLLedgerEntryPoster(PostTransaction laborGLLedgerEntryPoster) {
442            this.laborGLLedgerEntryPoster = laborGLLedgerEntryPoster;
443        }
444    
445        /**
446         * Sets the laborLedgerEntryPoster attribute value.
447         * 
448         * @param laborLedgerEntryPoster The laborLedgerEntryPoster to set.
449         */
450        public void setLaborLedgerEntryPoster(PostTransaction laborLedgerEntryPoster) {
451            this.laborLedgerEntryPoster = laborLedgerEntryPoster;
452        }
453    
454        /**
455         * Sets the laborOriginEntryService attribute value.
456         * 
457         * @param laborOriginEntryService The laborOriginEntryService to set.
458         */
459        public void setLaborOriginEntryService(LaborOriginEntryService laborOriginEntryService) {
460            this.laborOriginEntryService = laborOriginEntryService;
461        }
462    
463        /**
464         * Sets the originEntryGroupService attribute value.
465         * 
466         * @param originEntryGroupService The originEntryGroupService to set.
467         */
468        public void setOriginEntryGroupService(OriginEntryGroupService originEntryGroupService) {
469            this.originEntryGroupService = originEntryGroupService;
470        }
471    
472        /**
473         * Sets the laborTransactionDescriptionService attribute value.
474         * @param laborTransactionDescriptionService The laborTransactionDescriptionService to set.
475         */
476        public void setLaborTransactionDescriptionService(LaborTransactionDescriptionService laborTransactionDescriptionService) {
477            this.laborTransactionDescriptionService = laborTransactionDescriptionService;
478        }
479        
480        /**
481         * Sets the reportWriterService
482         * 
483         * @param reportWriterService The reportWriterService to set.
484         */
485        public void setReportWriterService(ReportWriterService reportWriterService) {
486            this.reportWriterService = reportWriterService;
487        }
488    
489        /**
490         * Sets the errorListingReportWriterService
491         * 
492         * @param errorListingReportWriterService The errorListingReportWriterService to set.
493         */
494        public void setErrorListingReportWriterService(ReportWriterService errorListingReportWriterService) {
495            this.errorListingReportWriterService = errorListingReportWriterService;
496        }
497    
498        /**
499         * Sets the ledgerSummaryReportWriterService
500         * 
501         * @param ledgerSummaryReportWriterService The ledgerSummaryReportWriterService to set.
502         */
503        public void setLedgerSummaryReportWriterService(ReportWriterService ledgerSummaryReportWriterService) {
504            this.ledgerSummaryReportWriterService = ledgerSummaryReportWriterService;
505        }
506    
507        /**
508         * Sets the laborPosterTransactionValidator attribute value.
509         * 
510         * @param laborPosterTransactionValidator The laborPosterTransactionValidator to set.
511         */
512        public void setLaborPosterTransactionValidator(VerifyTransaction laborPosterTransactionValidator) {
513            this.laborPosterTransactionValidator = laborPosterTransactionValidator;
514        }
515    
516        /**
517         * Sets the parameterService attribute value.
518         * 
519         * @param parameterService The parameterService to set.
520         */
521        public void setParameterService(ParameterService parameterService) {
522            this.parameterService = parameterService;
523        }
524    
525        /**
526         * Sets the laborGlEntryStatisticsReportWriterService attribute value.
527         * 
528         * @param laborGlEntryStatisticsReportWriterService The laborGlEntryStatisticsReportWriterService to set.
529         */
530        public void setLaborGlEntryStatisticsReportWriterService(ReportWriterService laborGlEntryStatisticsReportWriterService) {
531            this.laborGlEntryStatisticsReportWriterService = laborGlEntryStatisticsReportWriterService;
532        }
533    
534        /**
535         * Sets the batchFileDirectoryName attribute value.
536         * 
537         * @param batchFileDirectoryName The batchFileDirectoryName to set.
538         */
539        public void setBatchFileDirectoryName(String batchFileDirectoryName) {
540            this.batchFileDirectoryName = batchFileDirectoryName;
541        }
542    }