static void
fm_cust_pol_set_brandinfo(
	pcm_context_t		*ctxp,
	int32			opflags,
	pin_flist_t		*i_flistp,
	pin_flist_t		**r_flistpp,
	pin_errbuf_t		*ebufp)
{
	/*
	 * If there are pending errors, then short circuit immediately
	 */
        if (PIN_ERR_IS_ERR(ebufp))
                return;
        PIN_ERR_CLEAR_ERR(ebufp);

	/* Attempt to set the brand name */
	fm_cust_pol_set_brandname(ctxp, opflags, i_flistp, r_flistpp, ebufp);

	/* If there's no pending errors, then just use what we got */
	if(!PIN_ERR_IS_ERR(ebufp)) {
		*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
	}

	return;
}
/*******************************************************************
 * fm_price_pol_prep_dependency():
 *
 *	Prepare the given dependency flist for database insertion.
 *
 *	XXX NOOP - STUBBED PROTOTYPE ONLY XXX
 *
 *******************************************************************/
void
fm_price_pol_prep_dependency(
	pcm_context_t		*ctxp,
	u_int32			flags,
	pin_flist_t		*i_flistp,
	pin_flist_t		**o_flistpp,
        pin_errbuf_t		*ebufp)
{
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/*
	 * Copy the input to output
	 */

	*o_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);


	/*
	 * Error?
	 */
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_price_pol_prep_dependency error", ebufp);
	}

	return;
}
/*******************************************************************
 * fm_cust_pol_get_config()
 *
 *	Policy that takes the incoming flist of info contained
 *	on an srvc array and other, and adds more information and
 *	sends out the config information in big flist.
 *
 *******************************************************************/
static void
fm_cust_pol_get_config(
	pcm_context_t		*ctxp,
	pin_flist_t		*in_flistp,
	pin_flist_t		**out_flistpp,
        pin_errbuf_t		*ebufp)
{
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Copy the incoming flist.
	 ***********************************************************/
	*out_flistpp = PIN_FLIST_COPY(in_flistp, ebufp);

	/***********************************************************
	 * Add the file configed parameters.
	 ***********************************************************/
	fm_cust_pol_read_config(*out_flistpp, in_flistp, ebufp);

	/***********************************************************
	 * Error?
	 ***********************************************************/
	if(PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_cust_pol_get_config error", ebufp);
	}

	return;
}
/*******************************************************************
 * fm_bill_pol_spec_billno()
 *
 *	Prep the billno for the given bill obj.
 *
 *******************************************************************/
static void
fm_bill_pol_spec_billno(
	pcm_context_t		*ctxp,
	u_int			flags,
	pin_flist_t		*in_flistp,
	pin_flist_t		**out_flistpp,
        pin_errbuf_t		*ebufp)
{
	pin_flist_t	*b_flistp = NULL;
	poid_t		*pdp = NULL;
	void            *vp = NULL;

	int64		poid_db;
	int64		poid_id;
	char		billno[60];

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	b_flistp = PIN_FLIST_COPY(in_flistp, ebufp);

	/***********************************************************
	 * We don't need a bill_no if the bill type is subordinate.
	 ***********************************************************/
	vp = PIN_FLIST_FLD_GET(b_flistp, PIN_FLD_PAY_TYPE, 0, ebufp);

	if (vp != (void *)NULL) {
		PIN_FLIST_FLD_DROP(b_flistp, PIN_FLD_PAY_TYPE, ebufp);
	}

	/***********************************************************
	 * Set the BILL_NO field according to poid.
	 ***********************************************************/
        vp = PIN_FLIST_FLD_GET(b_flistp, PIN_FLD_BILL_NO, 1, ebufp);
	if ((vp == (void *)NULL) || (strlen((char *)vp) <= 0)) {

		pdp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, 
			PIN_FLD_POID, 0, ebufp);

		poid_db = PIN_POID_GET_DB(pdp);
		poid_id = PIN_POID_GET_ID(pdp);

		sprintf(billno, "%u.%u.%u.%u-%llu",
		(u_int)((poid_db & (u_int64)MASKUPPER) >> 48),
		(u_int)((poid_db & (u_int64)MASKSECOND) >> 32),
		(u_int)((poid_db & (u_int64)MASKTHIRD) >> 16),
		(u_int)(poid_db & (u_int64)0xFFFF), poid_id);

		PIN_FLIST_FLD_SET(b_flistp, PIN_FLD_BILL_NO, 
			(void *)billno, ebufp);
	}
/*******************************************************************
 * fm_device_pol_set_state:
 *
 *******************************************************************/
static void
fm_device_pol_set_state(
	pcm_context_t           *ctxp,
	int32                   flags,
	pin_flist_t             *i_flistp,
	pin_flist_t             **r_flistpp,
	pin_errbuf_t            *ebufp)
{

	poid_t          *dev_poidp = NULL;
	char            *poid_type = NULL;

	if (PIN_ERR_IS_ERR(ebufp)) {
		return;
	}

	PIN_ERR_CLEAR_ERR(ebufp);
	
	/*
	 * Get the old device object poid
	 */
	dev_poidp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
	
	/*
	 * Get the device poid type
	 * this poid will be used in identifiing different Devices like sim,num..
	 */
	poid_type = (char *) PIN_POID_GET_TYPE(dev_poidp);

	if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_IP) == 0) {
		/*
		 * call IP policy to do the work we want
		 */
		 PCM_OP(ctxp, PCM_OP_IP_POL_DEVICE_SET_STATE, flags, i_flistp,
			r_flistpp, ebufp);
	} else if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_APN) == 0) {
		/*
		 * call APN policy to do the work we want
		 */
		 PCM_OP(ctxp, PCM_OP_APN_POL_DEVICE_SET_STATE, flags, i_flistp,
			r_flistpp, ebufp);
	}
	else {
		/***********************************************************
		 * Prepare return flist
		 ***********************************************************/
		*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
	}

	return;
}
/*******************************************************************
 * This is the default implementation for this policy
 *******************************************************************/
static void 
fm_act_pol_pre_reauthorize(
	pcm_context_t		*ctxp,
	int32			flags,
	pin_flist_t		*i_flistp,
	pin_flist_t		**r_flistpp,
	pin_errbuf_t		*ebufp)
{
	if (PIN_ERR_IS_ERR(ebufp))
		return;

	*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);

	/********************************************************* 
	 * Errors..?
	 *********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_act_pol_pre_reauthorize error",ebufp);
	}
	
	return;
}
/*******************************************************************
 * This is the default implementation for this policy
 *******************************************************************/
