netsuite 0.8.10 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/dependabot.yml +14 -0
  4. data/.github/workflows/codeql-analysis.yml +70 -0
  5. data/.github/workflows/main.yml +7 -4
  6. data/Gemfile +5 -3
  7. data/HISTORY.md +56 -2
  8. data/README.md +94 -38
  9. data/lib/netsuite/actions/add.rb +7 -2
  10. data/lib/netsuite/actions/attach_file.rb +87 -0
  11. data/lib/netsuite/actions/delete.rb +18 -1
  12. data/lib/netsuite/actions/delete_list.rb +1 -1
  13. data/lib/netsuite/actions/get.rb +1 -1
  14. data/lib/netsuite/actions/get_deleted.rb +1 -1
  15. data/lib/netsuite/actions/get_list.rb +1 -1
  16. data/lib/netsuite/actions/initialize.rb +2 -2
  17. data/lib/netsuite/actions/search.rb +20 -7
  18. data/lib/netsuite/configuration.rb +16 -3
  19. data/lib/netsuite/records/account.rb +0 -1
  20. data/lib/netsuite/records/accounting_period.rb +1 -1
  21. data/lib/netsuite/records/assembly_component.rb +0 -2
  22. data/lib/netsuite/records/assembly_item.rb +2 -2
  23. data/lib/netsuite/records/assembly_unbuild.rb +0 -1
  24. data/lib/netsuite/records/cash_refund.rb +0 -1
  25. data/lib/netsuite/records/cash_refund_item.rb +1 -1
  26. data/lib/netsuite/records/cash_sale.rb +1 -2
  27. data/lib/netsuite/records/contact.rb +0 -1
  28. data/lib/netsuite/records/credit_memo.rb +1 -1
  29. data/lib/netsuite/records/currency_rate.rb +0 -1
  30. data/lib/netsuite/records/custom_record.rb +1 -1
  31. data/lib/netsuite/records/customer.rb +224 -23
  32. data/lib/netsuite/records/customer_deposit.rb +0 -1
  33. data/lib/netsuite/records/customer_payment.rb +0 -1
  34. data/lib/netsuite/records/customer_refund.rb +1 -2
  35. data/lib/netsuite/records/deposit.rb +0 -1
  36. data/lib/netsuite/records/deposit_application.rb +0 -1
  37. data/lib/netsuite/records/description_item.rb +3 -3
  38. data/lib/netsuite/records/discount_item.rb +1 -1
  39. data/lib/netsuite/records/employee.rb +1 -1
  40. data/lib/netsuite/records/estimate.rb +0 -1
  41. data/lib/netsuite/records/file.rb +1 -1
  42. data/lib/netsuite/records/gift_certificate_item.rb +1 -1
  43. data/lib/netsuite/records/inbound_shipment.rb +0 -1
  44. data/lib/netsuite/records/inventory_item.rb +237 -38
  45. data/lib/netsuite/records/inventory_number.rb +0 -1
  46. data/lib/netsuite/records/invoice.rb +2 -2
  47. data/lib/netsuite/records/item_availability.rb +46 -0
  48. data/lib/netsuite/records/item_fulfillment.rb +4 -2
  49. data/lib/netsuite/records/item_fulfillment_package_fed_ex.rb +28 -0
  50. data/lib/netsuite/records/item_fulfillment_package_fed_ex_list.rb +32 -0
  51. data/lib/netsuite/records/item_fulfillment_package_ups.rb +27 -0
  52. data/lib/netsuite/records/item_fulfillment_package_ups_list.rb +32 -0
  53. data/lib/netsuite/records/item_fulfillment_package_usps.rb +26 -0
  54. data/lib/netsuite/records/item_fulfillment_package_usps_list.rb +32 -0
  55. data/lib/netsuite/records/item_group.rb +3 -3
  56. data/lib/netsuite/records/item_option_custom_field.rb +52 -0
  57. data/lib/netsuite/records/item_receipt.rb +0 -1
  58. data/lib/netsuite/records/item_vendor.rb +10 -1
  59. data/lib/netsuite/records/job.rb +0 -1
  60. data/lib/netsuite/records/kit_item.rb +2 -2
  61. data/lib/netsuite/records/location.rb +0 -1
  62. data/lib/netsuite/records/lot_numbered_assembly_item.rb +1 -1
  63. data/lib/netsuite/records/lot_numbered_inventory_item.rb +226 -82
  64. data/lib/netsuite/records/matrix_option_list.rb +16 -0
  65. data/lib/netsuite/records/non_inventory_purchase_item.rb +1 -1
  66. data/lib/netsuite/records/non_inventory_resale_item.rb +157 -21
  67. data/lib/netsuite/records/non_inventory_sale_item.rb +134 -22
  68. data/lib/netsuite/records/null_field_list.rb +15 -0
  69. data/lib/netsuite/records/opportunity.rb +0 -1
  70. data/lib/netsuite/records/other_charge_sale_item.rb +2 -2
  71. data/lib/netsuite/records/payment_item.rb +3 -3
  72. data/lib/netsuite/records/payroll_item.rb +0 -1
  73. data/lib/netsuite/records/purchase_order.rb +0 -1
  74. data/lib/netsuite/records/record_ref.rb +1 -1
  75. data/lib/netsuite/records/return_authorization.rb +1 -0
  76. data/lib/netsuite/records/sales_order.rb +2 -2
  77. data/lib/netsuite/records/sales_order_item.rb +2 -1
  78. data/lib/netsuite/records/serialized_assembly_item.rb +1 -1
  79. data/lib/netsuite/records/serialized_inventory_item.rb +2 -2
  80. data/lib/netsuite/records/serialized_inventory_item_location.rb +0 -1
  81. data/lib/netsuite/records/service_resale_item.rb +125 -21
  82. data/lib/netsuite/records/service_sale_item.rb +1 -2
  83. data/lib/netsuite/records/{customer_subscription.rb → subscription.rb} +1 -1
  84. data/lib/netsuite/records/subscriptions_list.rb +10 -0
  85. data/lib/netsuite/records/subsidiary.rb +0 -1
  86. data/lib/netsuite/records/subtotal_item.rb +3 -4
  87. data/lib/netsuite/records/transfer_order.rb +0 -1
  88. data/lib/netsuite/records/translation.rb +17 -0
  89. data/lib/netsuite/records/translation_list.rb +11 -0
  90. data/lib/netsuite/records/vendor.rb +0 -1
  91. data/lib/netsuite/records/vendor_bill.rb +0 -1
  92. data/lib/netsuite/records/work_order.rb +0 -1
  93. data/lib/netsuite/records/work_order_item.rb +0 -1
  94. data/lib/netsuite/support/actions.rb +2 -0
  95. data/lib/netsuite/support/fields.rb +2 -0
  96. data/lib/netsuite/support/records.rb +22 -5
  97. data/lib/netsuite/support/sublist.rb +2 -2
  98. data/lib/netsuite/utilities/strings.rb +15 -0
  99. data/lib/netsuite/utilities.rb +25 -13
  100. data/lib/netsuite/version.rb +1 -1
  101. data/lib/netsuite.rb +15 -3
  102. data/netsuite.gemspec +5 -2
  103. data/spec/netsuite/actions/add_spec.rb +39 -1
  104. data/spec/netsuite/actions/attach_file_spec.rb +59 -0
  105. data/spec/netsuite/actions/delete_spec.rb +74 -14
  106. data/spec/netsuite/actions/get_select_value_spec.rb +43 -0
  107. data/spec/netsuite/actions/search_spec.rb +205 -0
  108. data/spec/netsuite/configuration_spec.rb +35 -0
  109. data/spec/netsuite/records/cash_refund_item_spec.rb +1 -1
  110. data/spec/netsuite/records/credit_memo_spec.rb +14 -0
  111. data/spec/netsuite/records/customer_spec.rb +287 -20
  112. data/spec/netsuite/records/inventory_item_spec.rb +239 -22
  113. data/spec/netsuite/records/invoice_spec.rb +43 -0
  114. data/spec/netsuite/records/item_availability_spec.rb +59 -0
  115. data/spec/netsuite/records/item_fulfillment_package_fed_ex_list_spec.rb +27 -0
  116. data/spec/netsuite/records/item_fulfillment_package_ups_list_spec.rb +27 -0
  117. data/spec/netsuite/records/item_fulfillment_package_usps_list_spec.rb +27 -0
  118. data/spec/netsuite/records/item_option_custom_field_spec.rb +27 -0
  119. data/spec/netsuite/records/item_vendor_list_spec.rb +2 -5
  120. data/spec/netsuite/records/item_vendor_spec.rb +14 -2
  121. data/spec/netsuite/records/lot_numbered_inventory_item_spec.rb +247 -0
  122. data/spec/netsuite/records/matrix_option_list_spec.rb +26 -0
  123. data/spec/netsuite/records/non_inventory_resale_item_spec.rb +159 -24
  124. data/spec/netsuite/records/non_inventory_sale_item_spec.rb +135 -22
  125. data/spec/netsuite/records/null_field_list_spec.rb +30 -0
  126. data/spec/netsuite/records/return_authorization_spec.rb +62 -0
  127. data/spec/netsuite/records/sales_order_item_spec.rb +4 -3
  128. data/spec/netsuite/records/sales_order_spec.rb +46 -0
  129. data/spec/netsuite/records/service_resale_item_spec.rb +122 -17
  130. data/spec/netsuite/records/{customer_subscription_spec.rb → subscription_spec.rb} +2 -2
  131. data/spec/netsuite/records/{customer_subscriptions_list_spec.rb → subscriptions_list_spec.rb} +2 -2
  132. data/spec/netsuite/records/translation_list_spec.rb +34 -0
  133. data/spec/netsuite/records/translation_spec.rb +28 -0
  134. data/spec/netsuite/support/fields_spec.rb +16 -4
  135. data/spec/netsuite/support/records_spec.rb +33 -7
  136. data/spec/netsuite/support/search_result_spec.rb +12 -0
  137. data/spec/netsuite/utilities_spec.rb +10 -2
  138. data/spec/support/fixtures/add/add_file.xml +20 -0
  139. data/spec/support/fixtures/add/add_invoice.xml +9 -5
  140. data/spec/support/fixtures/attach/attach_file_to_sales_order.xml +16 -0
  141. data/spec/support/fixtures/attach/attach_file_to_sales_order_error.xml +20 -0
  142. data/spec/support/fixtures/delete/delete_customer_error.xml +21 -0
  143. data/spec/support/fixtures/delete/delete_customer_multiple_errors.xml +25 -0
  144. data/spec/support/fixtures/get_item_availability/get_item_availability.xml +46 -0
  145. data/spec/support/fixtures/get_select_value/empty_result.xml +22 -0
  146. data/spec/support/fixtures/get_select_value/item_fulfillment_ship_method.xml +43 -0
  147. data/spec/support/fixtures/search/basic_search_contact.xml +39 -0
  148. data/spec/support/fixtures/search/single_search_result.xml +46 -0
  149. metadata +78 -17
  150. data/lib/netsuite/core_ext/string/lower_camelcase.rb +0 -9
  151. data/lib/netsuite/records/customer_subscriptions_list.rb +0 -10
