Example #1
0
 def updated_at(cls):
     """Timestamp for when this instance was last updated (via the app), in UTC"""
     return Column(
         TIMESTAMP(timezone=cls.__with_timezone__),
         default=func.utcnow(),
         onupdate=func.utcnow(),
         nullable=False)
Example #2
0
 def updated_at(cls):
     """Timestamp for when this instance was last updated (via the app), in UTC"""
     return Column(
         TIMESTAMP(timezone=cls.__with_timezone__),
         default=func.utcnow(),
         onupdate=func.utcnow(),
         nullable=False,
     )
Example #3
0
class TimestampMixin(object):
    """
    Provides the :attr:`created_at` and :attr:`updated_at` audit timestamps
    """
    query_class = Query
    #: Timestamp for when this instance was created, in UTC
    created_at = immutable(
        Column(DateTime, default=func.utcnow(), nullable=False))
    #: Timestamp for when this instance was last updated (via the app), in UTC
    updated_at = Column(DateTime,
                        default=func.utcnow(),
                        onupdate=func.utcnow(),
                        nullable=False)
Example #4
0
 def created_at(cls):
     """Timestamp for when this instance was created, in UTC"""
     return Column(
         TIMESTAMP(timezone=cls.__with_timezone__),
         default=func.utcnow(),
         nullable=False,
     )
Example #5
0
def process_partial_refund_for_order(data_dict):
    order = data_dict['order']
    form = data_dict['form']
    request_method = data_dict['request_method']

    if request_method == 'GET':
        return jsonify(form_template=render_form(form=form, title=u"Partial refund", submit=u"Refund", with_chrome=False))
    if form.validate_on_submit():
        requested_refund_amount = form.amount.data
        payment = OnlinePayment.query.filter_by(order=order, pg_payment_status=RAZORPAY_PAYMENT_STATUS.CAPTURED).one()
        rp_resp = razorpay.refund_payment(payment.pg_paymentid, requested_refund_amount)
        rp_refund = rp_resp.json()
        if rp_resp.status_code == 200:
            transaction = PaymentTransaction(order=order, transaction_type=TRANSACTION_TYPE.REFUND,
                online_payment=payment, currency=CURRENCY.INR, pg_refundid=rp_refund['id'],
                refunded_at=func.utcnow())
            form.populate_obj(transaction)
            db.session.add(transaction)
            db.session.commit()
            send_order_refund_mail.queue(order.id, transaction.amount, transaction.note_to_user)
            return api_success(result={'order_net_amount': order.net_amount},
                doc=_(u"Refund processed for order"), status_code=200)
        else:
            raise PaymentGatewayError("Refund failed for order - {order} with the following details - {msg}".format(order=order.id,
                msg=rp_refund['error']['description']), 424,
            "Refund failed. {reason}. Please try again or contact support at {email}.".format(reason=rp_refund['error']['description'], email=order.organization.contact_email))
    else:
        return api_error(message='Invalid input',
            status_code=403,
            errors=form.errors)
Example #6
0
def process_line_item_cancellation(line_item):
    order = line_item.order
    # initialize refund_amount to 0
    refund_amount = Decimal(0)

    if (not line_item.is_free) and order.net_amount > Decimal('0'):
        if line_item.discount_policy:
            pre_cancellation_order_amount = order.get_amounts(
                LINE_ITEM_STATUS.CONFIRMED
            ).confirmed_amount - order.refunded_amount
            pre_cancellation_line_items = order.confirmed_line_items
            line_item.cancel()
            updated_order = update_order_on_line_item_cancellation(
                order, pre_cancellation_line_items, line_item)
            post_cancellation_order_amount = updated_order.get_amounts(
                LINE_ITEM_STATUS.CONFIRMED
            ).confirmed_amount - order.refunded_amount
            refund_amount = pre_cancellation_order_amount - post_cancellation_order_amount
        else:
            line_item.cancel()
            refund_amount = line_item.final_amount

        if refund_amount > order.net_amount:
            # since the refund amount is more than the net amount received
            # only refund the remaining amount
            refund_amount = order.net_amount

    if refund_amount > Decimal('0'):
        payment = OnlinePayment.query.filter_by(
            order=line_item.order,
            pg_payment_status=RAZORPAY_PAYMENT_STATUS.CAPTURED).one()
        rp_resp = razorpay.refund_payment(payment.pg_paymentid, refund_amount)
        rp_refund = rp_resp.json()
        if rp_resp.status_code == 200:
            db.session.add(
                PaymentTransaction(
                    order=order,
                    transaction_type=TRANSACTION_TYPE.REFUND,
                    pg_refundid=rp_refund['id'],
                    online_payment=payment,
                    amount=refund_amount,
                    currency=CURRENCY.INR,
                    refunded_at=func.utcnow(),
                    refund_description="Refund: {line_item_title}".format(
                        line_item_title=line_item.item.title)))
        else:
            raise PaymentGatewayError(
                "Cancellation failed for order - {order} with the following details - {msg}"
                .format(order=order.id,
                        msg=rp_refund['error']['description']), 424,
                "Refund failed. {reason}. Please try again or write to us at {email}."
                .format(reason=rp_refund['error']['description'],
                        email=line_item.order.organization.contact_email))
    else:
        # no refund applicable, just cancel the line item
        line_item.cancel()
    db.session.commit()
    return refund_amount