static void 
fm_act_pol_post_authorize(
	pcm_context_t		*ctxp,
	int32			flags,
	pin_flist_t		*i_flistp,
	pin_flist_t		**r_flistpp,
	pin_errbuf_t		*ebufp)
{
	pin_flist_t	*rate_flistp = NULL;
	int32		elemid = 0;

	if (PIN_ERR_IS_ERR(ebufp))
		return;

	*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
	/* IF rating result is present in the output flist, drop it.
	 * By default we will drop this flist, to trim the final output flist.
         * If any of the vertical managers need this rating output, they need 
         * to customize the policy.
         */
	rate_flistp = PIN_FLIST_ELEM_GET(*r_flistpp, PIN_FLD_RESULTS,
		elemid, 1, ebufp);
	if (rate_flistp) {
		PIN_FLIST_ELEM_DROP(*r_flistpp, PIN_FLD_RESULTS, elemid, ebufp);
	}


	/********************************************************* 
	 * Errors..?
	 *********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_act_pol_post_authorize error",ebufp);
	}
	
	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_PYMT_POL_PURCHASE_DEAL operation.
 *******************************************************************/
void
op_pymt_pol_purchase_deal(
        cm_nap_connection_t	*connp,
	int32			opcode,
        int32			flags,
        pin_flist_t		*i_flistp,
        pin_flist_t		**r_flistpp,
        pin_errbuf_t		*ebufp)
{
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);
        
	/*******************************************************************
	 * Insanity check.
 	 *******************************************************************/
	if (opcode != PCM_OP_PYMT_POL_PURCHASE_DEAL) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_pymt_pol_purchase_deal bad opcode error", ebufp);
		return;
	}

	/*******************************************************************
	 * Debug: What we got.
 	 *******************************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_pymt_pol_purchase_deal input flist", i_flistp);
        
	/** Dummy Implementation for the time being **/
	*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);

	return;
}
/*******************************************************************
 * fm_cust_pol_prep_inherited()
 *
 *	Prep the inherited info to be ready for on-line registration.
 *
 *	XXX STUBBED ONLY XXX
 *
 *	We do fill in an empty service_ip substruct if one is needed. 
 *
 *******************************************************************/
static void
fm_cust_pol_prep_inherited(
	pcm_context_t		*ctxp,
	pin_flist_t		*in_flistp,
	pin_flist_t		**out_flistpp,
        pin_errbuf_t		*ebufp)
{
	pin_flist_t		*flistp = NULL;
	pin_flist_t		*sub_flistp = NULL;
	poid_t			*s_pdp = NULL;
	int32			intValue = 0;
	int32			*intp = NULL;
	char			*strp = NULL;
	const char		*s_type = NULL;

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Create outgoing flist
	 ***********************************************************/
	*out_flistpp = PIN_FLIST_COPY(in_flistp, ebufp);

	/***********************************************************
	 * Dummy up the inherited info if none provided 
	 ***********************************************************/
	s_pdp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0, ebufp);

	/**********************************************************
	 * Get the type information for quick comaparisons
	 **********************************************************/
	s_type = PIN_POID_GET_TYPE(s_pdp);

	/***********************************************************
	 * Add any mandatory "inherited_info" to the input flist. This
	 * effectively gets around the problem of missing substructs
	 * on service creations.
	 ***********************************************************/
        fm_utils_cust_add_missing_service_substructs(ctxp, *out_flistpp, ebufp);
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_cust_pol_prep_inherited ouput flist after adding missing substructs...", *out_flistpp);

	/***********************************************************
	 * Next, for any services that require special initialization,
	 * do that right here.
	 ***********************************************************/
	if ( s_type ) {
		
		if (strstr(s_type, "/service/gsm")) {
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(flistp,
				PIN_FLD_GSM_INFO, 0, ebufp);

			PIN_FLIST_FLD_SET(flistp, PIN_FLD_BEARER_SERVICE, (void *)" ",
						ebufp);
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_PRIMARY_MSISDN,
						(void *)&intValue, ebufp);
                }
	
		if ((strcmp(s_type, "/service/telco") == 0) ||
			(strncmp(s_type, "/service/telco/", 15) == 0)) {
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(flistp,
				PIN_FLD_TELCO_INFO, 0, ebufp);

			intValue = 1;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_PRIMARY_NUMBER,
				(void *)&intValue, ebufp);
        }

		if (strstr(s_type, "/service/telco/gsm") == s_type) {
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(flistp,
				PIN_FLD_TELCO_INFO, 0, ebufp);

			/*
			 * By default Primary Number flag is 0 for GSM 
			 * services, so override the value set in above
			 * generic /service/telco block.
			 */
			intValue = 0;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_PRIMARY_NUMBER,
				(void *)&intValue, ebufp);

			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(flistp,
				PIN_FLD_GSM_INFO, 0, ebufp);

			PIN_FLIST_FLD_SET(flistp, PIN_FLD_BEARER_SERVICE,
					(void *)"Bearer Service", ebufp);
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_IMEI,
					(void *)"IMEI", ebufp);
		}

		if ( !strcmp("/service/telephony", s_type ) ) { 

			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(flistp,
				PIN_FLD_SERVICE_TELEPHONY, 0, ebufp);

			intp = (int32 *)PIN_FLIST_FLD_GET(flistp, 
				PIN_FLD_MAX_ACTIVE_CALLS, 1, ebufp);
			if(intp == (int32 *)NULL) {
				/* Set "non-zero, non-blank" default values */
				intValue = 1;  /* Default Max Active Calls */
				PIN_FLIST_FLD_SET(flistp, PIN_FLD_MAX_ACTIVE_CALLS, 
						(void*)&intValue, ebufp);

			}

		}
	
		if ( !strcmp( "/service/ip/cable/teracomm", s_type ) ) {
			int32		zero = 0;
			int32		init_led_status;
	
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			sub_flistp = PIN_FLIST_SUBSTR_GET(flistp, 
				PIN_FLD_SERVICE_IP_CABLE, 0, ebufp);
			/*
		 	 * Set PIN_FLD_MODEM_MAC_ADDR and the bandwidth limit
		 	 * fields to known initial values, so that dm_teracomm
		 	 * can determine whether provisioning fields are set.
		 	 * The initial value for PIN_FLD_MODEM_MAC_ADDR is not
		 	 * a valid address (valid addresses are 12 hex. chars.).
		 	 */
			strp = (char *)PIN_FLIST_FLD_GET(sub_flistp, 
				PIN_FLD_MODEM_MAC_ADDR, 1, ebufp);
			if(strp == (char *)NULL) {
				PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MODEM_MAC_ADDR,
					(void *)PIN_TERACOMM_UNSPECIFIED_MODEM_MAC_ADDR,
					ebufp);
			}
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MIN_DOWNSTREAM_BANDWD,
					(void *)&zero, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MAX_DOWNSTREAM_BANDWD,
					(void *)&zero, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MIN_UPSTREAM_BANDWD,
					(void *)&zero, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MAX_UPSTREAM_BANDWD,
					(void *)&zero, ebufp);
	
			/* 
		 	 * Initialize fields in /service/ip/cable/teracomm substruct.
		 	 */
			sub_flistp = PIN_FLIST_SUBSTR_GET(flistp, 
					PIN_FLD_SERVICE_IP_CABLE_TERACOMM, 0, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_IP_LIMIT,
					(void *)&zero, ebufp);
			init_led_status = PIN_TERACOMM_LED_STATUS_OFF;
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_LED_STATUS,
					(void *)&init_led_status, ebufp);
			strp = (char *)PIN_FLIST_FLD_GET(sub_flistp, 
					PIN_FLD_TERALINK_NAME, 1, ebufp);
			if(strp == (char *)NULL) {
				PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_TERALINK_NAME,
					(void *)"", ebufp);
			}
			strp = (char *)PIN_FLIST_FLD_GET(sub_flistp, 
					PIN_FLD_ASSOC_NETWORK, 1, ebufp);
			if(strp == (char *)NULL) {
				PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_ASSOC_NETWORK,
					(void *)"", ebufp);
			}
		}
	
		if ( !strcmp(PIN_MSEXCHANGE_SERVICE_TYPE_USER, s_type ) ) {
			char 		*int_str = "";
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			sub_flistp = PIN_FLIST_SUBSTR_GET(flistp, 
				PIN_FLD_SERVICE_MSEXCHANGE_USER, 0, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_ORG_UNIT_NAME,
					(void *)int_str, ebufp);
		}
		if ( !strcmp( PIN_MSEXCHANGE_SERVICE_TYPE_FIRSTADMIN, s_type ) ){
			int32		int_value = PIN_MSEXCHANGE_INIT_STATE_INT_VALUE;
			char 		*int_str = "";
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			sub_flistp = PIN_FLIST_SUBSTR_GET(flistp, 
				PIN_FLD_SERVICE_MSEXCHANGE_USER, 0, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_ORG_UNIT_NAME,
					(void *)int_str, ebufp);
			flistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
				PIN_FLD_INHERITED_INFO, 0, ebufp);
			sub_flistp = PIN_FLIST_SUBSTR_GET(flistp, 
				PIN_FLD_SERVICE_MSEXCHANGE_ORG, 0, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_ORG_DISPLAY_NAME,
					(void *)int_str, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_SMTP_DOMAIN_NAME,
					(void *)int_str, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_MAX_USER_COUNT,
					(void *)&int_value, ebufp);
			PIN_FLIST_FLD_SET(sub_flistp, PIN_FLD_DEFAULT_MAX_MBOX_SIZE,
					(void *)&int_value, ebufp);
		}
	}

	/***********************************************************
	 * Error?
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_cust_pol_prep_inherited error", ebufp);
	}

	return;
}
/*******************************************************************
 * fm_cust_pol_prep_profile()
 *
 *      Prep the profile info to be ready for storage.
 *
 *      XXX STUBBED ONLY XXX
 *
 *******************************************************************/
