======Serials Checkin and Pattern Maintenance - some notes====== //These is a proposed implementation at this point, serials may not necessarily work like this// Serials maintenance is handled under //subscriptions//, which is associated with a start date. {{:acq:serials:sub1.jpg|Subscription Screen}} The //cycles// that identify a pattern for a serial are defined individually, and a notes field is available for adding explanatory text if desired. {{:acq:serials:ser2.jpg|Cycles Screen}} The recurrence definition is handled as an expandable list of options, and exceptions are associated with predefined calendars. So, for example, if a library does count holidays in determining whether a serial claim is warranted, one calendar can maintain this information. Further exceptions can also be placed when the cycle is associated with a subscription. {{:acq:serials:ser3.jpg|Subscription Cycles Screen}} Any number of cycles can be associated with a subscription. A //claim delay// is used to identify the period of time to wait before initiating a claim. Addition exceptions can also be made using a calendar associated with this instance of the cycle. If a cycle is defined for a virtual resource, an option is to identify a web mechanism for checking the title's availability. Claims are identified by the //job scheduler//, which runs daily or more frequently if desired. The job scheduler uses an [[http://en.wikipedia.org/wiki/ICalendar|iCal]] rule structure. The service logic looks like: //work out permissions GenericDelegator delegator = dctx.getDelegator(); LocalDispatcher dispatcher = dctx.getDispatcher(); GenericValue userLogin = (GenericValue) context.get("userLogin"); Security security = dctx.getSecurity(); Locale locale = (Locale) context.get("locale"); if (! security.hasEntityPermission("ACCOUNTING", "_ATX_POST", userLogin)) { return ServiceUtil.returnError(UtilProperties.getMessage("FinancialsUiLabels", "FinancialsServiceErrorNoPermission", locale)); } //check patterns List transactions = null; try { List conditions = UtilMisc.toList( new EntityExpr("scheduledReceiveDate", EntityOperator.NOT_EQUAL, null), new EntityExpr("scheduledReceiveDate", EntityOperator.GREATER_THAN_EQUAL_TO, UtilDateTime.nowTimestamp()), new EntityExpr("isReceived", EntityOperator.EQUALS, "N") ); transactions = delegator.findByAnd("SerialsTrans", conditions); } catch( GenericEntityException e ) { Debug.logError(e.getMessage(), module); return ServiceUtil.returnError(e.getMessage()); } //invoke service to deal with titles due to be received Map input = UtilMisc.toMap("userLogin", userLogin); for (Iterator iter = transactions.iterator(); iter.hasNext(); ) { GenericValue transaction = (GenericValue) iter.next(); input.put("serialsTransId", transaction.get("serialsTransId")); try { Map results = dispatcher.runSync("dealWithMissedSerialsTrans", input); if (ServiceUtil.isError(results)) { Debug.logError("Failed to process SerialsTransaction ["+ transaction.get("serialsTransId")+"] due to logic error: " + ServiceUtil.getErrorMessage(results), module); } } catch( GenericServiceException e ) { Debug.logError(e, "Failed to post scheduled SerialsTransaction ["+ transaction.get("serialsTransId")+"] due to service engine error: " + e.getMessage(), module); } } return ServiceUtil.returnSuccess();