Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement amendment.amend() #125

Open
xer0x opened this issue Apr 27, 2015 · 15 comments
Open

implement amendment.amend() #125

xer0x opened this issue Apr 27, 2015 · 15 comments

Comments

@xer0x
Copy link
Contributor

xer0x commented Apr 27, 2015

The amend() method isn't implemented yet. It should generate the XML below. You can use amendment.create() as a work-around, but amend() is the recommended way to modify subscriptions since WSDL 29+.

See the Zuora docs for more here:
https://knowledgecenter.zuora.com/BC_Developers/SOAP_API/D_Use_Cases_Code_Samples/DJ_Cancel_a_Subscription_%28Amendment%29

The output XML should look similar to this:

<api:amend>
   <api:requests>
      <api:Amendments>
         <obj:ContractEffectiveDate>2010-01-01T20:44:54.718+05:30</obj:ContractEffectiveDate>
         <obj:CustomerAcceptanceDate>2010-01-01T20:44:54.718+05:30</obj:CustomerAcceptanceDate>
         <obj:Description>Cancel a subscription amendment</obj:Description>
         <obj:EffectiveDate>2010-01-01T20:44:54.718+05:30</obj:EffectiveDate>
         <obj:Name>Cancel a subscription amendment</obj:Name>
         <obj:ServiceActivationDate>2010-01-01T20:44:54.718+05:30</obj:ServiceActivationDate>
         <obj:Status>Completed</obj:Status>
         <obj:SubscriptionId>402892c42ce80787012ce80ea1aa0014</obj:SubscriptionId>
         <obj:Type>Cancellation</obj:Type>
      </api:Amendments>
      <api:PreviewOptions>
         <api:EnablePreviewMode>true</api:EnablePreviewMode>
      </api:PreviewOptions>
   </api:requests>
</api:amend>
@arenoux
Copy link
Contributor

arenoux commented Oct 14, 2015

👍
Any chance to have this method implemented here soon ?

@xer0x
Copy link
Contributor Author

xer0x commented Oct 14, 2015

Try using amendment.create() first. If that doesn't work for you, then maybe you or I can get subscription.amend() working. I haven't implemented subscription.amend() because using the original CRUD style methods was easiest. Hopefully this is a reasonable workaround for you:

// Add our amendment attributes
var amendment = {
  Name:                  'Fix-missed-destroy',
  Type:                  'Cancellation',
  SubscriptionId:        subscription.Id,
  EffectiveDate:         nextDay.toISOString(),
  ContractEffectiveDate: nextDay.toISOString()
};

// Connect to your Zuora api
var z = zuora.connect();

// Create our amendment on Zuora
z.amendment.create(amendment, {
  CallOptions: {useSingleTransaction: true}
}, function (err, results) {
  // Handle the results. This example will send all errors to console.log.
  if (err) return console.log(err);
  if (result.length > 0) {
    var success = result[0][0].Success;
    if (!success) {
      var errors = result[0][0].Errors;
      for (var i=0; i<errors.length; i++) {
        console.log ( errors[i].Message );
      }
    }
  }
});

I'll try this week to add some tests and maybe get to subscription.amend(). Also you can use amendment.delete({id: ID}, cb) to tidy up as you test this out.

@arenoux
Copy link
Contributor

arenoux commented Oct 15, 2015

Thanks for your answer.
My problem is that I want to update RatePlanCharges.
I'm trying do an amendment with type=UpdateProduct. (http://knowledgecenter.zuora.com/BC_Developers/SOAP_API/E1_SOAP_API_Object_Reference/Amendment/Update_a_Product_(Amendment))
Im using WSDL 70.0

If I want to use the create method, the payload to send should look like :