@@ -193,6 +193,30 @@ describe NetSuite::Actions::Search do
193
193
  expect(search.results.first.location_re_order_point).to eq('2565.0')
194
194
  expect(search.results.first.location_quantity_on_order).to eq('40000.0')
195
195
  end
196
+
197
+ it "should handle an ID search with basic non-field result columns" do
198
+ response = File.read('spec/support/fixtures/search/saved_search_item_2.xml')
199
+ savon.expects(:search)
200
+ .with(message: {
201
+ "searchRecord"=>{
202
+ "@xsi:type" =>"listAcct:ItemSearchAdvanced",
203
+ "@savedSearchId" =>42,
204
+ :content! =>{"listAcct:criteria"=>{}},
205
+ }
206
+ }).returns(response)
207
+
208
+ search = NetSuite::Records::InventoryItem.search(saved: 42)
209
+
210
+ results = search.results
211
+ custom_fields = results.map do |record|
212
+ record.custom_field_list.custom_fields.map(&:internal_id)
213
+ end.flatten.uniq
214
+ [
215
+ :location_quantity_available,
216
+ :location_re_order_point,
217
+ :location_quantity_on_order,
218
+ ].each {|field| expect(custom_fields).to include(field)}
219
+ end
196
220
  end
197
221
 
198
222
  context "advanced search" do