Example #7
0
def process_partial_refund_for_order(data_dict):
    order = data_dict['order']
    form = data_dict['form']
    request_method = data_dict['request_method']

    if request_method == 'GET':
        return jsonify(form_template=render_form(form=form,
                                                 title="Partial refund",
                                                 submit="Refund",
                                                 with_chrome=False).get_data(
                                                     as_text=True))
    if form.validate_on_submit():
        requested_refund_amount = form.amount.data
        payment = OnlinePayment.query.filter_by(
            order=order,
            pg_payment_status=RAZORPAY_PAYMENT_STATUS.CAPTURED).one()
        rp_resp = razorpay.refund_payment(payment.pg_paymentid,
                                          requested_refund_amount)
        rp_refund = rp_resp.json()
        if rp_resp.status_code == 200:
            transaction = PaymentTransaction(
                order=order,
                transaction_type=TRANSACTION_TYPE.REFUND,
                online_payment=payment,
                currency=CURRENCY.INR,
                pg_refundid=rp_refund['id'],
                refunded_at=func.utcnow(),
            )
            form.populate_obj(transaction)
            db.session.add(transaction)
            db.session.commit()
            send_order_refund_mail.queue(order.id, transaction.amount,
                                         transaction.note_to_user)
            return api_success(
                result={'order_net_amount': order.net_amount},
                doc=_("Refund processed for order"),
                status_code=200,
            )
        else:
            raise PaymentGatewayError(
                "Refund failed for order - {order} with the following details - {msg}"
                .format(order=order.id, msg=rp_refund['error']['description']),
                424,
                "Refund failed. {reason}. Please try again or contact support at {email}."
                .format(
                    reason=rp_refund['error']['description'],
                    email=order.organization.contact_email,
                ),
            )
    else:
        return api_error(message='Invalid input',
                         status_code=403,
                         errors=form.errors)
Example #8
0
def process_partial_refund_for_order(order, form_dict):
    form = RefundTransactionForm.from_json(form_dict, meta={'csrf': False})
    if form.validate():
        requested_refund_amount = form.amount.data
        if not order.paid_amount:
            return api_error(
                message='Refunds can only be issued for paid orders',
                status_code=403,
                errors=['non cancellable'])

        if (order.refunded_amount +
                requested_refund_amount) > order.paid_amount:
            return api_error(
                message=
                'Invalid refund amount, must be lesser than net amount paid for the order',
                status_code=403,
                errors=['excess partial refund'])

        payment = OnlinePayment.query.filter_by(
            order=order,
            pg_payment_status=RAZORPAY_PAYMENT_STATUS.CAPTURED).one()
        rp_resp = razorpay.refund_payment(payment.pg_paymentid,
                                          requested_refund_amount)
        if rp_resp.status_code == 200:
            rp_refund = rp_resp.json()
            transaction = PaymentTransaction(
                order=order,
                transaction_type=TRANSACTION_TYPE.REFUND,
                online_payment=payment,
                currency=CURRENCY.INR,
                pg_refundid=rp_refund['id'],
                refunded_at=func.utcnow())
            form.populate_obj(transaction)
            db.session.add(transaction)
            db.session.commit()
            send_order_refund_mail.delay(order.id, transaction.amount,
                                         transaction.note_to_user)
            return api_success(result={'order_net_amount': order.net_amount},
                               doc=_(u"Refund processed for order"),
                               status_code=200)
        else:
            raise PaymentGatewayError(
                "Refund failed for order - {order} with the following details - {msg}"
                .format(order=order.id, msg=rp_resp.content), 424,
                "Refund failed. Please try again or contact support at {email}."
                .format(email=order.organization.contact_email))
    else:
        return api_error(message='Invalid input',
                         status_code=403,
                         errors=form.errors)
