/*******************************************************************
 * 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;
}
/*******************************************************************
 * Simple search.
 *
 *	Performs a read-object search for the master account
 *	object and displays the results with PIN_FLIST_PRINT.
 *
 *	The "one arg equal" search for /account is 201.
 *
 *	Note: In real life, this isn't particularly useful
 *	since we could use the poid of the account to do a
 *	read-object op directly.
 *
 *******************************************************************/
void
sample_read_obj_search(
	pcm_context_t	*ctxp,
	u_int64		database,
	pin_errbuf_t	*ebufp)
{
	pin_flist_t	*flistp = NULL;
	pin_flist_t	*a_flistp = NULL;
	pin_flist_t	*r_flistp = NULL;

	poid_t		*objp = NULL;
	u_int64		id;


	/***********************************************************
	 * Check the error buffer.
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Allocate the flist for searching.
	 ***********************************************************/
	flistp = PIN_FLIST_CREATE(ebufp);

	/***********************************************************
	 * Allocate the search poid and give it to the flist.
	 ***********************************************************/
	id = (u_int64)201;

	objp = PIN_POID_CREATE(database, "/search", id, ebufp);
	PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search arguments array.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);

	/***********************************************************
	 * Allocate the master account poid and add as the arg.
	 ***********************************************************/
	id = (u_int64)1;

	objp = PIN_POID_CREATE(database, "/account", id, ebufp);
	PIN_FLIST_FLD_PUT(a_flistp, PIN_FLD_POID, (void *)objp, ebufp);

	/***********************************************************
	 * Add a search results marker.
	 *
	 * Making this NULL forces the read-object result we want.
	 ***********************************************************/
	a_flistp = (pin_flist_t *)NULL;
	PIN_FLIST_ELEM_PUT(flistp, a_flistp, PIN_FLD_RESULTS, 0, ebufp);

	/***********************************************************
	 * Call the DM to do the search.
	 ***********************************************************/
	PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);

	/***********************************************************
	 * Get (and show) the results.
	 ***********************************************************/
	a_flistp = PIN_FLIST_ELEM_GET(r_flistp, PIN_FLD_RESULTS, 0, 0, ebufp);

	fprintf(stdout,"\nSimple Search Result Flist:\n");
	PIN_FLIST_PRINT(a_flistp, stdout, ebufp);

	/***********************************************************
	 * Clean up.
	 ***********************************************************/
	/* Free local memory */
	PIN_FLIST_DESTROY(r_flistp, NULL);
	PIN_FLIST_DESTROY(flistp, NULL);

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

	return;
}
/*******************************************************************
 * fm_pymt_pol_chagre_process_result()
 * This function reads the response from vendor
 * and assigns a reason ID for the response
 *******************************************************************/