static void
fm_cust_pol_prep_profile(
        pcm_context_t           *ctxp,
        pin_flist_t             *in_flistp,
        pin_flist_t             **out_flistpp,
        pin_errbuf_t            *ebufp)
{
        pin_flist_t             *flistp = NULL;
        poid_t                  *s_pdp = NULL;
 
        if (PIN_ERR_IS_ERR(ebufp))
                return;
        PIN_ERR_CLEAR_ERR(ebufp);
 
        /***********************************************************
         * Create outgoing flist
         ***********************************************************/
        *out_flistpp = PIN_FLIST_COPY(in_flistp, ebufp);
 
#ifdef EXAMPLE_USE

        /***********************************************************
         * Dummy up the ip inherited info in none provided
         ***********************************************************/
        s_pdp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0, ebufp);
 
        /*
         * XXX - this is the place where any customer sites could plug
         * in any preperatory profile specific information. Note that the
         * POID at this point is:
         *
         *      * A "type only" poid if the profile object is about to
         *        be created.
         *
         *      * A "real" poid if the profile object is being modified.
         */
 
        /*
         * One prep example might be to name the object that is
         * being created. Do this only on create.
         */
        if(PIN_POID_IS_TYPE_ONLY(s_pdp)) {
                pin_flist_t     *sublistp;
 
                sublistp = PIN_FLIST_SUBSTR_GET(*out_flistpp,
                        PIN_FLD_INHERITED_INFO, 1, ebufp);
                if(sublistp == (pin_flist_t *)NULL) {
                        sublistp = PIN_FLIST_SUBSTR_ADD(*out_flistpp,
                                PIN_FLD_INHERITED_INFO, ebufp);
                }
 
                PIN_FLIST_FLD_SET(sublistp, PIN_FLD_NAME,
                        (void *)"Example Name", ebufp);
        }
#endif

        /***********************************************************
         * Error?
         ***********************************************************/
        if (PIN_ERR_IS_ERR(ebufp)) {
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                        "fm_cust_pol_prep_profile error", ebufp);
        }
 
        return;
}
/********************************************************************
 * Function : fm_cust_pol_prep_topup
 * Description : This function will prepare the input flist for the
 *               Standards as well as the Sponsored topup.
 ********************************************************************/