Example #9
0
class Measurements(db.Model):
    # Define the columns of the table, including primary keys, unique, and
    # indexed fields, which makes searching faster
    __tablename__ = 'measurements'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(
        db.String(256), nullable=False
    )  #name of the measurement, such as temperature, pressure, etc.
    value = db.Column(db.String(256),
                      nullable=False)  #value of the measurement
    device = db.Column(db.Integer, db.ForeignKey('devices.id'), nullable=False)
    created_date = db.Column(
        DateTime(), server_default=func.now())  #time of the measurement
    updated_date = db.Column(DateTime(), onupdate=func.utcnow())

    def __repr__(self):
        return '<Measurement {}>'.format(self.id)  #prints <Measurement 'id'>
Example #10
0
class Devices(db.Model):
    # Define the columns of the table, including primary keys, unique, and
    # indexed fields, which makes searching faster
    __tablename__ = 'devices'

    id = db.Column(db.Integer, primary_key=True)  #id of the device
    device_name = db.Column(db.String(256), nullable=False)
    device_owner = db.Column(
        db.Integer,
        db.ForeignKey('customers.id'))  #connect each device to a customer
    device_measurements = db.relationship('Measurements',
                                          backref='devices',
                                          lazy=True)
    created_date = db.Column(
        DateTime(), server_default=func.now()
    )  #func.now() tells the db to calculate the timestamp itself rather than letting the application do it
    updated_date = db.Column(DateTime(), onupdate=func.utcnow())

    def __repr__(self):
        return '<Device {}>'.format(self.id)  #prints <Device 'id'>
Example #11
0
 def make_void(self):
     self.status = LINE_ITEM_STATUS.VOID
     self.cancelled_at = func.utcnow()
Example #12
0
 def cancel(self):
     """Sets status and cancelled_at."""
     self.status = LINE_ITEM_STATUS.CANCELLED
     self.cancelled_at = func.utcnow()
Example #13
0
def process_line_item_cancellation(line_item):
    order = line_item.order
    # initialize refund_amount to 0
    refund_amount = Decimal(0)

    if (not line_item.is_free) and order.net_amount > Decimal('0'):
        if line_item.discount_policy:
            pre_cancellation_order_amount = order.get_amounts(LINE_ITEM_STATUS.CONFIRMED).confirmed_amount - order.refunded_amount
            pre_cancellation_line_items = order.confirmed_line_items
            line_item.cancel()
            updated_order = update_order_on_line_item_cancellation(order, pre_cancellation_line_items, line_item)
            post_cancellation_order_amount = updated_order.get_amounts(LINE_ITEM_STATUS.CONFIRMED).confirmed_amount - order.refunded_amount
            refund_amount = pre_cancellation_order_amount - post_cancellation_order_amount
        else:
            line_item.cancel()
            refund_amount = line_item.final_amount

        if refund_amount > order.net_amount:
            # since the refund amount is more than the net amount received
            # only refund the remaining amount
            refund_amount = order.net_amount

    if refund_amount > Decimal('0'):
        payment = OnlinePayment.query.filter_by(order=line_item.order, pg_payment_status=RAZORPAY_PAYMENT_STATUS.CAPTURED).one()
        rp_resp = razorpay.refund_payment(payment.pg_paymentid, refund_amount)
        rp_refund = rp_resp.json()
        if rp_resp.status_code == 200:
            db.session.add(PaymentTransaction(order=order, transaction_type=TRANSACTION_TYPE.REFUND,
                pg_refundid=rp_refund['id'], online_payment=payment, amount=refund_amount, currency=CURRENCY.INR, refunded_at=func.utcnow(),
                refund_description='Refund: {line_item_title}'.format(line_item_title=line_item.item.title)))
        else:
            raise PaymentGatewayError("Cancellation failed for order - {order} with the following details - {msg}".format(order=order.id,
                msg=rp_refund['error']['description']), 424,
            'Refund failed. {reason}. Please try again or write to us at {email}.'.format(reason=rp_refund['error']['description'], email=line_item.order.organization.contact_email))
    else:
        # no refund applicable, just cancel the line item
        line_item.cancel()
    db.session.commit()
    return refund_amount