<ns1:create xmlns:ns1="http://api.zuora.com/"> 
  <ns1:zObjects xmlns:ns2="http://object.api.zuora.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:Amendment">  
    <ns2:ContractEffectiveDate>2010-07-21</ns2:ContractEffectiveDate>  
    <ns2:CustomerAcceptanceDate>2010-07-21</ns2:CustomerAcceptanceDate>  
    <ns2:EffectiveDate>2010-07-21</ns2:EffectiveDate>  
    <ns2:Name>test_amend1279683889873</ns2:Name>  
    <ns2:RatePlanData>    
       <ns1:RatePlan xsi:type="ns2:RatePlan">      
         <ns2:AmendmentSubscriptionRatePlanId>402892ca29f3191a0129f31a84d000a8
         </ns2:AmendmentSubscriptionRatePlanId>    
       </ns1:RatePlan>    
         <ns1:RatePlanChargeData>      
           <ns1:RatePlanCharge xsi:type="ns2:RatePlanCharge">        
             <ns2:Description>111111</ns2:Description>        
             <ns2:Price>1000</ns2:Price>        
             <ns2:ProductRatePlanChargeId>402892ca29f3191a0129f31a82b00099
             </ns2:ProductRatePlanChargeId>      
           </ns1:RatePlanCharge>    
         </ns1:RatePlanChargeData>  
    </ns2:RatePlanData>
    <ns2:ServiceActivationDate>2010-07-21</ns2:ServiceActivationDate>  
    <ns2:SubscriptionId>402892ca29f3191a0129f31a86ad00ac</ns2:SubscriptionId>  
    <ns2:Type>UpdateProduct</ns2:Type>
  </ns1:zObjects>
</ns1:create>

With you example, if I update the amendment var:

var amendment = {
                Name: "TEST Soap Node",
                Type: "UpdateProduct",
                SubscriptionId: "subscription.Id",
                EffectiveDate: "2015-10-16",
                ContractEffectiveDate: "2015-10-16",
                RatePlanData: {
                    RatePlan: {
                        AmendmentSubscriptionRatePlanId: "ratePlan.Id"
                    },
                    RatePlanChargeData: [{
                        RatePlanCharge: {
                            ProductRatePlanChargeId: "productRatePlan.Id",
                            IncludedUnits: 123,
                            Quantity: 456
                        }
                    }]
                },
            };

The generated payload (obtained with options.verboseLog=true). looks like :

<zns:create>
    <zns:zObjects xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"ons:Amendment\">
    <ons:Name>
    <![CDATA[TEST Soap Node]]>
</ons:Name>
<ons:Type>UpdateProduct</ons:Type>
<ons:SubscriptionId>2c92c0fa501d435d015060e634654e7d</ons:SubscriptionId>
<ons:EffectiveDate>2015-10-16</ons:EffectiveDate>
<ons:ContractEffectiveDate>2015-10-16</ons:ContractEffectiveDate>
<ons:RatePlanData>[object Object]</ons:RatePlanData>
</zns:zObjects>
</zns:create>

It seems that the RatePlanData part is not generated the right way...
So I think I can't do what I want with the existing version of your library...

Thats the reason why i'm looking for the implementation of .amend() method :p

@xer0x
Copy link
Contributor Author

xer0x commented Oct 16, 2015

Ah thanks, I see what you're trying to do.

<ons:RatePlanData>[object Object]</ons:RatePlanData>

There's a couple things that could fix that. The function making the XML is naively expecting a shallow array of attributes. We could fix it to check if any nested objects are present. The node-soap library I'm using already includes functions to do this. It might be as simple as switching to use them.

Otherwise, yes implementing .amend() seems like a good idea. I'll try to take a look at it tomorrow.

@arenoux
Copy link
Contributor

arenoux commented Oct 16, 2015

I forked the project and made changes in xmlFromFieldList function of lib/xml.js so that object can be parsed as expected :)

It's not ready for an eventual Pull Request here because i'm doing tricky stuff to get the right znstype for my use case (ratePlan and ratePlanCharge...).