static void fm_cust_pol_prep_topup(
        pcm_context_t           *ctxp,
        int32                   flags,
        pin_flist_t             *i_flistp,
        pin_flist_t             **r_flistpp,
        pin_errbuf_t            *ebufp)
{
    int    createonly =    0;
    int    status     =    0;
    int    index      =    0;
    int    sponsore_topup = 0;
    void    *vp       =    NULL;

    
    pin_flist_t    *intopup_flistp        =    NULL;
    pin_flist_t    *outtopup_flistp       =    NULL;
    pin_flist_t    *ingrptopupmem_flistp  =    NULL;
    pin_flist_t    *outgrptopupmem_flistp =    NULL;
    pin_flist_t    *grptopup_flistp       =    NULL;
    pin_flist_t    *ingrptopup_flistp     =    NULL;
    pin_flist_t    *outgrptopup_flistp    =    NULL;
    pin_flist_t    *r_flistp              =    NULL;

    poid_t    *intopup_pdp   =    NULL;
    poid_t    *inparent_pdp  =    NULL;
    poid_t    *initiator_pdp =    NULL;
    poid_t    *grp_pdp       =    NULL;
    poid_t    *tmp_pdp       =    NULL;
    
    
    if (PIN_ERR_IS_ERR(ebufp))
            return;
    PIN_ERR_CLEAR_ERR(ebufp);
    /****************************************************************
     * Get the PIN_FLD_TOPUP_INFO from the input flist.
     * Value available in the input flist this function construct the 
     * output flist.
     *****************************************************************/
    intopup_flistp = PIN_FLIST_ELEM_GET(i_flistp, PIN_FLD_TOPUP_INFO,
                                                         PIN_ELEMID_ANY, 0, ebufp); 

    /****************************************************************
     * Just copy the input flist to the retflist.If any change is required
     * for the flist we will manipulate the output flist.
     ****************************************************************/

    *r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
        
    /****************************************************************
     * First check requires the POID and PARENT poid from the input 
     * flist. From this we check whether the call is to
     * create the standard topup or the sponsored topup.
     ****************************************************************/
    intopup_pdp = (poid_t *)PIN_FLIST_FLD_GET(intopup_flistp, PIN_FLD_POID, 0, ebufp);
    inparent_pdp = (poid_t *)PIN_FLIST_FLD_GET(intopup_flistp,  PIN_FLD_PARENT, 1, ebufp);
        
    /****************************************************************
     * check the topup poid is just type only or not.
     ****************************************************************/
    if( PIN_POID_IS_TYPE_ONLY(intopup_pdp) )
    { 
        /****************************************************************
         * topup poid is just type only i,e. 0.0.0.x /topup -1 1
	 ****************************************************************/
        if( PIN_POID_IS_NULL(inparent_pdp) )
        {
            fm_cust_pol_prep_create_standard_topup(ctxp, flags, i_flistp, r_flistpp, ebufp);
            return;
        }
        else
        {
            createonly = 1;
            sponsore_topup = 1;
            fm_cust_pol_prep_create_sponsored_topup(ctxp, flags, i_flistp, r_flistpp, ebufp);
        }
    }
    else
    {
        /****************************************************************
         * The input flist contains the valid topup poid.
         ****************************************************************/

        /****************************************************************
         * Now read PIN_FLD_GROUP_OBJ and PIN_FLD_GROUP_INDEX from 
         * the /topup object 
         ****************************************************************/

        grptopup_flistp = PIN_FLIST_CREATE(ebufp);
        tmp_pdp = PIN_POID_COPY( intopup_pdp, ebufp);
        PIN_FLIST_FLD_PUT(grptopup_flistp, PIN_FLD_POID, tmp_pdp, ebufp);
        /****************************************************************
         * setting the group dummy group poid and group index
         ****************************************************************/
        PIN_FLIST_FLD_SET(grptopup_flistp, PIN_FLD_GROUP_OBJ, tmp_pdp, ebufp);
        PIN_FLIST_FLD_SET(grptopup_flistp, PIN_FLD_GROUP_INDEX, (void *) &index, ebufp);

        PCM_OP(ctxp, PCM_OP_READ_FLDS, flags, grptopup_flistp, &r_flistp, ebufp);


        /****************************************************************
         * Now get the group object from the return flist.
         ****************************************************************/
        grp_pdp = (poid_t *)PIN_FLIST_FLD_GET(r_flistp, PIN_FLD_GROUP_OBJ, 1, ebufp);

        /****************************************************************
         * check whethere the poid is null or not.
         ****************************************************************/
        if( PIN_POID_IS_NULL(grp_pdp) )
        {
            if( PIN_POID_IS_NULL(inparent_pdp) )  
            {
                /****************************************************************
                 * Since the input flist does not contains the PARENT and
                 * specefied the topup object does not have the GROUP_OBJ
                 * it hase to prepare the flist for the modification
                 * standard topup.
                 ****************************************************************/
                fm_cust_pol_prep_modify_standard_topup(ctxp, flags, i_flistp, r_flistpp, ebufp);
                return ;
            }
            else
            {
                /****************************************************************
                 * Input flist have the PARENT poid and the topup object does not  have the
                 * valid group poid, hence prepare the flist to create the 
                 * sponsored topup.
                 * This case if for a account holder having the standard topup
                 * is being added to PARENts some group.
                 ****************************************************************/

                createonly = 1;
                sponsore_topup = 1;
                fm_cust_pol_prep_create_sponsored_topup(ctxp, flags, i_flistp, r_flistpp, ebufp);
            }
        }
        else
        {
            /****************************************************************
             * The topup object is having the  valid group poid.
             * Hence prepare the flistp for modifing the sponsored topup.
             ****************************************************************/
            sponsore_topup = 1;
            fm_cust_pol_prep_modify_sponsored_topup(ctxp, flags, i_flistp, r_flistpp, ebufp);
        }
        PIN_FLIST_DESTROY_EX(&grptopup_flistp, NULL);
        PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
    }

    /****************************************************************
     * Check whethere we are preparing the flist for standard or
     * sponsored topup. Becuse we have to continue exution for 
     * for sponsored topup.
     ****************************************************************/
    if( sponsore_topup )
    {
        initiator_pdp = (poid_t *)PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
        outtopup_flistp = PIN_FLIST_ELEM_GET(*r_flistpp, PIN_FLD_TOPUP_INFO,
                                                 PIN_ELEMID_ANY, 0, ebufp);

        outgrptopup_flistp = PIN_FLIST_ELEM_GET(outtopup_flistp, PIN_FLD_GROUP_TOPUP_INFO,
                                                 PIN_ELEMID_ANY, 0, ebufp);
        outgrptopupmem_flistp = PIN_FLIST_ELEM_GET(outgrptopup_flistp, PIN_FLD_GROUP_TOPUP_MEMBERS,
                                                PIN_ELEMID_ANY, 0, ebufp);

        /****************************************************************
         * Check who is the intiatore of the operation.
         ****************************************************************/
        if( !PIN_POID_COMPARE( inparent_pdp, initiator_pdp , 0, ebufp) )
        {
            /****************************************************************
             * Initiatore is the payers.
             ****************************************************************/
            ingrptopup_flistp = PIN_FLIST_ELEM_GET(intopup_flistp, PIN_FLD_GROUP_TOPUP_INFO,
                                            PIN_ELEMID_ANY, 0, ebufp);
            ingrptopupmem_flistp = PIN_FLIST_ELEM_GET(ingrptopup_flistp, PIN_FLD_GROUP_TOPUP_MEMBERS,
                                            PIN_ELEMID_ANY, 0, ebufp);

            /****************************************************************
             * If the STATUS is not set set it to ACTIVE.
             ****************************************************************/
            vp = PIN_FLIST_FLD_GET(ingrptopupmem_flistp, PIN_FLD_STATUS, 1, ebufp);

            if( vp == NULL )
            {
                status = PIN_STATUS_ACTIVE;
                PIN_FLIST_FLD_SET(outgrptopupmem_flistp, PIN_FLD_STATUS, &status, ebufp);
            }

            /****************************************************************
             * If the opcode is creating the sponsored topup and the group 
             * name is not set it to default.
             ****************************************************************/
            if( createonly )
            {
                vp = PIN_FLIST_FLD_GET(ingrptopup_flistp, PIN_FLD_NAME, 1, ebufp);
                if( vp == NULL )
                {
                    PIN_FLIST_FLD_SET(outgrptopup_flistp, PIN_FLD_NAME, (void *)"default", ebufp);
                }
            }
        }
        else
        {
            /****************************************************************
             * Initiatore is member account. Set the PIN to NULL and
             * STATUS is INACTIVE.
             ****************************************************************/
            status = PIN_STATUS_INACTIVE;
            PIN_FLIST_FLD_SET(outgrptopupmem_flistp, PIN_FLD_STATUS, &status, ebufp);
            PIN_FLIST_FLD_SET(outgrptopupmem_flistp, PIN_FLD_PIN, (void *)"", ebufp);
        }
    }
    if (PIN_ERR_IS_ERR(ebufp))
              PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                               "fm_cust_pol_prep_topup error",
                                 ebufp);

    return;
}
/*******************************************************************
 * Main routine for the PCM_OP_PYMT_POL_PRE_COLLECT  command
 *******************************************************************/