static void
fm_pymt_pol_charge_process_result(
	pcm_context_t           *ctxp,
	pin_flist_t		*i_flistp,
	int			*reason_id,
	int			*domain_idp,
	pin_errbuf_t		*ebufp)
{
	pin_flist_t             *info_flistp = NULL;
	pin_errbuf_t            any_field_ebuf;
	pin_cookie_t            cookie = NULL;
	pin_fld_num_t		field = 0;
	int32			rec_id = 0;
	pin_charge_result_t	*resultp = NULL;
	if (PIN_ERR_IS_ERR(ebufp))
	{
		return ;
	}
	PIN_ERR_CLEAR_ERR(ebufp);

	PIN_ERR_CLEAR_ERR(&any_field_ebuf);	

	while (PIN_FLIST_ANY_GET_NEXT(i_flistp, &field, 
				&rec_id, &cookie, &any_field_ebuf) != NULL ){
		if (field == PIN_FLD_CC_INFO || field == PIN_FLD_DD_INFO) {
			info_flistp = PIN_FLIST_ELEM_GET(i_flistp, 
					field, 0, 0, ebufp);
			resultp = (pin_charge_result_t *)PIN_FLIST_FLD_GET(info_flistp,
					PIN_FLD_RESULT, 0,ebufp);
			/*******************************************
			 * Set the PIN_FLD_RESULT_ID in the PIN_FLD_RESULTS 
			 * array
			 ******************************************/
			if (resultp){
				/******************************
				 *Set Default Reason ID to 0
				 *******************************/
				switch (*resultp) {
				case PIN_CHARGE_RES_PASS: 
					*reason_id = PIN_REASON_ID_APPROVED;
					*domain_idp = PIN_PYMT_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_NO_ANS:
					*reason_id = PIN_REASON_ID_FAIL_NO_ANS;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_ADDR_AVS:
					*reason_id = PIN_REASON_ID_FAIL_ADDR_AVS;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_ADDR_LOC:
					*reason_id = PIN_REASON_ID_FAIL_ADDR_LOC;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_ADDR_ZIP:
					*reason_id = PIN_REASON_ID_FAIL_ADDR_ZIP;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_CARD_BAD:
					*reason_id = PIN_REASON_ID_FAIL_CARD_BAD;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_DECL_SOFT:
					*reason_id = PIN_REASON_ID_FAIL_DECL_SOFT;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_SRVC_UNAVAIL:
					*reason_id = PIN_REASON_ID_FAIL_SRVC_UNAVAIL;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_DECL_HARD:
					*reason_id = PIN_REASON_ID_FAIL_DECL_HARD;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_NO_MIN:
					*reason_id = PIN_REASON_ID_FAIL_NO_MIN;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_INVALID_CMD:
					*reason_id = PIN_REASON_ID_INVALID_CMD;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_SELECT_ITEMS:
					*reason_id = PIN_REASON_ID_FAIL_SELECT_ITEMS;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_CVV_BAD:
					*reason_id = PIN_REASON_ID_FAIL_CVV_BAD;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_NO_CREDIT_BALANCE:
					*reason_id =  PIN_REASON_ID_NO_CREDIT_BALANCE;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_LOGICAL_PROBLEM:
					*reason_id = PIN_REASON_ID_FAIL_LOGICAL_PROBLEM;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_FORMAT_ERROR:
					*reason_id = PIN_REASON_ID_FAIL_FORMAT_ERROR;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_INVALID_CONTENT:
					*reason_id = PIN_REASON_ID_FAIL_INVALID_CONTENT;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				case PIN_CHARGE_RES_FAIL_TECHNICAL_PROBLEM:
					*reason_id = PIN_REASON_ID_FAIL_TECHNICAL_PROBLEM;
					*domain_idp = PIN_PYMT_FAILED_REASON_DOMAIN_ID;
					break;
				default:
					*reason_id = PIN_REASON_ID_DEFAULT;
					/*******************************************
					 * Setting the default reason domain
					 * since we are setting default reason ID
					 * The following line can be commented if
					 * the domain id has to be retained as 
					 * it was passed in the function.
					 ******************************************/
					*domain_idp = PIN_PYMT_REASON_DOMAIN_ID;
					break;
				}
			}
                }
	}
	/*************************************************
	 * Check Error buf and Debug it
	 ************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_DEBUG,
                                "fm_pymt_pol_charge_process_result", ebufp);
	}

	return;
}
void
fm_cust_pol_create_metafield_obj(
    pcm_context_t           *ctxp,
    int32                    flags,
    pin_flist_t             *in_flistp,
    pin_flist_t            **ret_flistpp,
    pin_errbuf_t            *ebufp)

{
    void 		   *vp = NULL;
    int 		   count =0;
    int64        database  = pcm_get_current_db_no(ctxp);
    pin_flist_t   *i_flist = NULL;
    pin_flist_t   *sub_flistp = NULL;
    pin_flist_t   *r_flistp = NULL;
    char 	      *program_name = NULL;
    char 	      *class_name= NULL;
    char 	      *default_value= NULL;
    int 	       fld_type=0;

    if(PIN_ERRBUF_IS_ERR(ebufp))
        return;
    PIN_ERR_CLEAR_ERR(ebufp);

    *ret_flistpp = NULL;

    //Count FIELDS array
    count = PIN_FLIST_ELEM_COUNT(in_flistp,PIN_FLD_VALUES,ebufp);


    if (count==0)
        return;

    if(count==1)
    {

        i_flist= PIN_FLIST_CREATE(ebufp);
        vp = PIN_FLIST_FLD_GET(in_flistp,PIN_FLD_POID,1,ebufp);
        PIN_FLIST_FLD_SET(i_flist,PIN_FLD_POID,(void*)vp,ebufp);

        sub_flistp = PIN_FLIST_ELEM_GET(in_flistp, PIN_FLD_VALUES,PIN_ELEMID_ANY, 1, ebufp);
        program_name = PIN_FLIST_FLD_GET(sub_flistp,PIN_FLD_NAME,1,ebufp);
        PIN_FLIST_FLD_SET(i_flist,PIN_FLD_NAME,program_name,ebufp);

        fld_type =*(int*) PIN_FLIST_FLD_GET(sub_flistp,PIN_FLD_TYPE,1,ebufp);
        PIN_FLIST_FLD_SET(i_flist,PIN_FLD_TYPE,&fld_type,ebufp);

        class_name=PIN_FLIST_FLD_GET(sub_flistp,PIN_FLD_CLASS_NAME,1,ebufp);
        PIN_FLIST_FLD_SET(i_flist,PIN_FLD_CLASS_NAME,class_name,ebufp);

        default_value=PIN_FLIST_FLD_GET(sub_flistp,PIN_FLD_DEFAULT_VALUE,1,ebufp);
        if(default_value)
            PIN_FLIST_FLD_SET(i_flist,PIN_FLD_DEFAULT_VALUE,default_value,ebufp);

        if (PIN_ERRBUF_IS_ERR(ebufp))
        {
            PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,"Error Occured while creating the input flist",ebufp);
            return;
        }

        PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,"input flist for metafield obj ",i_flist);


        //Call pcm_op_create_obj
        PCM_OP(ctxp,PCM_OP_CREATE_OBJ,0,i_flist,ret_flistpp,ebufp);

        if(PIN_ERRBUF_IS_ERR(ebufp))
        {
            PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,"Error Occured while calling PCM_OP_CREATE_OBJ",ebufp);
            return;
        }

    }
    else if (count >1)
    {
        //Call pcm_op_bulk_create_obj
        PCM_OP(ctxp,PCM_OP_BULK_CREATE_OBJ ,0,in_flistp,ret_flistpp,ebufp);

        if(PIN_ERRBUF_IS_ERR(ebufp))
        {
            PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,"Error Occured while calling PCM_OP_BULK_CREATE_OBJ" ,ebufp);
            return;
        }
    }

    if(ret_flistpp)
        PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG,"Output flist for metafield obj ",*ret_flistpp);

    return;

}
/**********************************************************************
 * fm_pymt_pol_spec_collect_get_ach()
 * Get ACH information
 **********************************************************************/
static void
fm_pymt_pol_spec_collect_get_ach(
	pcm_context_t	*ctxp,
	int32		flags,
	pin_flist_t	*i_flistp,
	pin_flist_t	*o_flistp,
	pin_errbuf_t	*ebufp)
{

	void		*vp		= NULL;
	pin_flist_t	*flistp		= NULL;
	pin_flist_t	*p_flistp	= NULL;
	pin_flist_t	*rp_flistp	= NULL;
	pin_flist_t	*a_flistp	= NULL;
	pin_flist_t	*ra_flistp	= NULL;
	int32		rec_id		= 0;
	poid_t		*p_pdp		= NULL;
	poid_t		*a_pdp		= NULL;

	if (PIN_ERR_IS_ERR(ebufp)) {
		return;
	}

	PIN_ERR_CLEAR_ERR(ebufp);

	p_pdp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_PAYINFO_OBJ, 0, ebufp);
        a_pdp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
	
	/** read the payinfo to get the ach pointer. **/
	p_flistp = PIN_FLIST_CREATE(ebufp);
	PIN_FLIST_FLD_SET(p_flistp, PIN_FLD_POID, p_pdp, ebufp);
	PIN_FLIST_FLD_SET(p_flistp, PIN_FLD_ACH, &rec_id, ebufp);
	
	PCM_OP(ctxp, PCM_OP_READ_FLDS, PCM_OPFLG_READ_UNCOMMITTED, 
					p_flistp, &rp_flistp, ebufp);	

	if (rp_flistp != (pin_flist_t *)NULL) {
		vp = PIN_FLIST_FLD_GET(rp_flistp, PIN_FLD_ACH, 0, ebufp);
		
		if (vp) {
			rec_id = *(int32 *)vp;
		}
                a_flistp = PIN_FLIST_CREATE(ebufp);
                PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_POID, a_pdp, ebufp);
                PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_ACH,
                                                (void *) &rec_id, ebufp);

                PCM_OP(ctxp, PCM_OP_PYMT_GET_ACH_INFO, 0, a_flistp,
                                                &ra_flistp, ebufp);

                flistp = PIN_FLIST_ELEM_GET(ra_flistp, PIN_FLD_RESULTS, 0,
                                                PIN_ELEMID_ANY, ebufp);

                vp = PIN_FLIST_FLD_GET(flistp, PIN_FLD_MERCHANT, 0, ebufp);
                PIN_FLIST_FLD_SET(o_flistp, PIN_FLD_MERCHANT, vp, ebufp);

                PIN_FLIST_FLD_SET(o_flistp, PIN_FLD_ACH, (void *) &rec_id, ebufp);

                vp = PIN_FLIST_FLD_TAKE(flistp, PIN_FLD_POID_VAL, 0, ebufp);

                flistp = PIN_FLIST_ELEM_ADD(o_flistp, PIN_FLD_BATCH_INFO, 0,
                                                                ebufp);
                PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID_VAL, vp, ebufp);
	}

	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
				"fm_pymt_pol_spec_collect_get_ach error", ebufp);
	}

	PIN_FLIST_DESTROY_EX(&p_flistp, NULL);
	PIN_FLIST_DESTROY_EX(&rp_flistp, NULL);
	PIN_FLIST_DESTROY_EX(&a_flistp, NULL);
	PIN_FLIST_DESTROY_EX(&ra_flistp, NULL);

	return;
}
static void
fm_get_meta_field(
	pcm_context_t           *ctxp,
        pin_flist_t             *in_flistp,
        pin_flist_t             **out_flistpp,
        pin_errbuf_t            *ebufp)
{
	pin_flist_t     *keys_flistp = NULL;
        pin_flist_t     *search_flistp = NULL;
        pin_flist_t     *flistp = NULL; 
        poid_t          *s_pdp = NULL; 
        poid_t          *bi_pdp = NULL; 
        int64           database = 0;
        int32           sflags = 256;
        int32           result = PIN_BOOLEAN_FALSE;
        void            *vp = NULL;
        pin_decimal_t   *zero_decimal =  pin_decimal("0.0", ebufp);
	pin_flist_t	*r_flistp = NULL;
	char                    *name = NULL;
	char                    *class_name = NULL;
	char                    *default_value;
	int32           count = 0;
	int32           cnt_flds = 0;
	int32                   elemid = 1;
	pin_errbuf_t            any_field_ebuf;
        pin_cookie_t            cookie = NULL;
        pin_fld_num_t           field = 0;
        int32                   rec_id = 0;
	void            *type = NULL;

        if (PIN_ERR_IS_ERR(ebufp)) {
                return;
        }
        PIN_ERR_CLEAR_ERR(ebufp);
	PIN_ERR_CLEAR_ERR(&any_field_ebuf);
	
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG, "fm_get_meta_field input flistp", in_flistp);
	bi_pdp = (poid_t *) PIN_FLIST_FLD_GET(in_flistp,
                                PIN_FLD_POID,0, ebufp);

	count = PIN_FLIST_ELEM_COUNT (in_flistp,
                        PIN_FLD_KEYS, ebufp);
	if (count == 0)
        {

                 pin_set_err(ebufp, PIN_ERRLOC_FM,
                        PIN_ERRCLASS_SYSTEM_DETERMINATE,
                        PIN_ERR_BAD_OPCODE, 0, 0, count);
                PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                        "op_get_meta_field search flistp", ebufp);

                *out_flistpp = NULL;
                return;
        }

	else {
	keys_flistp = PIN_FLIST_ELEM_GET (in_flistp, PIN_FLD_KEYS,
                PIN_ELEMID_ANY, 0, ebufp);
	while (PIN_FLIST_ANY_GET_NEXT(keys_flistp, &field,
                                &rec_id, &cookie, &any_field_ebuf) != NULL ){
        cnt_flds = cnt_flds + 1;
	if (field == PIN_FLD_NAME){
 	name = (char *)PIN_FLIST_FLD_GET(keys_flistp, PIN_FLD_NAME, 1, ebufp);
	}
	if (field == PIN_FLD_CLASS_NAME){
       class_name = PIN_FLIST_FLD_GET(keys_flistp, PIN_FLD_CLASS_NAME, 0, ebufp );
	}
	if (field == PIN_FLD_TYPE){
	type = PIN_FLIST_FLD_GET(keys_flistp, PIN_FLD_TYPE, 0, ebufp );			
	}
	}
	if ( cnt_flds == 1)
        {
        vp = (void *)"select X from /metafield where F1 = V1 ";
        }
        if ( cnt_flds == 2)
        {
        vp = (void *)"select X from /metafield where F1 = V1 and F2 = V2 ";
        }
        if ( cnt_flds == 3)
        {
        vp = (void *)"select X from /metafield where F1 = V1 and F2 = V2 and F3 = V3 ";
        }

	 /*********************************************************
         * Create the search flist to search in the item objects
         *********************************************************/
        search_flistp = PIN_FLIST_CREATE(ebufp);
        database = PIN_POID_GET_DB(bi_pdp);
        s_pdp = PIN_POID_CREATE(database, "/search", -1, ebufp);
        PIN_FLIST_FLD_PUT(search_flistp, PIN_FLD_POID, (void *)s_pdp, ebufp);
       /******************************************************************
         * Set the search template.
         ******************************************************************/
        PIN_FLIST_FLD_SET(search_flistp, PIN_FLD_TEMPLATE, vp, ebufp);
        PIN_FLIST_FLD_SET(search_flistp, PIN_FLD_FLAGS, (void *)&sflags, ebufp);

	/*********************************************************
         * Add the search arguments.
         *********************************************************/
	if (name != NULL) {
        flistp = PIN_FLIST_ELEM_ADD(search_flistp, PIN_FLD_ARGS, elemid++, ebufp);
        PIN_FLIST_FLD_SET(flistp, PIN_FLD_NAME, name, ebufp);
	}

        /*********************************************************
         * Add the search arguments.
         *********************************************************/
	if (class_name != NULL) {
        flistp = PIN_FLIST_ELEM_ADD(search_flistp, PIN_FLD_ARGS, elemid++, ebufp);
        PIN_FLIST_FLD_SET(flistp, PIN_FLD_CLASS_NAME, class_name, ebufp);
        }
	
	/*********************************************************
         * Add the search arguments.
         *********************************************************/
        if (type != NULL) {
        flistp = PIN_FLIST_ELEM_ADD(search_flistp, PIN_FLD_ARGS, elemid++, ebufp);
        PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE, type, ebufp);
        }


        /*********************************************************
         * Add the result array for the search.
         *********************************************************/

        flistp = PIN_FLIST_ELEM_ADD(search_flistp, PIN_FLD_RESULTS, 0, ebufp);
	PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE,(void *)NULL, ebufp);
        
	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG, "op_get_meta_field search flistp", search_flistp);  

	 PCM_OP(ctxp, PCM_OP_SEARCH, 0, search_flistp, out_flistpp, ebufp);

	PIN_ERR_LOG_FLIST(PIN_ERR_LEVEL_DEBUG, "op_get_meta_field search flistp", *out_flistpp);
	}
	     
 	}
