Exemplo n.º 1
0
def validate_payment_detail(pd):
    if PaymentConfig.default_validations_disabled:
        return []

    errors = []
    if pd.insurance_number is None:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_INSURANCE_NB,
            'message': _("payment.validation.detail.reject.insurance_nb") % {
                'id': pd.id
            },
            'detail': pd.id
        }]

    if pd.product_code is None:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_PRODUCT_CODE,
            'message': _("payment.validation.detail.reject.product_code") % {
                'id': pd.id
            },
            'detail': pd.id
        }]

    if len(errors) > 0:
        return errors

    insuree = Insuree.filter_queryset().filter(chf_id=pd.insurance_number) \
        .first()
    if not insuree:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_INSURANCE_NB_INVALID,
            'message':
            _("payment.validation.detail.reject.insurance_nb_invalid") % {
                'id': pd.id,
                'chf': pd.insurance_number
            },
            'detail': pd.id
        }]
        return errors

    policy = Policy.filter_queryset()\
        .filter(product__validity_to__isnull=True, product__code=pd.product_code)\
        .filter(family__validity_to__isnull=True)\
        .filter(family__members__validity_to__isnull=True, family__members__chf_id=pd.insurance_number)\
        .first()

    if not policy:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_POLICY_NOT_FOUND,
            'message':
            _("payment.validation.detail.reject.policy_not_found") % {
                'id': pd.id,
                'chf': pd.insurance_number,
                'product_code': pd.product_code,
            },
            'detail': pd.id
        }]
        return errors

    location_cursor = insuree.family.location
    family_location_ids = []
    if location_cursor:
        for loc in LocationConfig.location_types:
            family_location_ids.append(location_cursor.id)
            location_cursor = location_cursor.parent
            if location_cursor is None:
                break

    # Original code checked the product validity against current_date, I used the enroll_date instead
    product = Product.filter_queryset().filter(
        Q(location_id__isnull=True) | Q(location_id__in=family_location_ids),
        date_from__lte=policy.enroll_date,
        date_to__gte=policy.enroll_date,
        code=pd.product_code,
    ).first()
    if not product:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_PRODUCT_NOT_ALLOWED,
            'message':
            _("payment.validation.detail.reject.product_not_allowed") % {
                'id': pd.id,
                'chf': pd.insurance_number,
                'product_code': pd.product_code,
            },
            'detail': pd.id
        }]
        return errors

    # Check enrollment officer
    officer = Officer.filter_queryset().filter(
        code=pd.payment.officer_code).first()
    if not product:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_OFFICER_NOT_FOUND,
            'message':
            _("payment.validation.detail.reject.officer_not_found") % {
                'id': pd.id,
                'chf': pd.insurance_number,
                'officer_code': pd.payment.officer_code,
            },
            'detail': pd.id
        }]
        return errors

    # Check officer district vs product location
    # TODO this checks district/region, should be more generic
    if not (officer.location is None or product is None
            or officer.location_id == product.location_id or
            (officer.location.parent is not None
             and officer.location.parent == product.location.parent)):
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_PRODUCT_LOCATION,
            'message':
            _("payment.validation.detail.reject.product_location") % {
                'id': pd.id,
                'chf': pd.insurance_number,
                'product_code': pd.product_code,
            },
            'detail': pd.id
        }]
        return errors

    # Check that there is a premium available for that policy
    # TODO avoid relying on max(id) as using uuids would ruin it
    latest_premium = policy.premiums.filter(
        validity_to__isnull=True).aggregate(Max("id"))
    if not latest_premium:
        errors += [{
            'code': PAYMENT_DETAIL_REJECTION_NO_PREMIUM,
            'message': _("payment.validation.detail.reject.no_premium") % {
                'id': pd.id,
                'policy': policy.uuid,
            },
            'detail': pd.id
        }]
        return errors

    # TODO instead of returning those, we should update the payment_detail with actual foreign keys
    pd.policy = policy
    pd.insuree = insuree
    pd.latest_premium = latest_premium
    pd.product = product
    return errors