@@ -201,6 +225,187 @@ describe NetSuite::Actions::Search do
201
225
  end
202
226
 
203
227
  context "basic search" do
228
+ it "should handle a basic search matching on RecordRef using internalId" do
229
+ response = File.read('spec/support/fixtures/search/basic_search_contact.xml')
230
+ savon.expects(:search)
231
+ .with(message: {
232
+ "searchRecord" => {
233
+ :content! => {
234
+ "listRel:basic" => {
235
+ "platformCommon:company" => {
236
+ "@operator" => "anyOf",
237
+ "@xsi:type" => "platformCore:SearchMultiSelectField",
238
+ "platformCore:searchValue" => [
239
+ {
240
+ :content! => {},
241
+ "@xsi:type" => "platformCore:RecordRef",
242
+ "@type" => "account",
243
+ "@internalId" => 7497,
244
+ },
245
+ {
246
+ :content! => {},
247
+ "@xsi:type" => "platformCore:RecordRef",
248
+ "@type" => "account",
249
+ "@internalId" => 7270,
250
+ },
251
+ ],
252
+ },
253
+ },
254
+ },
255
+ "@xsi:type" => "listRel:ContactSearch",
256
+ },
257
+ }).returns(response)
258
+
259
+ search = NetSuite::Records::Contact.search(
260
+ basic: [{
261
+ field: 'company',
262
+ operator: 'anyOf',
263
+ value: [
264
+ NetSuite::Records::RecordRef.new(internal_id: 7497),
265
+ NetSuite::Records::RecordRef.new(internal_id: 7270),
266
+ ],
267
+ }],
268
+ )
269
+
270
+ expect(search.results.size).to eq(1)
271
+ end
272
+
273
+ it "should handle a basic search matching on RecordRef using externalId" do
274
+ response = File.read('spec/support/fixtures/search/basic_search_contact.xml')
275
+ savon.expects(:search)
276
+ .with(message: {
277
+ "searchRecord" => {
278
+ :content! => {
279
+ "listRel:basic" => {
280
+ "platformCommon:company" => {
281
+ "@operator" => "anyOf",
282
+ "@xsi:type" => "platformCore:SearchMultiSelectField",
283
+ "platformCore:searchValue" => [
284
+ {
285
+ :content! => {},
286
+ "@xsi:type" => "platformCore:RecordRef",
287
+ "@type" => "account",
288
+ "@externalId" => "external_abc",
289
+ },
290
+ {
291
+ :content! => {},
292
+ "@xsi:type" => "platformCore:RecordRef",
293
+ "@type" => "account",
294
+ "@externalId" => "external_xyz",
295
+ },
296
+ ],
297
+ },
298
+ },
299
+ },
300
+ "@xsi:type" => "listRel:ContactSearch",
301
+ },
302
+ }).returns(response)
303
+
304
+ search = NetSuite::Records::Contact.search(
305
+ basic: [{
306
+ field: 'company',
307
+ operator: 'anyOf',
308
+ value: [
309
+ NetSuite::Records::RecordRef.new(external_id: "external_abc"),
310
+ NetSuite::Records::RecordRef.new(external_id: "external_xyz"),
311
+ ],
312
+ }],
313
+ )
314
+
315
+ expect(search.results.size).to eq(1)
316
+ end
317
+
318
+ it "should handle a basic search matching on RecordRef using mix of internalId and externalId" do
319
+ response = File.read('spec/support/fixtures/search/basic_search_contact.xml')
320
+ savon.expects(:search)
321
+ .with(message: {
322
+ "searchRecord" => {
323
+ :content! => {
324
+ "listRel:basic" => {
325
+ "platformCommon:company" => {
326
+ "@operator" => "anyOf",
327
+ "@xsi:type" => "platformCore:SearchMultiSelectField",
328
+ "platformCore:searchValue" => [
329
+ {
330
+ :content! => {},
331
+ "@xsi:type" => "platformCore:RecordRef",
332
+ "@type" => "account",
333
+ "@internalId" => 7497,
334
+ },
335
+ {
336
+ :content! => {},
337
+ "@xsi:type" => "platformCore:RecordRef",
338
+ "@type" => "account",
339
+ "@externalId" => "external_xyz",
340
+ },
341
+ ],
342
+ },
343
+ },
344
+ },
345
+ "@xsi:type" => "listRel:ContactSearch",
346
+ },
347
+ }).returns(response)
348
+
349
+ search = NetSuite::Records::Contact.search(
350
+ basic: [{
351
+ field: 'company',
352
+ operator: 'anyOf',
353
+ value: [
354
+ NetSuite::Records::RecordRef.new(internal_id: 7497),
355
+ NetSuite::Records::RecordRef.new(external_id: "external_xyz"),
356
+ ],
357
+ }],
358
+ )
359
+
360
+ expect(search.results.size).to eq(1)
361
+ end
362
+
363
+ it "should handle a basic search matching on RecordRef using both internalId and externalId" do
364
+ response = File.read('spec/support/fixtures/search/basic_search_contact.xml')
365
+ savon.expects(:search)
366
+ .with(message: {
367
+ "searchRecord" => {
368
+ :content! => {
369
+ "listRel:basic" => {
370
+ "platformCommon:company" => {
371
+ "@operator" => "anyOf",
372
+ "@xsi:type" => "platformCore:SearchMultiSelectField",
373
+ "platformCore:searchValue" => [
374
+ {
375
+ :content! => {},
376
+ "@xsi:type" => "platformCore:RecordRef",
377
+ "@type" => "account",
378
+ "@internalId" => 7497,
379
+ "@externalId" => "external_abc",
380
+ },
381
+ {
382
+ :content! => {},
383
+ "@xsi:type" => "platformCore:RecordRef",
384
+ "@type" => "account",
385
+ "@externalId" => 7270,
386
+ },
387
+ ],
388
+ },
389
+ },
390
+ },
391
+ "@xsi:type" => "listRel:ContactSearch",
392
+ },
393
+ }).returns(response)
394
+
395
+ search = NetSuite::Records::Contact.search(
396
+ basic: [{
397
+ field: 'company',
398
+ operator: 'anyOf',
399
+ value: [
400
+ NetSuite::Records::RecordRef.new(internal_id: 7497, external_id: "external_abc"),
401
+ NetSuite::Records::RecordRef.new(external_id: 7270),
402
+ ],
403
+ }],
404
+ )
405
+
406
+ expect(search.results.size).to eq(1)
407
+ end
408
+
204
409
  skip "should handle searching basic fields"
205
410
  skip "should handle searching with joined fields"
206
411
  end
@@ -14,6 +14,20 @@ describe NetSuite::Configuration do
14
14
  config.reset!
15
15
  expect(config.attributes).to be_empty
16
16
  end
17
+
18
+ it 'ensures that attributes are not shared between threads' do
19
+ config.attributes[:blah] = 'something'
20
+ expect(config.attributes[:blah]).to eq('something')
21
+
22
+ thread = Thread.new {
23
+ config.attributes[:blah] = 'something_else'
24
+ expect(config.attributes[:blah]).to eq('something_else')
25
+ }
26
+
27
+ thread.join
28
+
29
+ expect(config.attributes[:blah]).to eq('something')
30
+ end
17
31
  end
18
32
 
19
33
  describe '#filters' do
@@ -476,4 +490,25 @@ describe NetSuite::Configuration do
476
490
  end
477
491
  end
478
492
 
493
+ describe '#proxy' do
494
+ it 'defaults to nil' do
495
+ expect(config.proxy).to be_nil
496
+ end
497
+
498
+ it 'can be set with proxy=' do
499
+ config.proxy = "https://my-proxy"
500
+
501
+ expect(config.proxy).to eql("https://my-proxy")
502
+
503
+ # ensure no exception is raised
504
+ config.connection
505
+ end
506
+
507
+ it 'can be set with proxy(value)' do
508
+ config.proxy("https://my-proxy")
509
+
510
+ expect(config.proxy).to eql("https://my-proxy")
511
+ end
512
+ end
513
+
479
514
  end