var xmlFromFieldList = function (zObject, ns) {
  if (common.isString(zObject)) return zObject;
  return Object.keys(zObject).map(function(field) {
    var znstype = '';
    ns = ns || ns1;

    if(field.toLowerCase() === 'rateplan' || field.toLowerCase() === 'rateplancharge'){
      ns=ns1;
      znstype = 'xsi:type="' + ns2 + ':' + field + '"';
    }

    if(Array.isArray(zObject[field])){
      return tag(field, ns, escapeUserFields(field, zObject[field].map(function(zObj) {
        return xmlFromFieldList(zObj, ns2);
      }).join('\n'), znstype));
    }else if(typeof zObject[field] === 'object'){
      return tag(field, ns, escapeUserFields(field, xmlFromFieldList(zObject[field], ns2)), znstype);
    }else{
      return tag(field, ns, escapeUserFields(field, zObject[field]));
    }
  }).join('\n');
};

Anyway, if you are up to implement the .amend() it would be great :)

@xer0x
Copy link
Contributor Author

xer0x commented Oct 16, 2015

Cool. Yeah, Zuora's namespaces really do get in the way.

@yousefcodes
Copy link

Hi xer0x,

I'm running into the same need for the ammend() call. Is the feature coming?

@yousefcodes
Copy link

Hi,

I added an implementation for amendment.amend() and I have a pull request up.

Thanks!

@xer0x
Copy link
Contributor Author

xer0x commented Nov 4, 2015

Sweet that was fast. I'll check it out.

@yousefcodes
Copy link

Tried installing the latest, 1.2.0 doesn't seem to include the recently merged changes yet.

@arenoux
Copy link
Contributor

arenoux commented Nov 4, 2015

Maybe you should have wait a bit before cloning my branch changes from my own repo and make a pull request here...
My code was just a quick patch to handle a particular use-case (the create() for an amendment) ...

I think that the makeZobject function should only be called to create Zuora Objects...

According to Zuora documentation the new amend() function is not managing zObjects...

I think that we should have a new function in charge of parsing this new type of payload...
Otherwise, you will parse amend() payload like a zObject and will obtain unwanted results.
e.g.

...
<ns1:RatePlan xsi:type="ns2:RatePlan">
...

instead of

...
<ns1:RatePlan>
...

@xer0x
Copy link
Contributor Author

xer0x commented Nov 4, 2015

+1 arenoux. Sorry for prematurely jumping ahead on this. I don't have much time for working on this, so I'm over eager to slurp up changes. You're absolutely right that makeZobject should only make Zuora Objects.

I've been looking at switching the XML generation to use the existing functions in Node-Soap. Zuora's use of mixed namespaces is tricky for the existing code. It's too naive about the types of payload that Zuora needs. A better way of creating would be very welcome.

I tried to keep the namespaces out of the javascript objects. Maybe for this we need to be able to force the namespace to match what Zuora needs. Thoughts?

@yousefcodes
Copy link

I agree, although a working amend() call is better than a broken one :)

I want to iterate over it. The code was already considering non-zObject "request" elements for instance.

Best regards,

Yousef Elreda

On Nov 4, 2015, at 12:29 PM, Drew Miller notifications@github.com wrote:

+1 arenoux. Sorry for prematurely jumping ahead on this. I don't have much time for working on this, so I'm over eager to slurp up changes. You're absolutely right that makeZobject should only make Zuora Objects.

I've been looking at switching the XML generation to use the existing functions in Node-Soap. Zuora's use of mixed namespaces is tricky for the existing code. It's too naive about the types of payload that Zuora needs. A better way of creating would be very welcome.

I tried to keep the namespaces out of the javascript objects. Maybe for this we need to be able to force the namespace to match what Zuora needs.


Reply to this email directly or view it on GitHub.

@yousefcodes
Copy link

Unfortunately version 1.4 broke the amend functionality I had implemented. Any plans for this functionality to come back? Based on the what I see in the new implementation of xml.js, it needs a full re-write.

@sgaestel
Copy link
Contributor

sgaestel commented Mar 7, 2016

@yousefcodes Are you talking about a real amend() call (not available yet) or a create() on amendment object ?
I just noticed a bug in my xml parsing rework, working on the fix to submit it here.
Could you provide the payload you are sending so that I can see if the root cause is the identified one ?
Thanks.

I'll implement the amend() functionnality soon as it should be easier now with my updates (similar to the subscribe() call).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants