import unittest
from Products.ERP5Type.tests.Sequence import SequenceList
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
from Products.ERP5Type.DateUtils import getClosestDate
from DateTime import DateTime
from testVifibOpenOrderSimulation import generateTimeFrameList

class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):

  def stepTriggerBuild(self, sequence, **kw):
    self.portal.portal_alarms.vifib_trigger_build.activeSense()

  def stepCheckPayment(self, sequence, **kw):
    raise NotImplementedError

  def stepCheckSubscriptionSalePackingListCoverage(self, sequence, **kw):
    hosting_subscription = self.portal.portal_catalog.getResultValue(
      uid=sequence['hosting_subscription_uid'])
    delivery_list = self.portal.portal_catalog(
      portal_type='Sale Packing List',
      causality_relative_url=hosting_subscription.getRelativeUrl(),
      sort_on=(('delivery.start_date', 'desc'),)
    )
    # is whole year covered?
    self.assertEqual(12, len(delivery_list))

    # generate the expected time frames
    now = DateTime()
    start_date = \
      getClosestDate(target_date=now, precision='day', before=1)

    # Calculate the list of time frames
    expected_time_frame_list = generateTimeFrameList(start_date)

    idx = 0
    for delivery in delivery_list:
      expected_start_date = expected_time_frame_list[idx]
      expected_stop_date = expected_time_frame_list[idx+1]
      self.assertEqual(expected_start_date, delivery.getStartDate())
      self.assertEqual(expected_stop_date, delivery.getStopDate())

      self.assertEqual(hosting_subscription.getRelativeUrl(),
        delivery.getCausality())
      delivery_line_list = \
        delivery.contentValues(portal_type="Sale Packing List Line")
      self.assertEquals(1, len(delivery_line_list))
      delivery_line = delivery_line_list[0]
      self.assertEquals("organisation_module/vifib_internet",
        delivery.getSource())
      self.assertEquals("organisation_module/vifib_internet",
        delivery.getSourceSection())
      self.assertEquals("person_module/test_vifib_customer",
        delivery.getDestination())
      self.assertEquals("person_module/test_vifib_customer",
        delivery.getDestinationSection())
      self.assertEquals("currency_module/EUR",
        delivery.getPriceCurrency())

      # check sale packing list line related property
      self.assertEquals("service_module/vifib_instance_subscription",
        delivery_line.getResource())
      self.assertEquals(1,
        delivery_line.getQuantity())
      self.assertEquals("unit/piece",
        delivery_line.getQuantityUnit())
      self.assertEquals(1,
        delivery_line.getPrice())

      # fetch open order, open order line and subscription
      person = self.portal.person_module['test_vifib_customer']
      open_order = \
        person.getDestinationDecisionRelatedValue(portal_type="Open Sale Order")
      open_order_line = \
        open_order.contentValues(portal_type="Open Sale Order Line")[0]

      # check related property
      self.assertEquals(open_order_line.getSpecialise(),
        delivery.getSpecialise())

      idx += 1

  def stepCheckHostingSubscriptionInitialDocumentCoverage(self, sequence, **kw):
    catalog = self.portal.portal_catalog
    hosting_resource = self.portal.portal_preferences\
      .getPreferredInstanceHostingResource()
    setup_resource = self.portal.portal_preferences\
      .getPreferredInstanceSetupResource()
    subscription_resource = self.portal.portal_preferences\
      .getPreferredInstanceSubscriptionResource()
    sequence.edit(
      hosting_resource=hosting_resource,
      setup_resource=setup_resource,
      subscription_resource=subscription_resource
    )

    hosting_subscription = catalog.getResultValue(
      uid=sequence['hosting_subscription_uid'])
    hosting_subscription_url = hosting_subscription.getRelativeUrl()

    # hosting is confirmed, so no invoice
    hosting_delivery_line_list = catalog(portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=hosting_resource)

    self.assertEqual(1, len(hosting_delivery_line_list))
    self.assertEqual('confirmed', hosting_delivery_line_list[0]\
      .getSimulationState())

    hosting_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=hosting_resource)
    self.assertEqual(0, len(hosting_invoice_line_list))

    # setup is stopped, and has there is invoice
    setup_delivery_line_list = catalog(portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=setup_resource)

    self.assertEqual(1, len(setup_delivery_line_list))
    self.assertEqual('stopped', setup_delivery_line_list[0]\
      .getSimulationState())

    setup_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=setup_resource)
    self.assertEqual(1, len(setup_invoice_line_list))
    self.assertEqual('planned', setup_invoice_line_list[0]\
      .getSimulationState())

    # there are 12 confirmed subscription, so no invoice
    subscription_delivery_line_list = catalog(
      portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=subscription_resource,
      sort_on=(('movement.start_date', 'desc'),)
    )

    self.assertEqual(12, len(subscription_delivery_line_list))
    self.assertEqual(['confirmed'] * 12, [q.getSimulationState() for \
      q in subscription_delivery_line_list])

    subscription_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=subscription_resource)
    self.assertEqual(0, len(subscription_invoice_line_list))

    # invoice shall be solved
    self.assertEqual('solved', setup_invoice_line_list[0].getCausalityState())

    # invoice shall have causality of one packing list
    self.assertEqual(
      [setup_delivery_line_list[0].getParentValue().getUid()],
      setup_invoice_line_list[0].getParentValue().getCausalityUidList())

    sequence.edit(
      subscription_delivery_uid_list=[q.getParentValue().getUid() for q in \
        subscription_delivery_line_list]
    )

  def stepSelectNextSubscriptionDelivery(self, sequence, **kw):
    subscription_delivery_uid_list = sequence['subscription_delivery_uid_list']
    subscription_delivery_uid_list.reverse()
    subscription_delivery_uid = subscription_delivery_uid_list.pop()
    subscription_delivery_uid_list.reverse()
    sequence.edit(
      subscription_delivery_uid_list=subscription_delivery_uid_list,
      subscription_delivery_uid=subscription_delivery_uid
    )

  def stepStartSubscriptionDelivery(self, sequence, **kw):
    self.portal.portal_catalog.getResultValue(
      uid=sequence['subscription_delivery_uid']).start()

  def stepStopSubscriptionDelivery(self, sequence, **kw):
    self.portal.portal_catalog.getResultValue(
      uid=sequence['subscription_delivery_uid']).stop()

  def stepCheckHostingSubscriptionStoppedDocumentCoverage(self, sequence, **kw):
    catalog = self.portal.portal_catalog
    hosting_subscription = catalog.getResultValue(
      uid=sequence['hosting_subscription_uid'])
    hosting_subscription_url = hosting_subscription.getRelativeUrl()

    # hosting is confirmed, so no invoice
    hosting_delivery_line_list = catalog(portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['hosting_resource'])

    self.assertEqual(1, len(hosting_delivery_line_list))
    self.assertEqual('confirmed', hosting_delivery_line_list[0]\
      .getSimulationState())

    hosting_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['hosting_resource'])
    self.assertEqual(0, len(hosting_invoice_line_list))

    # setup is stopped, and has there is invoice
    setup_delivery_line_list = catalog(portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['setup_resource'])

    self.assertEqual(1, len(setup_delivery_line_list))
    self.assertEqual('stopped', setup_delivery_line_list[0]\
      .getSimulationState())

    setup_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['setup_resource'])
    self.assertEqual(1, len(setup_invoice_line_list))
    self.assertEqual('planned', setup_invoice_line_list[0]\
      .getSimulationState())

    # there are 11 confirmed and 1 stopped subscription, so 1 invoice line
    subscription_delivery_line_list = catalog(
      portal_type='Sale Packing List Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['subscription_resource'])

    self.assertEqual(12, len(subscription_delivery_line_list))
    self.assertEqual((['confirmed'] * 11) + ['stopped'],
      sorted([q.getSimulationState() for \
      q in subscription_delivery_line_list]))

    subscription_invoice_line_list = catalog(portal_type='Invoice Line',
      aggregate_relative_url=hosting_subscription_url,
      resource_relative_url=sequence['subscription_resource'])
    self.assertEqual(1, len(subscription_invoice_line_list))
    self.assertEqual('planned', subscription_invoice_line_list[0]\
      .getSimulationState())

    # there are two invoice lines sharing same invoice
    self.assertEqual(
      setup_invoice_line_list[0].getParentValue().getRelativeUrl(),
      subscription_invoice_line_list[0].getParentValue().getRelativeUrl()
    )

    # invoice shall be solved
    self.assertEqual('solved', setup_invoice_line_list[0].getCausalityState())

    # invoice shall have causality of two packing lists
    self.assertEqual(
      sorted([setup_delivery_line_list[0].getParentValue().getUid()] +
      [q.getParentValue().getUid() for q in subscription_delivery_line_list if q.getSimulationState() == 'stopped']),
      sorted(setup_invoice_line_list[0].getParentValue().getCausalityUidList()))


  def test_OpenOrder_sale_packing_list(self):
    """
    Check that sale_packing_list is generated properly from simulation
    """
    sequence_list = SequenceList()
    sequence_string = \
        self.prepare_installed_computer_partition_sequence_string  + \
        """
        LoginDefaultUser
        TriggerBuild
        Tic
        CheckSubscriptionSalePackingListCoverage

        TriggerBuild
        Tic
        # Nothing shall change
        CheckHostingSubscriptionInitialDocumentCoverage

        # Stop first Subscriptoin delivery and after triggering build check
        # that invoice got updated

        SelectNextSubscriptionDelivery
        StartSubscriptionDelivery
        StopSubscriptionDelivery
        Tic

        TriggerBuild
        Tic

        CheckHostingSubscriptionStoppedDocumentCoverage

        CheckPayment
        """
    sequence_list.addSequenceString(sequence_string)
    sequence_list.play(self)

def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestVifibInstanceHostingRelatedDocument))
  return suite