@@ -5,7 +5,7 @@ describe NetSuite::Records::CashRefundItem do
5
5
 
6
6
  it 'has all the right fields' do
7
7
  [
8
- :amount
8
+ :amount, :gross_amt, :rate, :quantity, :is_taxable, :order_line, :line, :description
9
9
  ].each do |field|
10
10
  expect(item).to have_field(field)
11
11
  end
@@ -20,6 +20,20 @@ describe NetSuite::Records::CreditMemo do
20
20
  end
21
21
  end
22
22
 
23
+ it 'has all the right fields with specific classes' do
24
+ {
25
+ custom_field_list: NetSuite::Records::CustomFieldList,
26
+ item_list: NetSuite::Records::CreditMemoItemList,
27
+ apply_list: NetSuite::Records::CreditMemoApplyList,
28
+ ship_group_list: NetSuite::Records::SalesOrderShipGroupList,
29
+ null_field_list: NetSuite::Records::NullFieldList,
30
+ transaction_bill_address: NetSuite::Records::BillAddress,
31
+ billing_address: NetSuite::Records::Address,
32
+ }.each do |field, klass|
33
+ expect(memo).to have_field(field, klass)
34
+ end
35
+ end
36
+
23
37
  it 'has all the right record refs' do
24
38
  [
25
39
  :account, :bill_address_list, :created_from, :custom_form, :department, :discount_item, :entity, :gift_cert,
@@ -5,30 +5,268 @@ describe NetSuite::Records::Customer do
5
5
 
6
6
  it 'has all the right fields' do
7
7
  [
8
- :account_number, :aging, :alt_email, :alt_name, :alt_phone, :balance, :bill_pay,
9
- :buying_reason, :buying_time_frame, :campaign_category, :click_stream, :comments, :company_name,
10
- :consol_aging, :consol_balance, :consol_days_overdue, :consol_deposit_balance, :consol_overdue_balance,
11
- :consol_unbilled_orders, :contrib_pct, :credit_hold_override, :credit_limit,
12
- :date_created, :days_overdue, :default_address,
13
- :deposit_balance, :download_list, :email, :email_preference, :email_transactions, :end_date, :entity_id,
14
- :estimated_budget, :fax, :fax_transactions, :first_name, :first_visit, :give_access, :global_subscription_status,
15
- :group_pricing_list, :home_phone, :image, :is_budget_approved, :is_inactive, :is_person, :item_pricing_list, :keywords,
16
- :language, :last_modified_date, :last_name, :last_page_visited, :last_visit, :middle_name, :mobile_phone,
17
- :opening_balance, :opening_balance_account, :opening_balance_date, :overdue_balance,
18
- :password, :password2, :phone, :phonetic_name, :pref_cc_processor,:print_on_check_as,
19
- :print_transactions, :referrer, :reminder_days, :representing_subsidiary, :require_pwd_change, :resale_number,
20
- :sales_group, :sales_readiness, :salutation, :send_email, :ship_complete,
21
- :stage, :start_date, :sync_partner_teams, :tax_exempt, :taxable,
22
- :third_party_acct, :third_party_country, :third_party_zipcode, :title, :unbilled_orders, :url,
23
- :vat_reg_number, :visits, :web_lead
8
+ :account_number,
9
+ :aging,
10
+ :aging1,
11
+ :aging2,
12
+ :aging3,
13
+ :aging4,
14
+ :alcohol_recipient_type,
15
+ :alt_email,
16
+ :alt_name,
17
+ :alt_phone,
18
+ :bill_pay,
19
+ :click_stream,
20
+ :comments,
21
+ :company_name,
22
+ :consol_aging,
23
+ :consol_aging1,
24
+ :consol_aging2,
25
+ :consol_aging3,
26
+ :consol_aging4,
27
+ :consol_days_overdue,
28
+ :contrib_pct,
29
+ :credit_hold_override,
30
+ :credit_limit,
31
+ :date_created,
32
+ :days_overdue,
33
+ :default_address,
34
+ :default_order_priority,
35
+ :display_symbol,
36
+ :email,
37
+ :email_preference,
38
+ :email_transactions,
39
+ :end_date,
40
+ :entity_id,
41
+ :estimated_budget,
42
+ :fax,
43
+ :fax_transactions,
44
+ :first_name,
45
+ :first_visit,
46
+ :give_access,
47
+ :global_subscription_status,
48
+ :home_phone,
49
+ :is_budget_approved,
50
+ :is_inactive,
51
+ :is_person,
52
+ :keywords,
53
+ :language,
54
+ :last_modified_date,
55
+ :last_name,
56
+ :last_page_visited,
57
+ :last_visit,
58
+ :middle_name,
59
+ :mobile_phone,
60
+ :monthly_closing,
61
+ :negative_number_format,
62
+ :number_format,
63
+ :opening_balance,
64
+ :opening_balance_date,
65
+ :override_currency_format,
66
+ :password,
67
+ :password2,
68
+ :phone,
69
+ :phonetic_name,
70
+ :print_on_check_as,
71
+ :print_transactions,
72
+ :referrer,
73
+ :reminder_days,
74
+ :require_pwd_change,
75
+ :resale_number,
76
+ :salutation,
77
+ :send_email,
78
+ :ship_complete,
79
+ :stage,
80
+ :start_date,
81
+ :symbol_placement,
82
+ :sync_partner_teams,
83
+ :taxable,
84
+ :tax_exempt,
85
+ :third_party_acct,
86
+ :third_party_country,
87
+ :third_party_zipcode,
88
+ :title,
89
+ :url,
90
+ :vat_reg_number,
91
+ :visits,
92
+ :web_lead,
24
93
  ].each do |field|
25
94
  expect(customer).to have_field(field)
26
95
  end
27
96
  end
28
97
 
98
+ it 'has all the right fields with specific classes' do
99
+ {
100
+ addressbook_list: NetSuite::Records::CustomerAddressbookList,
101
+ contact_roles_list: NetSuite::Records::ContactAccessRolesList,
102
+ credit_cards_list: NetSuite::Records::CustomerCreditCardsList,
103
+ currency_list: NetSuite::Records::CustomerCurrencyList,
104
+ custom_field_list: NetSuite::Records::CustomFieldList,
105
+ # download_list: NetSuite::Records::CustomerDownloadList, # TODO Implement me
106
+ # group_pricing_list: NetSuite::Records::CustomerGroupPricingList, # TODO: Implement me
107
+ # item_pricing_list: NetSuite::Records::CustomerItemPricingList, # TODO: Implement me
108
+ partners_list: NetSuite::Records::CustomerPartnersList,
109
+ sales_team_list: NetSuite::Records::CustomerSalesTeamList,
110
+ subscriptions_list: NetSuite::Records::SubscriptionsList,
111
+ # tax_registration_list: NetSuite::Records::CustomerTaxRegistrationList, # TODO: Implement me
112
+ }.each do |field, klass|
113
+ expect(customer).to have_field(field, klass)
114
+ end
115
+ end
116
+
117
+ it 'has all the right read_only_fields' do
118
+ [
119
+ :balance,
120
+ :consol_balance,
121
+ :deposit_balance,
122
+ :consol_deposit_balance,
123
+ :overdue_balance,
124
+ :consol_overdue_balance,
125
+ :unbilled_orders,
126
+ :consol_unbilled_orders,
127
+ ].each do |field|
128
+ expect(NetSuite::Records::Customer).to have_read_only_field(field)
129
+ end
130
+ end
131
+
132
+ it 'has all the right search_only_fields' do
133
+ [
134
+ :address,
135
+ :address1,
136
+ :address2,
137
+ :address3,
138
+ :addressee,
139
+ :address_internal_id,
140
+ :address_label,
141
+ :address_phone,
142
+ :alt_contact,
143
+ :assigned_site,
144
+ :assigned_site_id,
145
+ :attention,
146
+ :available_offline,
147
+ :bill_address,
148
+ :bill_address1,
149
+ :bill_address2,
150
+ :bill_address3,
151
+ :bill_addressee,
152
+ :bill_attention,
153
+ :bill_city,
154
+ :bill_country,
155
+ :bill_country_code,
156
+ :bill_phone,
157
+ :bill_state,
158
+ :bill_zip_code,
159
+ :cc_customer_code,
160
+ :cc_default,
161
+ :cc_exp_date,
162
+ :cc_holder_name,
163
+ :cc_internal_id,
164
+ :cc_number,
165
+ :cc_state,
166
+ :cc_state_from,
167
+ :cc_type,
168
+ :city,
169
+ :contact,
170
+ :contribution,
171
+ :contribution_primary,
172
+ :conversion_date,
173
+ :country,
174
+ :country_code,
175
+ :credit_hold,
176
+ :date_closed,
177
+ :entity_number,
178
+ :explicit_conversion,
179
+ :first_order_date,
180
+ :first_sale_date,
181
+ :fx_balance,
182
+ :fx_consol_balance,
183
+ :fx_consol_unbilled_orders,
184
+ :fx_unbilled_orders,
185
+ :group_pricing_level,
186
+ :has_duplicates,
187
+ :is_default_billing,
188
+ :is_default_shipping,
189
+ :is_ship_address,
190
+ :item_pricing_level,
191
+ :item_pricing_unit_price,
192
+ :job_end_date,
193
+ :job_projected_end,
194
+ :job_start_date,
195
+ :job_type,
196
+ :last_order_date,
197
+ :last_sale_date,
198
+ :lead_date,
199
+ :level,
200
+ :manual_credit_hold,
201
+ :on_credit_hold,
202
+ :partner_contribution,
203
+ :partner_role,
204
+ :partner_team_member,
205
+ :pec,
206
+ :permission,
207
+ :pricing_group,
208
+ :pricing_item,
209
+ :prospect_date,
210
+ :role,
211
+ :sales_team_member,
212
+ :sales_team_role,
213
+ :ship_address,
214
+ :ship_address1,
215
+ :ship_address2,
216
+ :ship_address3,
217
+ :ship_addressee,
218
+ :ship_attention,
219
+ :ship_city,
220
+ :ship_country,
221
+ :ship_country_code,
222
+ :ship_phone,
223
+ :ship_state,
224
+ :ship_zip,
225
+ :source_site,
226
+ :source_site_id,
227
+ :state,
228
+ :subscription,
229
+ :subscription_date,
230
+ :subscription_status,
231
+ :zip_code,
232
+ ].each do |field|
233
+ expect(NetSuite::Records::Customer).to have_search_only_field(field)
234
+ end
235
+ end
236
+
29
237
  it 'has the right record_refs' do
30
238
  [
31
- :access_role, :currency, :custom_form, :entity_status, :partner, :sales_rep, :terms, :parent, :territory, :shipping_item, :tax_item
239
+ :access_role,
240
+ :assigned_web_site,
241
+ :buying_reason,
242
+ :buying_time_frame,
243
+ :campaign_category,
244
+ :category,
245
+ :currency,
246
+ :custom_form,
247
+ :default_allocation_strategy,
248
+ :default_tax_reg,
249
+ :dr_account,
250
+ :entity_status,
251
+ :fx_account,
252
+ :image,
253
+ :lead_source,
254
+ :opening_balance_account,
255
+ :parent,
256
+ :partner,
257
+ :pref_cc_processor,
258
+ :price_level,
259
+ :receivables_account,
260
+ :representing_subsidiary,
261
+ :sales_group,
262
+ :sales_readiness,
263
+ :sales_rep,
264
+ :shipping_item,
265
+ :source_web_site,
266
+ :subsidiary,
267
+ :tax_item,
268
+ :terms,
269
+ :territory,
32
270
  ].each do |record_ref|
33
271
  expect(customer).to have_record_ref(record_ref)
34
272
  end
@@ -115,12 +353,12 @@ describe NetSuite::Records::Customer do
115
353
  }