Example #14
0
 def fail(self):
     """Fails a payment, sets failed_at."""
     self.pg_payment_status = RAZORPAY_PAYMENT_STATUS.FAILED
     self.failed_at = func.utcnow()
Example #15
0
 def confirm(self):
     """Confirms a payment, sets confirmed_at and pg_payment_status."""
     self.confirmed_at = func.utcnow()
     self.pg_payment_status = RAZORPAY_PAYMENT_STATUS.CAPTURED
Example #16
0
def make_timestamp_columns():
    return (
        Column('created_at', DateTime, default=func.utcnow(), nullable=False),
        Column('updated_at', DateTime, default=func.utcnow(), onupdate=func.utcnow(), nullable=False),
        )
Example #17
0
class RuleDB(UIDFieldMixin, Base):
    """Db Schema for Rules table. Specifies the action to invoke on the occurrence of a Trigger. It
    also includes the transformation to perform to match the impedance
    between the payload of a TriggerInstance and input of a action.
    Attribute:
        trigger: Trigger that trips this rule.
        criteria:
        action: Action to execute when the rule is tripped.
        status: enabled or disabled. If disabled occurrence of the trigger
        does not lead to execution of a action and vice-versa.

    EXAMPLE:

    ---
    name: "rule_name"                      # required
    pack: "examples"                       # optional
    description: "Rule description."       # optional
    enabled: true                          # required

    trigger:                               # required
        type: "trigger_type_ref"

    criteria:                              # optional
        trigger.payload_parameter_name1:
            type: "regex"
            pattern : "^value$"
        trigger.payload_parameter_name2:
            type: "iequals"
            pattern : "watchevent"

    action:                                # required
        ref: "action_ref"
        parameters:                        # optional
            foo: "bar"
            baz: "{{ trigger.payload_parameter_1 }}"
    """

    RESOURCE_TYPE = ResourceType.RULE
    UID_FIELDS = ["packs_name", "name"]

    __tablename__ = "rules"

    id = Column("id", Integer, primary_key=True, index=True)
    name = Column("name", String(255))
    ref = Column("ref", String(255))
    description = Column("description", String(255))
    # trigger_type = Column(String(255))
    trigger = Column("trigger", String(255))

    # FIXME: This needs to be RuleTypeSpecDB
    type = Column("type", String(255))
    enabled = Column("enabled", Boolean)
    # FIXME: This needs to be ActionExecutionSpecDB
    # EG. action = me.EmbeddedDocumentField(ActionExecutionSpecDB)
    action = Column("action", String(255))

    packs_id = Column("packs_id",
                      Integer,
                      ForeignKey("packs.id"),
                      nullable=True)
    packs_name = Column("packs_name",
                        Integer,
                        ForeignKey("packs.name"),
                        nullable=True)
    # FIX: sqlalchemy Error creating backref on relationship
    # https://stackoverflow.com/questions/26693041/sqlalchemy-error-creating-backref-on-relationship
    pack = relationship("Packs",
                        backref=backref("pack_rules", uselist=False),
                        foreign_keys=[packs_id])

    criteria = Column("criteria", JSON)
    context = Column("context", JSON)
    created_at = Column(DateTime(timezone=True), server_default=func.utcnow())
    updated_at = Column(DateTime(timezone=True), onupdate=func.utcnow())

    def __init__(self, *args, **values):
        super(RuleDB, self).__init__(*args, **values)
        self.ref = self.get_reference().ref
        self.uid = self.get_uid()

    def get_reference(self):
        """
        Retrieve referene object for this model.

        :rtype: :class:`ResourceReference`
        """
        if getattr(self, "ref", None):
            ref = ResourceReference.from_string_reference(ref=self.ref)
        else:
            ref = ResourceReference(pack=self.pack, name=self.name)

        return ref

    def __repr__(self):
        result = []
        result.append("RuleDB@")
        result.append(str(id(self)))
        result.append('<ref="%s>", ' % self.ref)
        return "".join(result)
Example #18
0
 def make_void(self):
     self.status = LINE_ITEM_STATUS.VOID
     self.cancelled_at = func.utcnow()
Example #19
0
 def created_at(cls):
     """Timestamp for when this instance was created, in UTC"""
     return Column(
         TIMESTAMP(timezone=cls.__with_timezone__),
         default=func.utcnow(),
         nullable=False)
 def cancel(self):
     """
     Sets status and cancelled_at.
     """
     self.status = LINE_ITEM_STATUS.CANCELLED
     self.cancelled_at = func.utcnow()