def create():
	post_data = get_post_data()
	post_data['lead_id'] = parse_endpoint(post_data['lead'], 'leads')

	# saves the job
	job = Job()
	job.build(post_data)
	job.status = 'CREATED'
	job.unique_id = Job.generate_unique_id()

	if job.put():
		# enqueue job to be sent to townflix
		_enqueue_job_creation_message(job)

		pprint.pprint('=== JOB CREATED')

		# mark the lead as converted
		lead = job.lead.get()
		lead.status = 'CONVERTED'
		lead.put()

		create_activity('LEAD_CONVERTED', lead=lead, job=job)
		create_activity('JOB_CREATED', lead=lead, job=job)

		# send a message to property owner
		_enqueue_job_create_message(job)

		# if the lead has been sent by someone
		if lead.sender_broker is not None:
			# send a message to the broker
			_enqueue_broker_job_create_message(job)

		return jsonify(data=job.to_json()), 201
	else:
		return jsonify(data=job.error_messages()), 500
def click(id):
	lead = Lead.get_by_id(int(id))
	lead.status = 'CLICKED'
	lead.put()

	create_activity('LEAD_CLICKED', lead=lead)
	return '', 200
def approve(id):
	job = _get_job(id)

	if _change_approval_status(job, 'APPROVED'):
		create_activity('JOB_APPROVED', job=job)

		Job.start_publishing(id)

		if job.tf_job_id is not None:
			tf_complete_job(id, job.tf_job_id)

		return jsonify(data=job.to_json()), 201
	else:
		abort(400, {'message': CANNOT_APPROVE_JOB_MESSAGE })
def read(id):
	lead = Lead.get_by_id(int(id))
	lead.mark_as_read()

	create_activity('LEAD_READ', lead=lead)

	image = Image.new("RGB", (1, 1), "black")
	output = StringIO.StringIO()
	image.save(output, format="png")
	text_layer = output.getvalue()
	logging.debug(text_layer)
	output.close()

	return Response(text_layer, mimetype='image/png')
def process_medias():
	# find the job which is being processed
	job_id = request.form['job_id']
	job = _get_job(job_id)

	pprint.pprint('========= BACKGROUND PROCESSING ')

	# gets the watermark image
	watermark = ih.get_watermark_image()

	photo_list = []
	# iterates over each photo
	for p in job.medias['photos']:
		new_url = _process_media(p, watermark, job_id)
		photo_list.append({
				'title': p['title'],
				'url': new_url,
				'media_id': p['media_id']
			})

	job.medias['photos'] = photo_list


	if job.status == 'ASSIGNED':
		# send a message to property owner telling him that his job is ready for approval
		_enqueue_job_in_approval_message(job)

		create_activity('JOB_PUBLISHING_DONE', job=job)
	elif job.status == 'REDO':
		_enqueue_job_back_from_redo_message(job)

		create_activity('JOB_PUBLISHING_REDO_DONE', job=job)

	job.status = 'REVIEW'
	job.put()


	Job.start_packaging(job_id)

	return '', 200
def redo(id):
	job = _get_job(id)
	post_data = get_post_data()

	pprint.pprint('Client POST')
	pprint.pprint(post_data)

	# validates if photos is sent
	if 'photos' not in post_data:
		abort(400, { 'message': 'Photos should be sent.'})

	# if the job is marked as review
	if tf_redo_job(id, job.tf_job_id, post_data):
		if _change_approval_status(job, 'REPROVED'):
			job.medias = post_data
			job.put()

			create_activity('JOB_REPROVED', job=job)

			return jsonify(data={}), 201
		else:
			abort(400, {'message': CANNOT_REPROVE_JOB_MESSAGE })
	else:
		abort(400, {'message': CANNOT_REPROVE_JOB_MESSAGE })
def publish(id):
	job = _get_job(id)
	post_data = get_post_data()

	# validates if photos is sent
	if 'photos' not in post_data:
		abort(400, { 'message': 'Photos should be sent.'})

	# if the status is assigned
	if job.status == 'ASSIGNED' or job.status == 'REDO':

		# patch the media to job
		job.medias = post_data
		job.put()

		create_activity('JOB_PUBLISHING_STARTED', job=job)

		# enqueue the job to be processed
		# when this task is processed the job will become REVIEW
		Job.enqueue_for_processing_media(job.key.id())

		return jsonify(data={}), 201
	else:
		abort(400, {'message': CANNOT_PUBLISH_JOB_MESSAGE })
def update(id):
	post_data = get_post_data()
	job = _get_job(id)
	has_patched_flixer = False
	should_update_lead = False
	should_send_reschedule_mail = False
	is_flixer_already_filled = True if job.flixer is not None else False

	# if flixer is sent
	if 'flixer' in post_data:
		# if the job status allows you to ASSIGN the job. RESCHEDULE is allowed just for development purposes.
		if job.status == 'CREATED' or job.status == 'ASSIGNED' or job.status == 'RESCHEDULE':
			job.flixer = post_data['flixer']
			job.status = 'ASSIGNED'
			has_patched_flixer = True

	# if scheduled_date is sent
	if 'scheduled_date' in post_data:
		try:
			# if scheduled_date is not empty, patches to job
			if post_data['scheduled_date'] is not None:
				job.scheduled_date = datetime.datetime.strptime(post_data['scheduled_date'], DATE_FORMAT)
			else:
				# check if the user is trying to cancel an assigned job
				if job.status == 'ASSIGNED':
					job.scheduled_date = None
					should_update_lead = True
					schedule_options = []

					cancelled_by_flixer = False

					pprint.pprint(post_data)
					if 'f' in post_data:
						cancelled_by_flixer = True

					_cancel_assigned_job(job, cancelled_by_flixer=cancelled_by_flixer)

					if cancelled_by_flixer:
						create_activity('JOB_CANCELLED_BY_FLIXER', job=job)
					else:
						create_activity('JOB_CANCELLED_BY_PROPERTY_OWNER', job=job)

		except ValueError:
			abort(500, {'message': DATE_FORMAT_INVALID_MESSAGE })

	# if schedule_options is sent
	if 'schedule_options' in post_data:
		# build an array with the schedule_options sent
		schedule_options = []
		for o in post_data['schedule_options']:
			schedule_options.append(datetime.datetime.strptime(o, DATE_FORMAT))
		should_update_lead = True

		# if the current status is to RESCHEDULE
		if job.status == 'RESCHEDULE':
			# mark the job as reopened and clean scheduled_date
			job.status = 'CREATED'
			job.scheduled_date = None

			# create a new job in townflix
			job_json = job.to_json()
			listing = job_json['listing']
			property_owner = job_json['property_owner']

			job_title = '%s - %s' % (listing['reference'], listing['title'])
			job_description = job_json['description'] if job_json['description'] is not None else '-'

			params = {
				'contact': {
					'contact_email': property_owner['email'],
					'contact_name': property_owner['name'],
					'contact_phone': property_owner['phone']
				},
				'address': listing['full_address'],
				'title': job_title,
				'description': job_description,
				'schedules': post_data['schedule_options'],
				'origin_id': str(job.key.id())
			}

			result = tf_create_job(params)
			if result is not None:
				job.tf_job_id = int(result['job_id'])

			# send a message to property owner telling him that his job has been rescheduled
			should_send_reschedule_mail = True

			create_activity('JOB_RESCHEDULED', job=job)


	# if something inside the lead has been modified
	if should_update_lead:
		# updates the lead
		lead = job.lead.get()
		lead.schedule_options = schedule_options
		lead.put()

	# if job is correctly updated
	if job.put():
		# if the flixer has been updated
		if has_patched_flixer:
			# send a message to property owner telling that his job has been assigned
			first_time = not is_flixer_already_filled
			_enqueue_assign_message(job, first_time=first_time)
			create_activity('JOB_ASSIGNED', job=job)

		if should_send_reschedule_mail:
			_enqueue_job_reschedule_message(job)

		return jsonify(data=job.to_json()), 201
	else:
		return jsonify(data=job.error_messages()), 500
def publish_medias():
	# collect all the information in order to publish the medias
	job_id = request.form['job_id']
	job = _get_job(job_id)
	lead = job.lead.get()
	listing = lead.listing.get()

	if lead.sender_broker is None:
		pprint.pprint('There is nothing to process.')
		return '', 200

	broker = lead.sender_broker.get()
	agency = broker.agency.get()
	external_id = listing.external_id

	fake_id = 666

	pprint.pprint('========= BACKGROUND PROCESSING ')
	pprint.pprint('Source Application: %s' % agency.source_application)
	pprint.pprint('Listing Id: %s' % external_id)

	# if we cannot publish the medias, skip it
	if settings.env() != 'prod' or external_id is None:
		pprint.pprint('Publishing is not active in this environment yet.')
	else:
		x = 1

		# iterates over all videos
		for v in job.medias['videos']:
			# export to valuegaia
			if external_id != fake_id:
				# todo: refactor urgent!!!!!
				# gets the townflix code inside the url sent by townflix
				k = v['url'].split('/')
				townflix_code = k[len(k)-1]

				# inserts the video at valuegaia
				valuegaia.insert_video(external_id, townflix_code, v['thumbnail'])

		# iterates over all photos
		for p in job.medias['photos']:
			featured = 'False'
			if x == 1:
				featured = 'True'

			# if valuegaia is the source of this job
			if agency.source_application == 'GAIA':
				# export to valuegaia
				if external_id != fake_id:
					valuegaia.insert_photo(external_id, p['url'], p['title'], featured)
			else:
				pprint.pprint('There is no source application for this job')

			x = x + 1

		if external_id != fake_id:
			# sort photos at valuegaia
			valuegaia.sort_photos(external_id)
			create_activity('JOB_PUBLISHED_AT_VALUEGAIA', job=job)

	# send a message to property owner telling his job is finished
	_enqueue_job_approved_message(job)

	# send a message to broker telling his job is finished
	_enqueue_broker_job_approved_message(job)

	create_activity('JOB_FINISHED', job=job)

	# todo: implement a new message to the broker
	# telling him that new photos and videos has been added to his listing

	return '', 200
def create():

	# get the post data
	post_data = get_post_data()

	sender_broker = None
	owner = None
	agency = None
	listing = None

	# validates required parameters
	_validates_required_parameters(post_data)

	# creates or find the property owner
	if 'property_owner' in post_data:
		owner = _create_property_owner(post_data['property_owner'])

	# creates or find the agency
	if 'agency' in post_data:
		agency = _create_agency(post_data['agency'], post_data['source_application'])

	# creates or find the property
	if 'listing' in post_data:
		listing = _create_listing(post_data['listing'])

	# if broker is sent
	if 'sender' in post_data:
		# creates or find the broker
		sender_broker = _create_broker(post_data['sender'], agency)

	# defines the buyer type and creates the lead
	buyer_type = ''

	if 'sender' in post_data and owner is not None:
		buyer_type = 'PROPERTY_OWNER'
	else:
		buyer_type = 'PROPERTY_OWNER_FROM_GAIAFLIX'


	# check if the plan is valid
	plan = None
	if 'plan' in post_data:
		plan = Plan.find_by_slug(post_data['plan'])
		if plan is None:
			abort(400, {'message': PLAN_INVALID_OR_NOT_PROVIDED })
	else:
		abort(400, {'message': PLAN_INVALID_OR_NOT_PROVIDED })

	# creates the lead
	lead = Lead()

	lead.sender_broker = sender_broker.key if sender_broker is not None else None
	lead.property_owner = owner.key if owner is not None else None
	lead.listing = listing.key if listing is not None else None
	lead.plan = plan.key
	lead.buyer_type = buyer_type
	lead.status = 'SENT'

	if lead.put():
		json_lead = lead.to_json()

		if lead.property_owner is not None:
			_enqueue_lead_message(json_lead)
			create_activity('LEAD_SENT', lead=lead)

		return jsonify(data=json_lead), 201
	else:
		return jsonify({'error': 'Error creating Lead'})
def process_payment():
	lead_id = request.form['lead_id']
	payment_id = request.form['payment_id']

	logging.debug('###### BACKGROUND PROCESSING!')
	logging.debug('Lead Id: %s' % lead_id)
	logging.debug('Payment Id: %s' % payment_id)

	lead = _get_lead(int(lead_id))
	payment = Payment.get_by_id(int(payment_id))
	plan = payment.plan.get()

	property_owner = lead.property_owner.get()
	customer_data = property_owner.to_json()
	email = customer_data['email']
	credit_card_brand = customer_data['credit_card_brand']

	logging.debug('trying to find customer %s' % email)
	fc_result = superlogica.find_customer(email)
	payment.update_status('PENDING', 'Creating customer')

	customer_id = None
	if fc_result is not None:
		if len(fc_result['body']) > 0:
			pprint.pprint(fc_result)
			customer_id = fc_result['body'][0]['id_sacado_sac']
			logging.debug('customer %s found' % customer_id)
		else:
			logging.debug('customer not found.')

	if customer_id is None:
		logging.debug('customer not found. lets create a new one')
		customer_result = _try_create_customer(customer_data)
		customer_id = customer_result['id_sacado_sac']
		logging.debug('customer %s created' % customer_id)


	payment.update_status('PENDING', 'Creating billing')
	if customer_id is not None:
		logging.debug('creating billing')
		bl_result = superlogica.create_billing(customer_id, plan.price, payment.instalments, plan.erp_id)
		logging.debug('registering creditcard')

		billing = Billing()
		billing.erp_result = bl_result
		billing.lead = lead.key
		billing.put()

		payment.update_status('PENDING', 'Creating credit card')
		callback_url = URL_CALLBACK % plan.slug
		cc_result = superlogica.register_creditcard(email, credit_card_brand.lower(), callback_url)

		url = cc_result['body']['url']
		payment.iframe_url = url
		payment.put()
		payment.update_status('SUCCESS', 'Done')

		lead.status = 'PENDING_PAYMENT'
		lead.put()

		create_activity('LEAD_PENDING_PAYMENT', lead=lead)
	else:
		payment.update_status('ERROR', 'Cannot create customer or billing at ERP')

	return '', 200