void
op_pymt_pol_pre_collect(
	cm_nap_connection_t	*connp,
	int			opcode,
	int			flags,
	pin_flist_t		*in_flistp,
	pin_flist_t		**ret_flistpp,
	pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_cookie_t		cookie = NULL;
	pin_flist_t		*flistp = NULL;
	pin_flist_t		*c_flistp = NULL;
	pin_flist_t		*chkpt_flistp = NULL;
	pin_flist_t		*rc_flistp = NULL;
	pin_charge_cmd_t	*cmdp = NULL;
	pin_decimal_t		*amtp = NULL;
	poid_t			*a_pdp = NULL;
	double			*d_ptr = NULL;
	char			*descr = NULL;
	int32			*selectp = NULL;
	int32			elemid = 0;
	int32			result = 0;
	int32			err = 0;
	int32			flag = 0;
	int32			sflag = 0;
	int32			rec_id = 0;
	pin_decimal_t		*minimum_pay = NULL;
	pin_decimal_t		*minimum_ref = NULL;
	pin_flist_t		*s_flistp = NULL;
	pin_flist_t		*a_flistp = NULL;
	pin_flist_t		*b_flistp = NULL;
	pin_flist_t		*r_flistp = NULL;
	poid_t			*s_pdp	  = NULL;	  
	int32			*mandate_status = 0;
	pin_pymt_result_t	*statusp = NULL;
	int32			*resultp  = NULL;
	char                    vendor_name[256] = {" "};
 	void                    *vp = NULL;
	char			*dd_vendorp = NULL;
	
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Null out results until we have some.
	 ***********************************************************/
	*ret_flistpp = (pin_flist_t *)NULL;

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_PYMT_POL_PRE_COLLECT) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"bad opcode in op_pymt_pol_pre_collect", ebufp);
		return;
	}

	/***********************************************************
	 * Debug: What did we get?
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_pymt_pol_pre_collect input flist", in_flistp);

	/***********************************************************
	 * Get command from very first element of array
	 * note: we cannot rely that it has index [0] or [1] or ...
	 ***********************************************************/
	flistp = PIN_FLIST_ELEM_GET_NEXT(in_flistp, PIN_FLD_CHARGES, 
					&elemid, 0, &cookie, ebufp);

	cmdp = (pin_charge_cmd_t *)PIN_FLIST_FLD_GET(flistp,
					PIN_FLD_COMMAND, 0, ebufp);
	



	/***********************************************************
	 * Select the list of outstanding checkpoint events.
	 * Checkpoints' existance has sense for following commands only: 
	 * authorization, deposit, conditional deposit and refund
	 ***********************************************************/
	if (cmdp && 
		((*cmdp == PIN_CHARGE_CMD_CONDITION) ||
		 (*cmdp == PIN_CHARGE_CMD_REFUND) ||
		 (*cmdp == PIN_CHARGE_CMD_AUTH_ONLY) ||
		 (*cmdp == PIN_CHARGE_CMD_DEPOSIT))) {
		/***********************************************************
		 * New algorithm is to search for checkpoint upfront and
		 * pass a flag that indicates that search is done
		 ***********************************************************/
		pin_flist_t		*b_flistp = NULL;
		int32			*b_flags = 0;

		/***********************************************************
		 * Get checkpoints' flag from very first element of array
		 * note: we cannot rely that it has index [0] or [1] or ...
		 ***********************************************************/
		elemid = 0;
		cookie = NULL;
		b_flistp = PIN_FLIST_ELEM_GET_NEXT(in_flistp,PIN_FLD_BATCH_INFO,
						   &elemid, 1, &cookie, ebufp);

		if (b_flistp != 0) {
			b_flags = (int32*)PIN_FLIST_FLD_GET(b_flistp,
						PIN_FLD_STATUS_FLAGS, 1, ebufp);
		}

		/***********************************************************
		 * 1. If no flags do checkpoints selection
		 * 2. If flag is not set do checkpoint selection
		 * 3. If flag is set don't perform checkpoint selection
		 ***********************************************************/
		if(!((b_flags != 0)&&(*b_flags & PIN_PAYMENT_BATCH_CHKPTS))){
			fm_pymt_pol_find_outstanding_chkpts(ctxp, in_flistp, 
							&chkpt_flistp, ebufp);
		}
	}

	/***********************************************************
	 * Get the minimum charge amount from the pin.conf. If the
	 * entry is missing from the pin.conf assume the default
	 * minimum value of 2.00
	 ***********************************************************/
	pin_conf("fm_pymt_pol", "minimum_payment", PIN_FLDT_NUM, 
		(caddr_t *)&d_ptr, &err);
	if (d_ptr) {
		minimum_pay = pbo_decimal_from_double(*d_ptr, ebufp);
		free(d_ptr);
        } else {
		minimum_pay = pbo_decimal_from_str("2.00", ebufp);
        }

	/***********************************************************
	 * Get the minimum refund amount from the pin.conf. If the
	 * entry is missing from the pin.conf assume the default
	 * minimum value of -2.00
	 ***********************************************************/
	pin_conf("fm_pymt_pol", "minimum_refund", PIN_FLDT_NUM, 
			(caddr_t *)&d_ptr, &err);
	if (d_ptr) {
		minimum_ref = pbo_decimal_from_double(*d_ptr, ebufp);
		free(d_ptr);
        } else {
		minimum_ref = pbo_decimal_from_str("2.00", ebufp);
	}

	/***********************************************************
	 * Get the dd_vendor value from the pin.conf. 
	 ***********************************************************/
	pin_conf("cm", "dd_vendor", PIN_FLDT_STR, 
			(caddr_t *)&dd_vendorp, &err);

	c_flistp = PIN_FLIST_COPY(in_flistp, ebufp);

	/***********************************************************
	 * Walk the charges array and check each element.
	 ***********************************************************/
	elemid = 0;
	cookie = NULL;

	while ((flistp = PIN_FLIST_ELEM_GET_NEXT(c_flistp, PIN_FLD_CHARGES,
		&elemid, 1, &cookie, ebufp)) != (pin_flist_t *)NULL) {

		statusp = (pin_pymt_result_t *) PIN_FLIST_FLD_GET(flistp,
				PIN_FLD_STATUS, 1, ebufp);
		resultp = (int32 *) PIN_FLIST_FLD_GET(flistp,PIN_FLD_RESULT, 1, ebufp);
                if((statusp && *statusp >= PIN_PYMT_SUSPENSE 
				&& *statusp < PIN_PYMT_FAILED) 
			|| (resultp && *resultp == PIN_PAYMENT_RES_FAIL)){
			/*******************************************
			 * Do nothing if a payment in suspense
			 *******************************************/
			continue;
		}

		amtp = (pin_decimal_t *)PIN_FLIST_FLD_GET(flistp, 
			PIN_FLD_AMOUNT, 1, ebufp);
		cmdp = (pin_charge_cmd_t *)PIN_FLIST_FLD_GET(flistp,
			PIN_FLD_COMMAND, 0, ebufp);
		a_pdp = (poid_t *)PIN_FLIST_FLD_GET(flistp, 
			PIN_FLD_ACCOUNT_OBJ,0,ebufp);
		selectp = (int *)PIN_FLIST_FLD_GET(flistp,
			PIN_FLD_SELECT_RESULT, 1, ebufp);

		/***************************************************
		 * Did PCM_OP_PYMT_SELECT_ITEMS retured OK?
		 ***************************************************/
		if (selectp && (*selectp != PIN_SELECT_RESULT_PASS)){
			result = PIN_CHARGE_RES_FAIL_SELECT_ITEMS;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
				(void *)&result, ebufp);

			descr = "Select Items Failed";
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
				(void *)descr, ebufp);

			continue;
		}

		/***************************************************
		 * Get the amount for this charge. If the amount to
		 * be charged is 0.0, then don't even bother dealing
		 * with this element.
		 ***************************************************/
		if ((amtp && 
			pbo_decimal_compare(amtp, minimum_pay, ebufp) < 0) &&
			 (cmdp &&  ((*cmdp == PIN_CHARGE_CMD_CONDITION) ||
			(*cmdp == PIN_CHARGE_CMD_AUTH_ONLY) ||
			(*cmdp == PIN_CHARGE_CMD_DEPOSIT)))) {
			result = PIN_CHARGE_RES_FAIL_NO_MIN;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
				(void *)&result, ebufp);

			descr = "Below Minimum";
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
				(void *)descr, ebufp);

			continue;
		}

		/***************************************************
		 * Set the minimum refund to compare.
		 ***************************************************/
		if (cmdp && ((*cmdp == PIN_CHARGE_CMD_NONE) &&
			(pbo_decimal_sign(amtp, ebufp) < 0))) {

			pbo_decimal_negate_assign(minimum_ref, ebufp);
		}

		/***************************************************
		 * If command and amount are not NULL and if the
		 * command is refund or if the commnd is none, but
		 * has a negative amount, check the amount with
		 * the minimum refund. 
		 ***************************************************/
		if (cmdp && amtp && (((*cmdp == PIN_CHARGE_CMD_REFUND) &&
			(pbo_decimal_compare(amtp, minimum_ref, ebufp) < 0)) ||
			((*cmdp == PIN_CHARGE_CMD_NONE) && 
			(pbo_decimal_sign(amtp, ebufp) < 0) &&
			(pbo_decimal_compare(amtp, minimum_ref, ebufp) > 0)))) {

			result = PIN_CHARGE_RES_FAIL_NO_MIN;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
					(void *)&result, ebufp);

			descr = "Below Minimum";
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
					(void *)descr, ebufp);

			continue;
		}

		/***************************************************
		 * If command and amount are not NULL and if the
		 * command is REFUND or if the command is NONE and
		 * its a negative amount, make sure that the account
		 * has sufficient credit balance. If not, set the 
		 * RESULT code to be NO_CREDIT_BALANCE.
		 ***************************************************/
		if (cmdp && amtp && ((*cmdp == PIN_CHARGE_CMD_REFUND) ||
			((*cmdp == PIN_CHARGE_CMD_NONE) && 
			(pbo_decimal_sign(amtp, ebufp) < 0)))) {

			flag = fm_pymt_pol_pre_collect_validate_refund(ctxp,
					amtp, flistp, ebufp);
			if (flag == PIN_BOOLEAN_FALSE) {

				result = PIN_CHARGE_RES_NO_CREDIT_BALANCE;
				PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
						(void *)&result, ebufp);

				descr = "No credit available";
				PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
						(void *)descr, ebufp);
			}
		}

		/***************************************************
		 * Is there a outstanding checkpoint for this acct?
		 ***************************************************/
		if ((chkpt_flistp != (pin_flist_t *)NULL) && cmdp &&
			((*cmdp == PIN_CHARGE_CMD_CONDITION) ||
			(*cmdp == PIN_CHARGE_CMD_REFUND) ||
			(*cmdp == PIN_CHARGE_CMD_AUTH_ONLY) ||
			(*cmdp == PIN_CHARGE_CMD_DEPOSIT))) {

			if (fm_pymt_pol_is_chkpt_outstanding(a_pdp,
				chkpt_flistp, ebufp)) {

				result = PIN_CHARGE_RES_CHECKPOINT;
				PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
					(void *)&result, ebufp);

				descr = "Checkpoint Outstanding";
				PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
					(void *)descr, ebufp);

				continue;
			}
		}
		s_flistp = PIN_FLIST_CREATE(ebufp);
		vp = PIN_FLIST_FLD_GET(flistp, PIN_FLD_ACH, 1, ebufp);
		if (vp) {
			vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0,
								 ebufp);
			PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_POID, 
						vp, ebufp);
			vp = PIN_FLIST_FLD_GET(flistp, PIN_FLD_ACH, 0,
                                                                 ebufp);	
			if (vp) {
				rec_id = *(int32 *)vp;
			}
			PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_ACH, 
						&rec_id, ebufp);

		        PCM_OP(ctxp, PCM_OP_PYMT_GET_ACH_INFO, sflag,
					s_flistp, &r_flistp, ebufp);

			rc_flistp = PIN_FLIST_ELEM_GET(r_flistp, PIN_FLD_RESULTS,
								 0, 0, ebufp);
			vp = PIN_FLIST_FLD_GET(rc_flistp,
       		                 		PIN_FLD_NAME, 0, ebufp);
			memset(vendor_name, 0, sizeof(vendor_name));
			if ((vp != (void *)NULL) && strlen(vp)) {
				strcpy(vendor_name, (char *)vp);
			}
		}
		 PIN_FLIST_DESTROY_EX(&s_flistp, NULL);
                 PIN_FLIST_DESTROY_EX(&r_flistp, NULL);

		/*************************************************************
		 * If Bertelsmann then check the mandate status.
		 *************************************************************/
		if (dd_vendorp && !strcasecmp(dd_vendorp,
			"Bertelsmann") && cmdp && *cmdp != PIN_CHARGE_CMD_RFR 
			&& vendor_name && !strcasecmp(vendor_name, 
			"bertelsmann")) {

			s_flistp = PIN_FLIST_CREATE(ebufp);
			s_pdp = PIN_POID_CREATE(PIN_POID_GET_DB(a_pdp),
				"/search/pin", 0, ebufp);
			PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_POID, 
						(void *)s_pdp, ebufp);
			PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_FLAGS, 
						(void *)&sflag, ebufp);
		
			PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_TEMPLATE, 
				"select X from /payinfo where F1 = V1 ", ebufp);

			a_flistp = PIN_FLIST_ELEM_ADD(s_flistp, PIN_FLD_ARGS, 
								1, ebufp);
			PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_ACCOUNT_OBJ, 
								a_pdp, ebufp);

			a_flistp = PIN_FLIST_ELEM_ADD(s_flistp, 
						PIN_FLD_RESULTS, 0, ebufp);
			b_flistp = PIN_FLIST_ELEM_ADD(a_flistp, 
						PIN_FLD_DD_INFO, 0, ebufp);
			PIN_FLIST_FLD_SET(b_flistp, PIN_FLD_MANDATE_STATUS, 
							(void *)0, ebufp);
			
			PCM_OP(ctxp, PCM_OP_SEARCH, 0, s_flistp, &r_flistp, 
									ebufp);

			if (r_flistp != (pin_flist_t *)NULL) {
				a_flistp = PIN_FLIST_ELEM_GET(r_flistp, 
						PIN_FLD_RESULTS, 0, 1, ebufp);
				b_flistp = PIN_FLIST_ELEM_GET(a_flistp, 
						PIN_FLD_DD_INFO, 0, 1, ebufp);

				/***********************************************
			 	* Do not allow accounts with the following
			 	* mandate_statuses to go to collection.
			 	***********************************************/
				mandate_status = PIN_FLIST_FLD_GET(b_flistp, 
						PIN_FLD_MANDATE_STATUS, 1, ebufp);
			
				if (!mandate_status || 
				   ((*mandate_status != PIN_MANDATE_RECEIVED) &&
				   (*mandate_status != PIN_MANDATE_NOT_REQUIRED)))
				{
					result = PIN_CHARGE_RES_FAIL_SELECT_ITEMS;
					PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
						(void *)&result, ebufp);

					descr = "Mandate Outstanding";
					PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
						(void *)descr, ebufp);
				}
			}

			/***********************************************
			 * Clean up.
			 ***********************************************/
			PIN_FLIST_DESTROY_EX(&s_flistp, NULL);
			PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
		}

		/***************************************************
		 * Check the command for this element.
		 ***************************************************/
		if (cmdp == NULL) {
			pin_set_err(ebufp, PIN_ERRLOC_FM,
				PIN_ERRCLASS_APPLICATION, 
				PIN_ERR_MISSING_ARG,
				PIN_FLD_COMMAND, elemid, 0);

			continue;
		}

		/***************************************************
		 * Is it ok?
		 ***************************************************/

		switch (*cmdp) {
		case PIN_CHARGE_CMD_NONE:
		case PIN_CHARGE_CMD_AUTH_ONLY:
		case PIN_CHARGE_CMD_CONDITION:
		case PIN_CHARGE_CMD_DEPOSIT:
		case PIN_CHARGE_CMD_REFUND:
		case PIN_CHARGE_CMD_RFR:
		case PIN_CHARGE_CMD_RESUBMIT:
			break;
		default:
			result = PIN_CHARGE_RES_INVALID_CMD;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_RESULT, 
				(void *)&result, ebufp);

			descr = "Invalid Command";
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_DESCR, 
				(void *)descr, ebufp);
		}
	}

	/***********************************************************
	 * Clean up.
	 ***********************************************************/
	PIN_FLIST_DESTROY_EX(&chkpt_flistp, NULL);
	pbo_decimal_destroy(&minimum_pay);
	pbo_decimal_destroy(&minimum_ref);

	if (dd_vendorp != (char *)NULL) {
		free(dd_vendorp);
		dd_vendorp = NULL;
	}

	/***********************************************************
	 * Results.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_FLIST_DESTROY_EX(&c_flistp, NULL);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_pymt_pol_pre_collect error", ebufp);
	} else {
		*ret_flistpp = c_flistp;
		PIN_ERR_CLEAR_ERR(ebufp);
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_pymt_pol_pre_collect return flist", 
			*ret_flistpp);
	}

	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_TRANS_POL_COMMIT operation.
 *******************************************************************/