116
354
  ]
117
355
  }
118
- expect(customer.subscriptions_list).to be_kind_of(NetSuite::Records::CustomerSubscriptionsList)
356
+ expect(customer.subscriptions_list).to be_kind_of(NetSuite::Records::SubscriptionsList)
119
357
  expect(customer.subscriptions_list.subscriptions.length).to eql(1)
120
358
  end
121
359
 
122
- it 'can be set from a CustomerSubscriptionsList object' do
123
- customer_subscriptions_list = NetSuite::Records::CustomerSubscriptionsList.new
360
+ it 'can be set from a SubscriptionsList object' do
361
+ customer_subscriptions_list = NetSuite::Records::SubscriptionsList.new
124
362
  customer.subscriptions_list = customer_subscriptions_list
125
363
  expect(customer.subscriptions_list).to eql(customer_subscriptions_list)
126
364
  end
@@ -202,6 +440,35 @@ describe NetSuite::Records::Customer do
202
440
  end
203
441
  end
204
442
 
443
+ describe '#attach_file' do
444
+ let(:test_data) { { :email => 'test@example.com', :fax => '1234567890' } }
445
+ let(:file) { double('file') }
446
+
447
+ context 'when the response is successful' do
448
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
449
+
450
+ it 'returns true' do
451
+ customer = NetSuite::Records::Customer.new(test_data)
452
+ expect(NetSuite::Actions::AttachFile).to receive(:call).
453
+ with([customer, file], {}).
454
+ and_return(response)
455
+ expect(customer.attach_file(file)).to be_truthy
456
+ end
457
+ end
458
+
459
+ context 'when the response is unsuccessful' do
460
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
461
+
462
+ it 'returns false' do
463
+ customer = NetSuite::Records::Customer.new(test_data)
464
+ expect(NetSuite::Actions::AttachFile).to receive(:call).
465
+ with([customer, file], {}).
466
+ and_return(response)
467
+ expect(customer.attach_file(file)).to be_falsey
468
+ end
469
+ end
470
+ end
471
+
205
472
  describe '#to_record' do
206
473
  let(:customer) { NetSuite::Records::Customer.new(:entity_id => 'TEST CUSTOMER', :is_person => true) }
207
474