/********************************************************************
 * 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;
}
/****************************************************************
 * Function : fm_cust_pol_prep_create_sponsored_topup
 * Description : This function will prepare the flist for
 *               creating the sponsored topup operation.
 ****************************************************************/
static void fm_cust_pol_prep_create_sponsored_topup(
        pcm_context_t           *ctxp,
        int32                   flags,
        pin_flist_t             *i_flistp,
        pin_flist_t             **r_flistpp,
        pin_errbuf_t            *ebufp)
{
    poid_t    *initiator_pdp =    NULL;
    poid_t    *parent_pdp    =    NULL;
    poid_t    *balgrp_pdp    =    NULL;
    poid_t    *s_pdp         =    NULL;
    poid_t    *grp_pdp       =    NULL;

    pin_flist_t    *topup_flistp      =    NULL;
    pin_flist_t    *ingrptopup_flistp =    NULL;
    pin_flist_t    *ingrplmt_flistp   =    NULL;
    pin_flist_t    *ingrpmem_flistp   =    NULL;
    pin_flist_t    *tmp_flistp        =    NULL;
    pin_flist_t    *args1_flistp      =    NULL;
    pin_flist_t    *args2_flistp      =    NULL;
    pin_flist_t    *args3_flistp      =    NULL;
    pin_flist_t    *outtopup_flistp   =    NULL;
    pin_flist_t    *outgrpmem_flistp  =    NULL;
    pin_flist_t    *outgrptopup_flistp=    NULL;
    pin_flist_t    *reslt_flistp      =    NULL;
    pin_flist_t    *f_flistp          =    NULL;
    pin_flist_t    *s_flistp          =    NULL;
    pin_flist_t    *r_flistp          =    NULL;
    
    char   *grp_name   = NULL;
    char   *s_tmplt    = NULL;
    int    *res_id     = NULL;
    int    *topup_interval = NULL;
    int64  db_no       = 0;
    int    search_flag = 256;
    time_t nexttopup;
    time_t now;
    void   *vp;


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

    initiator_pdp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);

    topup_flistp = PIN_FLIST_ELEM_GET(i_flistp, PIN_FLD_TOPUP_INFO,
                                                        PIN_ELEMID_ANY, 0, ebufp);
    ingrptopup_flistp = PIN_FLIST_ELEM_GET(topup_flistp, PIN_FLD_GROUP_TOPUP_INFO,
                                                        PIN_ELEMID_ANY, 0, ebufp);
    ingrpmem_flistp = PIN_FLIST_ELEM_GET(ingrptopup_flistp, PIN_FLD_GROUP_TOPUP_MEMBERS,
                                                        PIN_ELEMID_ANY, 0, ebufp);
    ingrplmt_flistp = PIN_FLIST_ELEM_GET(ingrptopup_flistp, PIN_FLD_GROUP_TOPUP_LIMITS,
                                                        PIN_ELEMID_ANY, 0, ebufp);

    /****************************************************************
     * Update the NEXT_TOPUP_T in the out put flist.
     ****************************************************************/

    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);
    outgrpmem_flistp = PIN_FLIST_ELEM_GET(outgrptopup_flistp, PIN_FLD_GROUP_TOPUP_MEMBERS,
                                                        PIN_ELEMID_ANY, 0, ebufp);
    topup_interval = PIN_FLIST_FLD_GET(outgrpmem_flistp, PIN_FLD_TOPUP_INTERVAL, 0, ebufp);

    if (PIN_ERR_IS_ERR(ebufp))
            return;

    vp = PIN_FLIST_FLD_GET(ingrpmem_flistp , PIN_FLD_NEXT_TOPUP_T, 1, ebufp);

    if(vp){
        PIN_FLIST_FLD_SET(outgrpmem_flistp, PIN_FLD_NEXT_TOPUP_T,  vp, ebufp);
    }else{
        now = pin_virtual_time((time_t *) NULL);
        nexttopup = now + ((*topup_interval) * 24 * 60 * 60 );
        PIN_FLIST_FLD_SET(outgrpmem_flistp, PIN_FLD_NEXT_TOPUP_T, &nexttopup, ebufp);
    }

    grp_name = PIN_FLIST_FLD_GET(ingrptopup_flistp, PIN_FLD_NAME, 1, ebufp);
    grp_pdp = PIN_FLIST_FLD_GET(ingrptopup_flistp, PIN_FLD_POID, 0, ebufp);

    /****************************************************************
     * check if the group poid is type only or not and also
     * it has the name or not.
     ****************************************************************/

    if( PIN_POID_IS_TYPE_ONLY(grp_pdp) || !grp_name )
    {
        /****************************************************************
         * If the group name or the group poid is not defind in the
         * input flist then search /group/topup for the particular
         * parent and set the name and the group poid.
         ****************************************************************/
        parent_pdp = PIN_FLIST_FLD_GET(ingrptopup_flistp, PIN_FLD_PARENT, 0, ebufp);
        balgrp_pdp = PIN_FLIST_FLD_GET(ingrptopup_flistp, PIN_FLD_BAL_GRP_OBJ, 0, ebufp);
        res_id = PIN_FLIST_FLD_GET(ingrplmt_flistp, PIN_FLD_RESOURCE_ID, 0, ebufp);

        db_no = PIN_POID_GET_DB(initiator_pdp);
        s_flistp = PIN_FLIST_CREATE(ebufp);
        s_pdp = PIN_POID_CREATE(db_no, "/search", -1, ebufp);
        s_tmplt = " select X from /group/topup where F1 = V1 and F2 = V2 and F3 = V3 ";
        PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_POID, s_pdp, ebufp);
        PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_TEMPLATE, s_tmplt, ebufp);
        PIN_FLIST_FLD_SET(s_flistp, PIN_FLD_FLAGS, &search_flag, ebufp);
        
        tmp_flistp = PIN_FLIST_CREATE(ebufp);
        PIN_FLIST_FLD_SET(tmp_flistp, PIN_FLD_PARENT, parent_pdp, ebufp);
        
        args1_flistp = PIN_FLIST_CREATE(ebufp);
        PIN_FLIST_FLD_SET(args1_flistp, PIN_FLD_BAL_GRP_OBJ, balgrp_pdp, ebufp);
        f_flistp = PIN_FLIST_CREATE(ebufp);
        if( grp_name == NULL )
        {
            /****************************************************************
             * if the group name is null then the search argument will contain
             * the resource id.
             ****************************************************************/
            args3_flistp = PIN_FLIST_CREATE(ebufp);
            PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_RESOURCE_ID, res_id, ebufp);
            PIN_FLIST_ELEM_PUT(args3_flistp, f_flistp, PIN_FLD_GROUP_TOPUP_LIMITS, PCM_RECID_ALL, ebufp);
            PIN_FLIST_ELEM_PUT(s_flistp, args3_flistp, PIN_FLD_ARGS,  3, ebufp);
        }
        else
        {
            PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_NAME, grp_name, ebufp);
            PIN_FLIST_ELEM_PUT(s_flistp, f_flistp, PIN_FLD_ARGS,  3, ebufp);
        }


        PIN_FLIST_ELEM_PUT(s_flistp, tmp_flistp, PIN_FLD_ARGS,  1, ebufp);
        PIN_FLIST_ELEM_PUT(s_flistp, args1_flistp, PIN_FLD_ARGS,  2, ebufp);

        reslt_flistp = PIN_FLIST_CREATE(ebufp);
        PIN_FLIST_FLD_SET(reslt_flistp, PIN_FLD_NAME, "",ebufp);

        PIN_FLIST_ELEM_PUT(s_flistp, reslt_flistp, PIN_FLD_RESULTS,  0, ebufp);

        PCM_OP(ctxp, PCM_OP_SEARCH, flags, s_flistp, &r_flistp, ebufp);

        PIN_FLIST_DESTROY_EX(&s_flistp, NULL);

        tmp_flistp = PIN_FLIST_ELEM_GET(r_flistp, PIN_FLD_RESULTS, 0, 1, ebufp);
        /****************************************************************
         * If the results array of search contains any record then select the
         * finst element of the results array and set the group poid and name
         * else don't set it.
         ****************************************************************/
        if( tmp_flistp != NULL )
        {
            grp_name = PIN_FLIST_FLD_GET(tmp_flistp, PIN_FLD_NAME, 0, ebufp);
            grp_pdp = PIN_FLIST_FLD_GET(tmp_flistp, PIN_FLD_POID, 0, ebufp);
             
            f_flistp = PIN_FLIST_ELEM_GET(outtopup_flistp, PIN_FLD_GROUP_TOPUP_INFO,
                                                        PIN_ELEMID_ANY, 0, ebufp);
            PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_NAME, grp_name, ebufp);
            PIN_FLIST_FLD_SET(f_flistp, PIN_FLD_POID, grp_pdp, ebufp);
        }
        PIN_FLIST_DESTROY_EX(&r_flistp, NULL);
    }
    if (PIN_ERR_IS_ERR(ebufp))
    {
        PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
                                 "fm_cust_pol_prep_create_sponsored_topup error",
                                 ebufp);
    }
    return;
}
/*******************************************************************
 * fm_pymt_pol_collect_result():
 *
 *	Turn a pin_charge result into a collect result.
 *
 *******************************************************************/
static void
fm_pymt_pol_collect_result(
	pcm_context_t		*ctxp,
	pin_flist_t		*i_flistp,
	pin_flist_t		*r_flistp,
	pin_errbuf_t		*ebufp)
{
	pin_charge_result_t	*type = NULL;
	int			result = 0;
	void			*vp = NULL;
	pin_flist_t             *res_flistp = NULL;

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

	res_flistp = PIN_FLIST_ELEM_GET(i_flistp, PIN_FLD_RESULTS, 0, 1, ebufp);
        if(res_flistp){
                vp = PIN_FLIST_FLD_GET(res_flistp, PIN_FLD_POID, 1, ebufp);

                if (vp){
                        PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_POID, vp, ebufp);
                }
                else{
                        vp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
                        PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_POID, vp, ebufp);
                }
        }
        else {
                vp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
                PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_POID, vp, ebufp);
        }
	/***********************************************************
	 * Our behavoir depends primarily on the pin_result.
	 ***********************************************************/
	type = (pin_charge_result_t *)PIN_FLIST_FLD_GET(i_flistp,
		PIN_FLD_RESULT, 0, ebufp);

	if (type == (pin_charge_result_t *)NULL) {
		/* log? */
		return;
	}

	/***********************************************************
	 * What is the pin_result?
	 ***********************************************************/
	if (*type >= PIN_CHARGE_RES_AUTH_PENDING){
		PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_RESULT, 
			(void *)type, ebufp);
		vp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_DESCR, 
			1, ebufp);
		if (vp) {
			PIN_FLIST_FLD_SET(r_flistp, 
				PIN_FLD_DESCR, vp, ebufp);
		}
	} else {	
		switch (*type) {
		case PIN_CHARGE_RES_PASS:
			fm_pymt_pol_collect_result_pass(ctxp,
				i_flistp, r_flistp, ebufp);
			break;

		case PIN_CHARGE_RES_FAIL_CARD_BAD:
		case PIN_CHARGE_RES_FAIL_DECL_HARD:
			fm_pymt_pol_collect_result_hard(ctxp,
				i_flistp, r_flistp, ebufp);
			break;

		case PIN_CHARGE_RES_CVV_BAD:
		case PIN_CHARGE_RES_FAIL_DECL_SOFT:
		case PIN_CHARGE_RES_FAIL_ADDR_AVS:
		case PIN_CHARGE_RES_FAIL_ADDR_LOC:
		case PIN_CHARGE_RES_FAIL_ADDR_ZIP:
		case PIN_CHARGE_RES_FAIL_NO_ANS:
		case PIN_CHARGE_RES_SRVC_UNAVAIL:
		case PIN_CHARGE_RES_FAIL_FORMAT_ERROR:
		case PIN_CHARGE_RES_FAIL_LOGICAL_PROBLEM:
		case PIN_CHARGE_RES_FAIL_INVALID_CONTENT:
		case PIN_CHARGE_RES_FAIL_TECHNICAL_PROBLEM :
			fm_pymt_pol_collect_result_soft(ctxp,
				i_flistp, r_flistp, ebufp);
			break;

		case PIN_CHARGE_RES_FAIL_NO_MIN:
		case PIN_CHARGE_RES_FAIL_SELECT_ITEMS:
		case PIN_CHARGE_RES_NO_CREDIT_BALANCE:
		case PIN_CHARGE_RES_INVALID_CMD:
		
			result = PIN_RESULT_FAIL;
			PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_RESULT, 
				(void *)&result, ebufp);
			vp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_DESCR,
							1, ebufp);
			if (vp){
				PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_DESCR,
							vp, ebufp);
			}
			break;

		default:
			/* error - I think */
			pin_set_err(ebufp, PIN_ERRLOC_FM,
				PIN_ERRCLASS_SYSTEM_DETERMINATE,
				PIN_ERR_BAD_VALUE, PIN_FLD_RESULT, 0, *type);
			break;
		}
	}

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

	return;
}
/******************************************************
 * Stuff a config parameter into outgoing flist, 
 * depending on string value
 ******************************************************/
static void
fm_cust_pol_get_config_stuff(
	pin_flist_t		*r_flistp,
	char			*key,
	char			*val,
	pin_errbuf_t		*ebufp)
{
	pin_errbuf_t		errbuf;
	u_int			type;
	pin_flist_t		*flistp = NULL;
	u_int			port = 0;

	if(ebufp == NULL) ebufp = &errbuf;

	PIN_ERR_CLEAR_ERR(ebufp);

	if(key == NULL) {
		return;
	}

	/*
	 * If DNS Address param, then create host array entry
	 */
	else if( strcmp( key, "dns_address_1")==0) {
		flistp = PIN_FLIST_ELEM_ADD(r_flistp, PIN_FLD_HOST, 1, ebufp);

		PIN_FLIST_FLD_SET(flistp, PIN_FLD_HOSTNAME, (void *)val, ebufp);

		type = PIN_HOST_DNS;
		PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE, (void *)&type, ebufp);
	}

	else if (strcmp(key, "dns_address_2") == 0) {
		flistp = PIN_FLIST_ELEM_ADD(r_flistp, PIN_FLD_HOST, 2, ebufp);

		PIN_FLIST_FLD_SET(flistp, PIN_FLD_HOSTNAME, (void *)val, ebufp);

		type = PIN_HOST_DNS;
		PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE, (void *)&type, ebufp);
	}

	/*
	 * If SMTP Hostname, then look to see if already a
	 * host array elem yet or not.  We will count on it
	 * being in elemid 3, although this is not a hard
	 * and fast rule except for only within this policy
	 * call.  It may have already been setup if the smtp_port
	 * parameter was previously found.
	 */

	else if (strcmp(key, "smtp_hostname") == 0) {
		flistp = PIN_FLIST_ELEM_GET(r_flistp,
			PIN_FLD_HOST, 3, 1, ebufp);

		if (flistp == (pin_flist_t *)NULL) {
			flistp = PIN_FLIST_ELEM_ADD( r_flistp, 
				PIN_FLD_HOST, 3, ebufp);

			type = PIN_HOST_SMTP;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE,
				(void *)&type, ebufp);
		}

		PIN_FLIST_FLD_SET(flistp, PIN_FLD_HOSTNAME, (void *)val, ebufp);
	}

	/*
	 * If SMTP port, then look to see if already a
	 * host array elem yet or not.  We will count on it
	 * being in elemid 3, although this is not a hard
	 * and fast rule except for only within this policy
	 * call.  It may have already been setup if the smtp_host
	 * parameter was previously found.
	 */
	else if (strcmp(key, "smtp_port") == 0) {
		flistp = PIN_FLIST_ELEM_GET(r_flistp,
			PIN_FLD_HOST, 3, 1, ebufp);

		if (flistp == (pin_flist_t *)NULL) {
			flistp = PIN_FLIST_ELEM_ADD(r_flistp, 
				PIN_FLD_HOST, 3, ebufp);

			type = PIN_HOST_SMTP;
			PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE,
				(void *)&type, ebufp);
		}

		port = atoi(val);
		PIN_FLIST_FLD_SET(flistp, PIN_FLD_PORT, (void *)&port, ebufp);

	}

	/*
	 * NNTP Hostname
	 */
	else if (strcmp(key, "nntp_hostname") == 0) {
		flistp = PIN_FLIST_ELEM_ADD(r_flistp, PIN_FLD_HOST, 4, ebufp);

		PIN_FLIST_FLD_SET(flistp, PIN_FLD_HOSTNAME, (void *)val, ebufp);

		type = PIN_HOST_NNTP;
		PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE, (void *)&type, ebufp);
	}

	/*
	 * Pop Host
	 */
	else if (strcmp(key, "pop_hostname") == 0) {
		flistp = PIN_FLIST_ELEM_ADD(r_flistp, PIN_FLD_HOST, 5, ebufp);

		PIN_FLIST_FLD_SET(flistp, PIN_FLD_HOSTNAME, (void *)val, ebufp);

		type = PIN_HOST_POP;
		PIN_FLIST_FLD_SET(flistp, PIN_FLD_TYPE, (void *)&type, ebufp);	
	}

	/*
	 * Http URL
	 */
	else if (strcmp(key, "http_url") == 0) {
		PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_HTTP_URL,
			(void *)val, ebufp);
	}

	/*
	 * Support number
	 */
	else if (strcmp(key, "support_number") == 0) {
		PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_SUPPORT_PHONE,
			(void *)val, ebufp);
	}


	return;
/*ErrOut:
	return;*/
}
/*******************************************************************
 * fm_cust_pol_valid_login()
 *
 *	Validate the given login according to the given poid type.
 *
 *	For now, logins are required (ie they can't be NULL) and
 *	must be less than the maximum length (currently 255).
 *
 *******************************************************************/
static void
fm_cust_pol_valid_login(cm_nap_connection_t	*connp,
			pin_flist_t		*i_flistp,
			int32			flags,
			pin_flist_t		**o_flistpp,
			pin_errbuf_t		*ebufp)
{
	pin_cookie_t		cookie = NULL;
	pin_flist_t		*r_flistp = NULL;
	pin_flist_t		*s_flistp = NULL;
	pin_flist_t		*a_flistp = NULL;
	pin_flist_t		*flistp = NULL;
	poid_t			*o_pdp = NULL;
	char			*login = NULL;
	void                    *vp = NULL;
	pcm_context_t		*ctxp = connp->dm_ctx;
	
	const char		*subtype = NULL;
	int32			result = PIN_CUST_VERIFY_PASSED;
	int32			elemid;
	int64			db_no;
	int			count = 0;
	int 			msexchange_service_type = 
	                                  PIN_MSEXCHANGE_SERVICE_NONE;



	/***********************************************************
         * Return immediately if there's an error in ebufp.
         ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp))
		return;
	PIN_ERR_CLEAR_ERR(ebufp);

	/***********************************************************
	 * Create outgoing flist
	 ***********************************************************/
	r_flistp = PIN_FLIST_CREATE(ebufp);
	*o_flistpp = r_flistp;

	/***********************************************************
	 * Get (and add) the object poid.
	 ***********************************************************/
	o_pdp = (poid_t *)PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
	PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_POID, (void *)o_pdp, ebufp);


	/***********************************************************
	 * Get the input login.
	 ***********************************************************/
	login = (char *)PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_LOGIN, 1, ebufp);
	
	/* 
	 *  LOGIN could be NULL if SET_LOGIN is called to set an alias entry
	 *  during SERVICE creation
	 */
	if (login != NULL) {
		count =  PIN_FLIST_ELEM_COUNT(i_flistp, PIN_FLD_ALIAS_LIST, 
					      ebufp);
		/***************************************************
		 * Try to validate based on /config/fld_validate 
		 * (Login) obj, if it is a new service with alias
		 * list or modifying a login with no alias list
		 **************************************************/
		if ((count < 1) || (fm_utils_op_is_ancestor(
			connp->coip, PCM_OP_CUST_CREATE_SERVICE))) {
			fm_cust_pol_validate_fld_value( ctxp, i_flistp, 
							i_flistp, r_flistp, 
							PIN_FLD_LOGIN, 
							0, "Login", 1, ebufp);
		}
	}

	/***********************************************************
         * Try to validate all of the alias list
         ***********************************************************/
	a_flistp = NULL;
	for ( 
		flistp = PIN_FLIST_ELEM_GET_NEXT( i_flistp, PIN_FLD_ALIAS_LIST,
						&elemid, 0, &cookie, ebufp );
		ebufp->pin_err == PIN_ERR_NONE;
		flistp = PIN_FLIST_ELEM_GET_NEXT( i_flistp, PIN_FLD_ALIAS_LIST,
						&elemid, 0, &cookie, ebufp )
	) {
		/***********************************************************
      	 	 * Prep the return flist
       		 ***********************************************************/
		if ( !a_flistp ) {
			a_flistp = PIN_FLIST_CREATE(ebufp);
		}

		if ( !flistp ) continue;

		/***********************************************************
      	 	 * Try to validate based on /config/fld_validate 
		 * (name) obj.  but since we cannot validate a value in
		 * PIN_FLD_NAME due to the facte we have to pass PIN_FLD_NAME
		 * as the name of the validation rule.  I will cady the 
		 * the PIN_FLD_NAME in a PIN_FLD_LOGIN and then manipulate 
		 * the error output if there is one.
       		 ***********************************************************/
		vp = PIN_FLIST_FLD_GET( flistp, PIN_FLD_NAME, 0, ebufp );
		PIN_FLIST_FLD_SET( flistp, PIN_FLD_LOGIN, vp, ebufp );
		fm_cust_pol_validate_fld_value( ctxp, i_flistp, flistp, 
			a_flistp, PIN_FLD_LOGIN, 0, "Login", 1, ebufp);
		PIN_FLIST_FLD_DROP( flistp, PIN_FLD_LOGIN, ebufp );

		if (PIN_FLIST_ELEM_COUNT(a_flistp, PIN_FLD_FIELD, ebufp) != 0) {
			/***************************************************
			 * There is a validation error so normalize it to
			 * the input flist
			 ***************************************************/
			pin_fld_num_t field = PIN_FLD_ALIAS_LIST;
			PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_FIELD_NUM,
					(void *)&field, ebufp);
			PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_ELEMENT_ID,
					(void *)&elemid, ebufp);
			result = PIN_CUST_VERIFY_FAILED;
			PIN_FLIST_FLD_SET(a_flistp, PIN_FLD_RESULT,
					(void *)&result, ebufp);
			count = PIN_FLIST_ELEM_COUNT(r_flistp, PIN_FLD_FIELD, 
					ebufp);
			PIN_FLIST_ELEM_PUT(r_flistp, a_flistp, PIN_FLD_FIELD,
					count, ebufp);
			a_flistp = PIN_FLIST_ELEM_GET( a_flistp, PIN_FLD_FIELD, 
					PIN_ELEMID_ANY, 0, ebufp );
			field = PIN_FLD_NAME;
			PIN_FLIST_FLD_SET( a_flistp, PIN_FLD_FIELD_NUM, 
					(void *)&field, ebufp );
			a_flistp = NULL;
		}

	}
	if ( ebufp->pin_err == PIN_ERR_NOT_FOUND ) {
		PIN_ERR_CLEAR_ERR( ebufp );
	}

	/***************************************************************
	 * clean up any last unused a_flistp
	 ***************************************************************/
	PIN_FLIST_DESTROY_EX( &a_flistp, NULL );

	if (PIN_FLIST_ELEM_COUNT(r_flistp, PIN_FLD_FIELD, ebufp) != 0) {
               	result = PIN_CUST_VERIFY_FAILED;
		goto Done;
	}
	
	/***************************************************************
	 * Get the poid type to check service type. Used for E2K service
	 ***************************************************************/
	db_no = PIN_POID_GET_DB(o_pdp);
	subtype = PIN_POID_GET_TYPE(o_pdp);
	if ( subtype && 
		(strcmp(subtype, PIN_MSEXCHANGE_SERVICE_TYPE_USER) == 0)){
		msexchange_service_type = PIN_MSEXCHANGE_SERVICE_USER;
	}
	if ( subtype && 
		(strcmp(subtype, PIN_MSEXCHANGE_SERVICE_TYPE_FIRSTADMIN) == 0)){
		msexchange_service_type = PIN_MSEXCHANGE_SERVICE_FIRSTADMIN;
	}

	/***********************************************************
	 * Reject login change for /service/gsm type and subtype
	 ***********************************************************/
	if (subtype &&
		(!(strncmp(subtype, "/service/gsm", 12)))) {
		/***************************************************
		 * if user try to change the login and it's not allowed
		 ***************************************************/
		char * login = NULL;
		login = (char *)PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_LOGIN,
			1, ebufp);
		if (login == NULL) {
			goto Done;
		} else {
			if (!(fm_utils_op_is_ancestor(connp->coip,
				PCM_OP_CUST_COMMIT_CUSTOMER))&&
			!(fm_utils_op_is_ancestor(connp->coip,
				PCM_OP_CUST_MODIFY_CUSTOMER))&&
			!(flags & PCM_OPFLG_CUST_REGISTRATION)) {
				(void)fm_cust_pol_valid_add_fail(r_flistp,
				PIN_FLD_LOGIN, (u_int)NULL,
				PIN_CUST_VAL_ERR_REJECT,
				PIN_CUST_REJECT_VALUE_ERR_MSG,
				(void *)login, ebufp);
				result = PIN_CUST_VERIFY_FAILED;
				goto Done;
			} 
		}
	}

	/***********************************************************
	* Reject login change for /service/telco type and subtype
	***********************************************************/
        if (subtype &&
            ((!(strncmp(subtype, "/service/telco/", 15))) ||
                (!(strcmp(subtype, "/service/telco"))))) {
                /***************************************************
                 * if user try to change the login and it's not allowed
                 ***************************************************/
                char * login = NULL;
                login = (char *)PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_LOGIN,
                                                  1, ebufp);
		if (login == NULL) {
			goto Done;
		} else {
			if (!(fm_utils_op_is_ancestor(connp->coip,
					     PCM_OP_CUST_COMMIT_CUSTOMER))&&
			!(fm_utils_op_is_ancestor(connp->coip,
					     PCM_OP_CUST_MODIFY_CUSTOMER))&&
			!(flags & PCM_OPFLG_CUST_REGISTRATION)) {
				(void)fm_cust_pol_valid_add_fail(r_flistp,
				PIN_FLD_LOGIN, (u_int)NULL,
				PIN_CUST_VAL_ERR_REJECT,
				PIN_CUST_REJECT_VALUE_ERR_MSG,
				(void *)login, ebufp);
				result = PIN_CUST_VERIFY_FAILED;
				goto Done;
			}
                }
        }
	/***********************************************************
	 * If we're still ok, check uniqueness, in case of multi_db 
	 * and single-schema TT env.
	 * In case of multi-db approach and  single-schema TT env, we 
	 * need to check in the uniqueness table, otherwise proceed 
	 * as before.
	 * We need to use both the service type and the login.
         ***********************************************************/
	if (cm_fm_is_multi_db() || cm_fm_is_timesten()) {

		int64		primary_db_no = 0;
		int64		trans_db_no = 0;
		pcm_context_t	*vctxp = NULL;
		poid_t		*trans_poidp = NULL;
		pin_flist_t	*trans_flistp = NULL;

		/***************************************************
 	 	 * Put in all the fields we need to insert the
 	 	 *  entry into the uniqueness table
 	 	 ***************************************************/
		cm_fm_get_primary_db_no(&primary_db_no, ebufp);

                trans_flistp = pcm_get_trans_flist(ctxp);
                if ( trans_flistp ) {
			trans_poidp = PIN_FLIST_FLD_GET(trans_flistp, 
							PIN_FLD_POID, 0, ebufp);
			trans_db_no = PIN_POID_GET_DB( trans_poidp );
                } else {
			trans_db_no = primary_db_no;
		}
		PIN_FLIST_DESTROY_EX( &trans_flistp, NULL );

		/* 
		 *if we are looking at a different db then we currently have a 
		 * transaction in then we need a new context 
		 */
		if ( primary_db_no != trans_db_no ) {
			PCM_CONTEXT_OPEN(&vctxp, (pin_flist_t *)0, ebufp);
		} else {
			vctxp = ctxp;
		}

		fm_cust_pol_valid_login_check_uniquiness_table( vctxp,
        				primary_db_no, 
					msexchange_service_type, 
					i_flistp, r_flistp, ebufp );

		if ( primary_db_no != trans_db_no ) {
			PCM_CONTEXT_CLOSE(vctxp, 0, NULL);
		}

		
	} else {

		/*********************************************************
		 * This happens only for a single db installation
		 * where we don't have to search in the uniqueness table.
		 ********************************************************/

		fm_cust_pol_valid_login_check_uniquiness_service( ctxp,
					db_no, msexchange_service_type, 
					i_flistp, r_flistp, ebufp );
	}

	if (PIN_FLIST_ELEM_COUNT(r_flistp, PIN_FLD_FIELD, ebufp) != 0) {
               	result = PIN_CUST_VERIFY_FAILED;
		goto Done;
	}

Done:
	PIN_FLIST_DESTROY_EX(&s_flistp, NULL);
	PIN_FLIST_DESTROY_EX(&a_flistp, NULL);
	/***********************************************************
         * Set the overall result and return.
         ***********************************************************/
        PIN_FLIST_FLD_SET(r_flistp, PIN_FLD_RESULT, (void *)&result, ebufp);

	/***********************************************************
	 * Error?
	 ***********************************************************/
	if (PIN_ERR_IS_ERR(ebufp)) {
		PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			"fm_cust_pol_valid_login 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;
}
/*******************************************************************
 * fm_zonemap_pol_get_lineage_load_zonemap():
 *
 *	Retrieve and process the named zonemap.
 *
 *******************************************************************/
static int32 
fm_zonemap_pol_get_lineage_load_zonemap(
	pcm_context_t		*pCtx, 
	const char		*pszTarget, 
	poid_t			*pRoutingPoid, 
	poid_t			**ppZonemapPoid,
	poid_t			*pBrandPoid, 
	Blob_t			**ppBuffer, 
	int32			*pnDefaultSearchMode, 
	pin_errbuf_t		*ebufp) 
{

	pin_flist_t		*pGetZonemapInFlist = NULL;
	pin_flist_t		*pGetZonemapOutFlist = NULL;
	pin_flist_t		*pZonemaps = NULL;
	poid_t			*pSearchPoid = NULL;
	pin_buf_t		*pBuf = NULL;
	Blob_t			*pTempBufAddr = NULL;
	int32			nRetVal = PIN_BOOLEAN_TRUE;
	pin_zonemap_data_type_t	dt = PIN_ZONEMAP_DATA_BINARY;
	int32			*pnSearchMode;
	
	PIN_HEAP_VAR;

	/* Debug */
	PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG, 
		"fm_zonemap_pol_get_lineage_load_zonemap starting");

	/*
	 * Create flist for retrieving matrix
	 */
	pGetZonemapInFlist = PIN_FLIST_CREATE(ebufp);

	pSearchPoid = PIN_POID_CREATE(PIN_POID_GET_DB((poid_t *) pRoutingPoid), 
		"/zonemap", -1, ebufp);
	PIN_FLIST_FLD_PUT(pGetZonemapInFlist, PIN_FLD_POID, 
		(void *)pSearchPoid, ebufp);

	PIN_FLIST_FLD_SET(pGetZonemapInFlist, PIN_FLD_NAME, 
		(void *) pszTarget, ebufp);

	PIN_FLIST_FLD_SET(pGetZonemapInFlist, PIN_FLD_ZONEMAP_DATA_TYPE, 
		(void *) &dt, ebufp);

	PIN_FLIST_FLD_SET(pGetZonemapInFlist, PIN_FLD_ACCOUNT_OBJ,
		(void *) pBrandPoid, ebufp);

	/* 
	 * Call zonemap loading opcode (automatically seaches)
	 */
	PCM_OP(pCtx, PCM_OP_ZONEMAP_GET_ZONEMAP, 0, pGetZonemapInFlist, 
		&pGetZonemapOutFlist, ebufp);

	/*
	 * Process matrix
	 */
	pZonemaps = PIN_FLIST_ELEM_GET(pGetZonemapOutFlist,
				PIN_FLD_ZONEMAPS, 
				PIN_ELEMID_ANY, 1, ebufp);

	if (pZonemaps != NULL) {
		/*
		 * Found a zonemap, set current matrix poid 
		 */	
		PIN_SET_GLOBAL_HEAP;

		*ppZonemapPoid = PIN_POID_COPY((poid_t*) 
			PIN_FLIST_FLD_GET(pZonemaps,PIN_FLD_POID, 0, ebufp),
			ebufp);

		PIN_RESET_GLOBAL_HEAP;

		/*
		 * Grab default search mode (NULL means no default)
		 */
		pnSearchMode = (int32*) PIN_FLIST_FLD_GET(pZonemaps,
					PIN_FLD_ZONEMAP_SEARCH_TYPE, 1, ebufp);

		/* Did we find a default search mode? */
		if (pnSearchMode != NULL) {
			/* Yes: copy value to input */
			*pnDefaultSearchMode = *pnSearchMode;
		}
		else {
			/* No: indicate no default search mode */
			pnDefaultSearchMode = NULL;
		}

		/*
		 * Get address of buffer
		 */
		pBuf = (pin_buf_t *)PIN_FLIST_FLD_GET(pZonemaps, 
				PIN_FLD_ZONEMAP_DATA_DERIVED, 1, ebufp);

		if (pBuf != NULL &&
			(pBuf->data != NULL)) { 
			/* get the actual blob */
			pTempBufAddr = (Blob_t *)(pBuf->data);
	
			PIN_SET_GLOBAL_HEAP;

			/* Allocate memory to hold buffer on global heap */
			*ppBuffer = (Blob_t*) malloc(pTempBufAddr->blob_size);

			/* Copy buffer to global mem */
			memcpy(*ppBuffer, pTempBufAddr, 
				pTempBufAddr->blob_size);

			PIN_RESET_GLOBAL_HEAP;

		}
		else {
			*ppBuffer = NULL;
		
			PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_WARNING,
				    "fm_zonemap_pol_get_lineage_load_zonemap: "
				    "zonemap is empty!", ebufp);
		}
	}
	else {
		/*
		 * No zonemap found
		 */
		nRetVal = PIN_BOOLEAN_FALSE;
	}

	/*
	 * Clean up
	 */
	PIN_FLIST_DESTROY_EX(&pGetZonemapInFlist, NULL);
	PIN_FLIST_DESTROY_EX(&pGetZonemapOutFlist, NULL);

	if (PIN_ERR_IS_ERR(ebufp)) {
		nRetVal = PIN_BOOLEAN_FALSE;

		if (ebufp->pin_err == PIN_ERR_NO_MATCH) {

			PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG,
			   "fm_zonemap_pol_get_lineage_load_zonemap: "
			   "no matrix");

			PIN_ERR_CLEAR_ERR(ebufp);

		} else {

			PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
			    "fm_zonemap_pol_get_lineage_load_zonemap: error", 
			    ebufp);

		}

	}

	/* Debug */
	PIN_ERR_LOG_MSG(PIN_ERR_LEVEL_DEBUG, 
		"fm_zonemap_pol_get_lineage_load_zonemap returning");

	return nRetVal;
}