<commit_before>module Integration
  class Order < Base

    attr_reader :object

    def initialize(config, object = {})
      @object = object
      super(config)
    end

    # Related docs:
    #
    # http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunity.htm
    # http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunitylineitem.htm
    def upsert!
      # Create or Update the Contact. Set the account id
      contact_account = ContactAccount.new(config, object[:order])
      account_id = contact_account.account_id

      if object[:order][:sf_record_type_id]
        contact_account.person_contact_update account_id
      else
        contact_account.upsert! AccountId: account_id
      end

      product_integration = Product.new(config, object[:order])
      line_item_integration = LineItem.new(config)

      # Opportunity lines needs to ref a product pricebook entry
      standard_id = product_integration.standard_pricebook(object[:order][:sf_pricebook_name])["Id"]

      # Create or Update the Opportunity. Set the opportunity id
      params = order_params.merge AccountId: account_id, Pricebook2Id: standard_id
      opportunity_id = order_service.upsert! params

      object[:order][:line_items].each do |line_item|

        # Create Product in case it doesn't exist in Salesforce yet
        unless product_id = product_integration.find_id_by_code(line_item[:product_id])
          attributes = Builder::Product.new(line_item).build.except "DefaultPrice"
          attributes.merge Currency: object[:order][:currency]
          product_id = product_integration.create! attributes
        end

        # Create (if not found) pricebook entry
        pricebook_entry_id = product_integration.setup_pricebook_entry standard_id, product_id, line_item[:price]

        # Create or Update Opportunity line
        line_item_integration.upsert! line_item, opportunity_id, pricebook_entry_id
      end

      payment_integration = Payment.new(config)

      object[:order][:payments].each do |payment|
        payment_integration.upsert! payment, opportunity_id
      end

      custom_objects_upsert object[:order][:salesforce_custom]
    end

    def fetch_updates
      latest_opportunities.map do |o|
        account = accounts_by_id.find { |a| a[:Id] == o[:Account][:Id] }
        contact = account[:Contacts].first

        {
          id: o[:Name],
          email: contact[:Email],
          placed_on: o[:CloseDate],
          channel: 'salesforce',
          updated_at: o[:LastModifiedDate],
          totals: {
            order: o[:Amount]
          },
          line_items: build_line_items(o[:OpportunityLineItems]),
          payments: build_payments(o[:Notes]),
          shipping_address: build_address(account, "Shipping"),
          billing_address: build_address(account),
          salesforce_id: o[:Id]
        }
      end
    end

    def latest_opportunities
      @latest_opportunities ||= order_service.latest_updates(config[:salesforce_orders_since]).to_a
    end

    def accounts_by_id
      ids = latest_opportunities.map { |o| "'#{o[:Account][:Id]}'" }
      account_service.fetch_contacts_along ids
    end

    def latest_timestamp_update(orders = nil)
      if order = (orders || latest_opportunities).last
        Time.parse(order["LastModifiedDate"]).utc.iso8601
      else
        Time.now.utc.iso8601
      end
    end

    private
      def build_payments(notes)
        notes.to_a.map do |note|
          {
            title: note[:Title],
            body: note[:Body]
          }
        end
      end

      def build_address(account, kind = "Billing")
        {
          address1: account["#{kind}Street"],
          zipcode: account["#{kind}PostalCode"],
          city: account["#{kind}City"],
          country: account["#{kind}Country"],
          state: account["#{kind}State"],<commit_msg>Avoid calling first no nil if no Contact found<commit_after>module Integration
  class Order < Base

    attr_reader :object

    def initialize(config, object = {})
      @object = object
      super(config)
    end

    # Related docs:
    #
    # http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunity.htm
    # http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunitylineitem.htm
    def upsert!
      # Create or Update the Contact. Set the account id
      contact_account = ContactAccount.new(config, object[:order])
      account_id = contact_account.account_id

      if object[:order][:sf_record_type_id]
        contact_account.person_contact_update account_id
      else
        contact_account.upsert! AccountId: account_id
      end

      product_integration = Product.new(config, object[:order])
      line_item_integration = LineItem.new(config)

      # Opportunity lines needs to ref a product pricebook entry
      standard_id = product_integration.standard_pricebook(object[:order][:sf_pricebook_name])["Id"]

      # Create or Update the Opportunity. Set the opportunity id
      params = order_params.merge AccountId: account_id, Pricebook2Id: standard_id
      opportunity_id = order_service.upsert! params

      object[:order][:line_items].each do |line_item|

        # Create Product in case it doesn't exist in Salesforce yet
        unless product_id = product_integration.find_id_by_code(line_item[:product_id])
          attributes = Builder::Product.new(line_item).build.except "DefaultPrice"
          attributes.merge Currency: object[:order][:currency]
          product_id = product_integration.create! attributes
        end

        # Create (if not found) pricebook entry
        pricebook_entry_id = product_integration.setup_pricebook_entry standard_id, product_id, line_item[:price]

        # Create or Update Opportunity line
        line_item_integration.upsert! line_item, opportunity_id, pricebook_entry_id
      end

      payment_integration = Payment.new(config)

      object[:order][:payments].each do |payment|
        payment_integration.upsert! payment, opportunity_id
      end

      custom_objects_upsert object[:order][:salesforce_custom]
    end

    def fetch_updates
      latest_opportunities.map do |o|
        account = accounts_by_id.find { |a| a[:Id] == o[:Account][:Id] }
        contact = account[:Contacts].to_a.first.to_h

        {
          id: o[:Name],
          email: contact[:Email],
          placed_on: o[:CloseDate],
          channel: 'salesforce',
          updated_at: o[:LastModifiedDate],
          totals: {
            order: o[:Amount]
          },
          line_items: build_line_items(o[:OpportunityLineItems]),
          payments: build_payments(o[:Notes]),
          shipping_address: build_address(account, "Shipping"),
          billing_address: build_address(account),
          salesforce_id: o[:Id]
        }
      end
    end

    def latest_opportunities
      @latest_opportunities ||= order_service.latest_updates(config[:salesforce_orders_since]).to_a
    end

    def accounts_by_id
      ids = latest_opportunities.map { |o| "'#{o[:Account][:Id]}'" }
      @accounts_by_id ||= account_service.fetch_contacts_along ids
    end

    def latest_timestamp_update(orders = nil)
      if order = (orders || latest_opportunities).last
        Time.parse(order["LastModifiedDate"]).utc.iso8601
      else
        Time.now.utc.iso8601
      end
    end

    private
      def build_payments(notes)
        notes.to_a.map do |note|
          {
            title: note[:Title],
            body: note[:Body]
          }
        end
      end

      def build_address(account, kind = "Billing")
        {
          address1: account["#{kind}Street"],
          zipcode: account["#{kind}PostalCode"],
          city: account["#{kind}City"],
          country: account["#{kind}Country"],
          state: account["#{kind}State"],
{'fraction_non_alphanumeric': 0.09917773561037319, 'fraction_numerical': 0.002530044275774826, 'mean_word_length': 2.8248669569424285, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2068052', 'n_tokens_mistral': 2355, 'n_tokens_neox': 2258, 'n_words': 460}