void
op_trans_pol_commit(
	cm_nap_connection_t	*connp,
	u_int			opcode,
	u_int			flags,
	pin_flist_t		*i_flistp,
	pin_flist_t		**o_flistpp,
	pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;


	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/*
	 * Insanity check.
	 */
	if (opcode != PCM_OP_TRANS_POL_COMMIT) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_trans_pol_commit opcode error", ebufp);
		return;
	}

	/*
	 * Debug: What we got.
	 */
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_trans_pol_commit input flist", i_flistp);

	/*
	 * Do the actual op.
	 */

	/*
	 * NOTE: The following call is for EAI framework.  Don't delete.
	 * Send commit to publisher if publish is enabled.
	 */
	fm_utils_publish_transaction_state(connp, opcode, i_flistp, ebufp);

	/*
	 * NOTE: The following call is for service order provisioning.
	 * Don't delete. Send commit to publisher.
	 */
	fm_utils_prov_txn_op(connp, opcode, i_flistp, ebufp);


	/*
	 * For now, just pass along a copy of the input flist
	 * (ie, it will continue to be the current transaction flist).
	 */
	*o_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);

	/*
	 * Error?
	 */
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_trans_pol_commit error", ebufp);
	} else {
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_trans_pol_commit return flist", *o_flistpp);
	}

}
/*******************************************************************
 * Main routine for the PCM_OP_SUBSCRIPTION_POL_COUNT_LINES operation.
 *******************************************************************/
void
op_subscription_pol_count_lines(
        cm_nap_connection_t	*connp,
	int32			opcode,
        int32			flags,
        pin_flist_t		*i_flistp,
        pin_flist_t		**o_flistpp,
        pin_errbuf_t		*ebufp)
{
	pcm_context_t		*ctxp = connp->dm_ctx;
	pin_flist_t		*r_flistp = NULL;

	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_SUBSCRIPTION_POL_COUNT_LINES) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_subscription_pol_count_lines opcode error", ebufp);
		return;
	}

	/***********************************************************
	 * Debug: What we got.
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_subscription_pol_count_lines input flist", i_flistp);

	/***********************************************************
	 * Prep the return flist.
	 ***********************************************************/
	r_flistp = PIN_FLIST_COPY(i_flistp, ebufp);


	/***********************************************************
	 * Results.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {

		/***************************************************
		 * Log something and return nothing.
		 ***************************************************/
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_subscription_pol_count_lines error", ebufp);
		PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
		*o_flistpp = NULL;

	} else {

		/***************************************************
		 * Point the real return flist to the right thing.
		 ***************************************************/
		PIN_ERR_CLEAR_ERR(ebufp);
		*o_flistpp = r_flistp;

		/***************************************************
		 * Debug: What we're sending back.
		 ***************************************************/
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_subscription_pol_count_lines return flist", 
		r_flistp);

	}

	return;
}
/*******************************************************************
 * fm_device_pol_create:
 *
 *******************************************************************/
static void
fm_device_pol_create(
	pcm_context_t           *ctxp,
	int32                   flags,
	pin_flist_t             *i_flistp,
	pin_flist_t             **r_flistpp,
	pin_errbuf_t            *ebufp)
{

	poid_t          *dev_poidp = NULL;
	char            *poid_type = NULL;

	if (PIN_ERR_IS_ERR(ebufp)) {
		return;
	}
	PIN_ERR_CLEAR_ERR(ebufp);
	
	/*
	 * Get the device poid
	 */
	dev_poidp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
	
	/*
	 * Get the device poid type
	 */
	poid_type = (char *) PIN_POID_GET_TYPE(dev_poidp);

	if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_SIM) == 0){
		/*
		 * The device type is SIM
		 * Call the SIM device create policy code
		 */
		 PCM_OP(ctxp, PCM_OP_SIM_POL_DEVICE_CREATE, flags, i_flistp, 
			r_flistpp, ebufp);
	} 	
	else if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_NUM) == 0){
		/*
		 * The device type is NUM
		 * Call the NUM device create policy code
		 */
		 PCM_OP(ctxp, PCM_OP_NUM_POL_DEVICE_CREATE, flags, i_flistp, 
			r_flistpp, ebufp);
	}
	else if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_VOUCHER) == 0){
		/*
		 * The device type is VOUCHER
		 * Call the VOUCHER device create policy code
		 */
		 PCM_OP(ctxp, PCM_OP_VOUCHER_POL_DEVICE_CREATE, flags, i_flistp, 
			r_flistpp, ebufp);
	}
	else if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_APN) == 0){
		/*
		 * The device type is APN
		 * Call the APN device create policy code
		 */
		 PCM_OP(ctxp, PCM_OP_APN_POL_DEVICE_CREATE, flags, i_flistp, 
			r_flistpp, ebufp);
	}
	else if (strcmp(poid_type, PIN_OBJ_TYPE_DEVICE_IP) == 0){
		/*
		 * The device type is IP
		 * Call the IP device create policy code
		 */
		 PCM_OP(ctxp, PCM_OP_IP_POL_DEVICE_CREATE, flags, i_flistp, 
			r_flistpp, ebufp);
	}

	else{
		*r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
	}

	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_device_pol_create error", ebufp);
	}
	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_PYMT_POL_CHARGE operation.
 *******************************************************************/
void
op_pymt_pol_charge(
        cm_nap_connection_t	*connp,
	int			opcode,
        int			flags,
        pin_flist_t		*i_flistp,
        pin_flist_t		**o_flistpp,
        pin_errbuf_t		*ebufp)
{
	pin_flist_t		*r_flistp = NULL;
	pcm_context_t		*ctxp = connp->dm_ctx;

	if (PIN_ERR_IS_ERR(ebufp))
	{
		return ;
	}
	PIN_ERR_CLEAR_ERR(ebufp);
	/***********************************************************
	 * Insanity check.
	 ***********************************************************/
	if (opcode != PCM_OP_PYMT_POL_CHARGE) {
		pin_set_err(ebufp, PIN_ERRLOC_FM,
			PIN_ERRCLASS_SYSTEM_DETERMINATE,
			PIN_ERR_BAD_OPCODE, 0, 0, opcode);
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_pymt_pol_charge opcode error", ebufp);
		return;
	}

	/***********************************************************
	 * Debug: The input Flist
	 ***********************************************************/
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_pymt_pol_charge input flist", i_flistp);
	/**********************************************************
	 * Copy the input flist to r_flsitp as. Do not change the 
	 * Input Flist
	 *********************************************************/
	r_flistp = PIN_FLIST_COPY(i_flistp,ebufp);

	fm_pymt_pol_charge(ctxp, i_flistp, r_flistp,ebufp);
	if (PIN_ERR_IS_ERR(ebufp)) {
		/***************************************************
		 * Log something and return nothing.
		 **************************************************/
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"op_pymt_pol_charge error", ebufp);
		PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
		*o_flistpp = NULL;

	} 
	else
	{

		/***************************************************
		 * Point the real return flist to the right thing.
		 ***************************************************/
		*o_flistpp = r_flistp;

		/***************************************************
		 * Debug: What we're sending back.
		 ***************************************************/
		PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
			"op_pymt_pol_charge return flist", r_flistp);
	}

	return;
}
/*******************************************************************
 * Main routine for the PCM_OP_ACT_POL_SPEC_GLID operation.
 *******************************************************************/
void
op_act_pol_spec_glid(
    cm_nap_connection_t	*connp,
    int			opcode,
    int			flags,
    pin_flist_t		*i_flistp,
    pin_flist_t		**r_flistpp,
    pin_errbuf_t		*ebufp)
{
    pin_cookie_t		cookie = NULL;
    pcm_context_t		*ctxp = connp->dm_ctx;
    pin_flist_t		*e_flistp = NULL;
    pin_flist_t		*s_flistp = NULL;
    pin_flist_t		*flistp = NULL;
    const char			*event_type = NULL;
    poid_t			*e_pdp = NULL;

    int			rec_id = 0;
    int			*glid = NULL;

    if (PIN_ERR_IS_ERR(ebufp))
        return;
    PIN_ERR_CLEAR_ERR(ebufp);
    *r_flistpp = (pin_flist_t *)NULL;

    /*******************************************************************
     * Insanity check.
     *******************************************************************/
    if (opcode != PCM_OP_ACT_POL_SPEC_GLID) {
        pin_set_err(ebufp, PIN_ERRLOC_FM,
                    PIN_ERRCLASS_SYSTEM_DETERMINATE,
                    PIN_ERR_BAD_OPCODE, 0, 0, opcode);
        PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                         "op_act_pol_spec_glid bad opcode error", ebufp);
        return;
    }

    /*******************************************************************
     * Debug: What we got.
     *******************************************************************/
    PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
                      "op_act_pol_spec_glid input flist", i_flistp);

    /*******************************************************************
     * Our action will depend on the type of event
     * Get the event substruct to get all the needed data
     *******************************************************************/
    *r_flistpp = PIN_FLIST_COPY(i_flistp, ebufp);
    e_flistp = PIN_FLIST_SUBSTR_GET(*r_flistpp, PIN_FLD_EVENT, 0, ebufp);
    e_pdp = (poid_t *)PIN_FLIST_FLD_GET(e_flistp, PIN_FLD_POID, 0, ebufp);
    event_type = PIN_POID_GET_TYPE(e_pdp);

    /******************************************************************
     * Check PIN_FLD_RATES_USED array, add a dummy one if not.
     ******************************************************************/
    if (PIN_FLIST_ELEM_COUNT(e_flistp, PIN_FLD_BAL_IMPACTS, ebufp) == 0) {

        /**********************************************************
         * Add the bal impacts array for this pre-rates event.
         **********************************************************/
        fm_act_pol_add_event_bal_impacts(ctxp, e_flistp, ebufp);
    }

    /******************************************************************
     * Now walk the PIN_FLD_RATES_USED array and check for G/L ID.
     ******************************************************************/
    while ((flistp = PIN_FLIST_ELEM_GET_NEXT(e_flistp, PIN_FLD_BAL_IMPACTS,
                     &rec_id, 1, &cookie, ebufp)) != (pin_flist_t *)NULL) {

        /**********************************************************
         * G/L id is inside the PIN_FLD_SUBTOTAL array.
         **********************************************************/
        glid = (int *)PIN_FLIST_FLD_GET(flistp,
                                        PIN_FLD_GL_ID, 1, ebufp);

        /**********************************************************
         * We need to fill in the G/L id now.
         **********************************************************/
        if (glid == (int *)NULL) {
            fm_act_pol_spec_glid(connp, i_flistp,
                                 event_type, flistp, ebufp);
        }
    }

    /*******************************************************************
     * Error?
     *******************************************************************/
    if (PIN_ERR_IS_ERR(ebufp)) {
        PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                         "op_act_pol_spec_glid error", ebufp);
    } else {
        PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
                          "op_act_pol_spec_glid return flist", *r_flistpp);
    }

    return;
}
/*******************************************************************
 * Main routine for the PCM_OP_GET_METAFIELD operation.
 *******************************************************************/
void
op_get_meta_field(
        cm_nap_connection_t	*connp,
	u_int			opcode,
        u_int			flags,
        pin_flist_t		*in_flistp,
        pin_flist_t             **ret_flistp,
        pin_errbuf_t		*ebufp)
		
		{
        pcm_context_t           *ctxp = connp->dm_ctx;
        pin_flist_t             *r_flistp = NULL;


        if (PIN_ERR_IS_ERR(ebufp))
                return;
        PIN_ERR_CLEAR_ERR(ebufp);
        /***********************************************************
         * Insanity check.
         ***********************************************************/
        if (opcode != PCM_OP_GET_METAFIELD) {
                pin_set_err(ebufp, PIN_ERRLOC_FM,
                        PIN_ERRCLASS_SYSTEM_DETERMINATE,
                        PIN_ERR_BAD_OPCODE, 0, 0, opcode);
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                        "op_get_meta_field opcode error", ebufp);
                return;
        }

		/*  Debug - What we got */
		
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
		"op_get_meta_field", in_flistp);


	/***********************************************************
         * Call main function 
         ***********************************************************/
        fm_get_meta_field(ctxp, in_flistp, &r_flistp, ebufp);
        
        if (PIN_ERR_IS_ERR(ebufp)) {
                /***************************************************
                 * Log Error Buuffer and return.
                 ***************************************************/
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                        "op_get_meta_field", ebufp);
                PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
                *ret_flistp = NULL;

        }
        else
        {

		*ret_flistp = PIN_FLIST_COPY(r_flistp, ebufp);
                /***************************************************
                 * Debug: What we're sending back.
                 ***************************************************/
                PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,
                        "op_get_meta_field return flist", r_flistp);
        }

		
  /*** Print Output What We Got ***/
        PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,"fm_get_meta_field", r_flistp);

	
		return;
		}