コード例 #1
0
def declare_logic():

    Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountOwed)

    Rule.formula(derive=Order.AmountOwed,
                 as_expression=lambda row: row.AmountTotal - row.AmountPaid)
    Rule.sum(derive=Order.AmountPaid,
             as_sum_of=PaymentAllocation.AmountAllocated)

    Rule.formula(
        derive=PaymentAllocation.AmountAllocated,
        as_expression=lambda row: min(Decimal(row.Payment.AmountUnAllocated),
                                      Decimal(row.Order.AmountOwed)))

    Rule.early_row_event(on_class=Payment, calling=allocate_payment)
    """
コード例 #2
0
ファイル: rules_bank.py プロジェクト: valhuber/LogicBank
def declare_logic():

    Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountOwed)

    Rule.formula(derive=Order.AmountOwed,
                 as_expression=lambda row: row.AmountTotal - row.AmountPaid)
    Rule.sum(derive=Order.AmountPaid,
             as_sum_of=PaymentAllocation.AmountAllocated)

    Rule.formula(
        derive=PaymentAllocation.AmountAllocated,
        as_expression=lambda row: min(Decimal(row.Payment.AmountUnAllocated),
                                      Decimal(row.Order.AmountOwed)))

    RuleExtension.allocate(provider=Payment,
                           recipients=unpaid_orders,
                           creating_allocation=PaymentAllocation)
    """
コード例 #3
0
ファイル: tutorial_logic.py プロジェクト: valhuber/LogicBank
def declare_logic():
    """
    activate, then rules applied on commit

    automatically invoked, ordered and optimized
    """

    explore_rules = False   # set True to explore rules
    if explore_rules:
        Rule.constraint(validate=Customer,
                        error_msg="balance ({row.Balance}) exceeds 2000)",
                        as_condition=lambda row: row.Balance <= 2000)

        Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal)

    explore_extensibility = False  # set True to explore extensibility
    if explore_extensibility:

        def follow_up(row: Order, old_row: Order, logic_row: LogicRow):
            if logic_row.ins_upd_dlt == "upd":
                if logic_row.row.AmountTotal < logic_row.old_row.AmountTotal:
                    print("\nStub: send email to sales manager to follow up\n")

        Rule.commit_row_event(on_class=Order, calling=follow_up)
コード例 #4
0
def activate_basic_check_credit_rules():
    """
    Issues function calls to activate check credit rules, below.
        These rules are executed not now, but on commits
        Order is irrelevant - determined by system based on dependency analysis
        Their inclusion in classes is for doc / convenience, no semantics

    These rules apply to all transactions (automatic re-use), eg.
    * place order
    * change Order Detail product, quantity
    * add/delete Order Detail
    * ship / unship order
    * delete order
    * move order to new customer, etc
    """

    def units_in_stock(row: Product, old_row: Product, logic_row: LogicRow):
        result = row.UnitsInStock - (row.UnitsShipped - old_row.UnitsShipped)
        return result

    def congratulate_sales_rep(row: Order, old_row: Order, logic_row: LogicRow):
        if logic_row.ins_upd_dlt == "ins" or True:  # logic engine fills parents for insert
            sales_rep = row.SalesRep  # type : Employee
            if sales_rep is None:
                logic_row.log("no salesrep for this order")
            else:
                logic_row.log(f'Hi, {sales_rep.Manager.FirstName}, congratulate {sales_rep.FirstName} on their new order')

    Rule.constraint(validate=Customer,
                    as_condition=lambda row: row.Balance <= row.CreditLimit,
                    error_msg="balance ({row.Balance}) exceeds credit ({row.CreditLimit})")
    Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal,
             where=lambda row: row.ShippedDate is None)  # *not* a sql select sum...

    Rule.sum(derive=Order.AmountTotal, as_sum_of=OrderDetail.Amount)

    Rule.formula(derive=OrderDetail.Amount, as_expression=lambda row: row.UnitPrice * row.Quantity)
    Rule.copy(derive=OrderDetail.UnitPrice, from_parent=Product.UnitPrice)

    Rule.formula(derive=OrderDetail.ShippedDate, as_exp="row.OrderHeader.ShippedDate")

    Rule.sum(derive=Product.UnitsShipped, as_sum_of=OrderDetail.Quantity,
             where="row.ShippedDate is not None")
    Rule.formula(derive=Product.UnitsInStock, calling=units_in_stock)

    Rule.commit_row_event(on_class=Order, calling=congratulate_sales_rep)

    Rule.count(derive=Customer.UnpaidOrderCount, as_count_of=Order,
             where=lambda row: row.ShippedDate is None)  # *not* a sql select sum...

    Rule.count(derive=Customer.OrderCount, as_count_of=Order)
コード例 #5
0
ファイル: logic.py プロジェクト: valhuber/LogicBank
def declare_logic():
    """
    Issues function calls to activate rules for check credit (etc), below.
        These rules are executed not now, but on commits
        Order is irrelevant - determined by system based on dependency analysis
        Their inclusion in classes is for doc / convenience, no semantics

    These rules apply to all transactions (automatic re-use), eg.
    * place order
    * change Order Detail product, quantity
    * add/delete Order Detail
    * ship / unship order
    * delete order
    * move order to new customer, etc

    Activate rules like this

        LogicBank.activate(session=session, activator=declare_logic)
    """

    def congratulate_sales_rep(row: Order, old_row: Order, logic_row: LogicRow):
        if logic_row.ins_upd_dlt == "ins":  # logic engine fills parents for insert
            sales_rep = row.SalesRep  # type : Employee
            if sales_rep is None:
                logic_row.log("no salesrep for this order")
            else:
                logic_row.log(f'Hi, {sales_rep.Manager.FirstName}, congratulate {sales_rep.FirstName} on their new order')

    Rule.constraint(validate=Customer,
                    as_condition=lambda row: row.Balance <= row.CreditLimit,
                    error_msg="balance ({row.Balance}) exceeds credit ({row.CreditLimit})")
    Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal,
             where=lambda row: row.ShippedDate is None)  # *not* a sql select sum...

    Rule.sum(derive=Order.AmountTotal, as_sum_of=OrderDetail.Amount)

    Rule.formula(derive=OrderDetail.Amount, as_expression=lambda row: row.UnitPrice * row.Quantity)
    Rule.copy(derive=OrderDetail.UnitPrice, from_parent=Product.UnitPrice)

    Rule.commit_row_event(on_class=Order, calling=congratulate_sales_rep)

    Rule.formula(derive=OrderDetail.ShippedDate, as_exp="row.OrderHeader.ShippedDate")

    def units_in_stock(row: Product, old_row: Product, logic_row: LogicRow):
        result = row.UnitsInStock - (row.UnitsShipped - old_row.UnitsShipped)
        return result
    Rule.sum(derive=Product.UnitsShipped, as_sum_of=OrderDetail.Quantity,
             where="row.ShippedDate is not None")
    Rule.formula(derive=Product.UnitsInStock, calling=units_in_stock)

    Rule.count(derive=Customer.UnpaidOrderCount, as_count_of=Order,
             where=lambda row: row.ShippedDate is None)  # *not* a sql select sum...

    Rule.count(derive=Customer.OrderCount, as_count_of=Order)

    Rule.constraint(validate=OrderClass,
                    as_condition=lambda row: row.Id <= 99999,
                    error_msg="Test constraint for className <> tableName")

    Rule.constraint(validate=Employee,
                    as_condition=lambda row: row.IsCommissioned == 1 or row.order_count == 0,
                    error_msg="{row.LastName} is not commissioned - cannot have orders")

    Rule.count(derive=Employee.order_count, as_count_of=Order)

    def raise_over_20_percent(row: Employee, old_row: Employee, logic_row: LogicRow):
        if logic_row.ins_upd_dlt == "upd" and row.Salary != old_row.Salary:
            return row.Salary >= Decimal('1.20') * old_row.Salary
        else:
            return True

    Rule.constraint(validate=Employee,
                    calling=raise_over_20_percent,
                    error_msg="{row.LastName} needs a more meaningful raise")

    def audit_by_event(row: Employee, old_row: Employee, logic_row: LogicRow):
        tedious = False  # tedious code to repeat for every audited class
        if tedious:      # see instead the following rule extension - nw_copy_row
            if logic_row.are_attributes_changed([Employee.Salary, Employee.Title]):
                copy_to_logic_row = logic_row.new_logic_row(EmployeeAudit)
                copy_to_logic_row.link(to_parent=logic_row)
                copy_to_logic_row.set_same_named_attributes(logic_row)
                copy_to_logic_row.insert(reason="Manual Copy " + copy_to_logic_row.name)  # triggers rules...
                # logic_row.log("audit_by_event (Manual Copy) complete")

    Rule.commit_row_event(on_class=Employee, calling=audit_by_event)

    """ also provided in system version
    RuleExtension.copy(copy_from=Employee,
                       copy_to=EmployeeAudit,
                       copy_when=lambda logic_row: logic_row.are_attributes_changed([Employee.Salary, Employee.Title]))
    """

    NWRuleExtension.nw_copy_row(copy_from=Employee,
                                copy_to=EmployeeAudit,
                                copy_when=lambda logic_row:
                                    logic_row.are_attributes_changed([Employee.Salary, Employee.Title]))

    def handle_all(logic_row: LogicRow):
        row = logic_row.row
        if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
            row.CreatedOn = datetime.datetime.now()
            logic_row.log("early_row_event_all_classes - handle_all sets 'Created_on"'')

    Rule.early_row_event_all_classes(early_row_event_all_classes=handle_all)
コード例 #6
0
def activate_basic_rules():

    def transfer_funds(row: TRANSFERFUND, old_row: TRANSFERFUND, logic_row: LogicRow):
        if logic_row.ins_upd_dlt == "ins" or True:  # logic engine fills parents for insert
            logic_row.log("Transfer from source to target")
            fromCustNum = row.FromCustNum
            toCustNum = row.ToCustNum
            acctNum = row.FromAcct
            trans_date = datetime.datetime(2020, 10, 1)
            transferAmt = row.TransferAmt
            transID = row.TransId
            # need to lookup the From Acct to see if it is checking or savings - that way we can reverse the flow
            deposit = models.SAVINGSTRANS(TransId=transID, CustNum=toCustNum, AcctNum=acctNum, DepositAmt=transferAmt, WithdrawlAmt=0,
                                          TransDate=trans_date)
            logic_row.insert("Deposit to savings", deposit)
            withdrawl = models.CHECKINGTRANS(TransId=transID, CustNum=fromCustNum, AcctNum=acctNum,
                                             DepositAmt=0, WithdrawlAmt=transferAmt, TransDate=trans_date)
            logic_row.insert("Withdraw from CHECKINGTRANS", withdrawl)

    Rule.sum(derive=CHECKING.Deposits, as_sum_of=CHECKINGTRANS.DepositAmt)
    Rule.sum(derive=CHECKING.Withdrawls, as_sum_of=CHECKINGTRANS.WithdrawlAmt)
    Rule.formula(derive=CHECKING.AvailableBalance, as_expression=lambda  row: row.Deposits - row.Withdrawls)
    Rule.count(derive=CHECKING.ItemCount, as_count_of=CHECKINGTRANS)

    Rule.sum(derive=CUSTOMER.CheckingAcctBal, as_sum_of=CHECKING.AvailableBalance)
    Rule.sum(derive=CUSTOMER.SavingsAcctBal, as_sum_of=SAVING.AvailableBalance)
    Rule.formula(derive=CUSTOMER.TotalBalance, as_expression=lambda row: row.CheckingAcctBal + row.SavingsAcctBal)
    Rule.constraint(validate=CUSTOMER,
                    as_condition=lambda row: row.CheckingAcctBal >= 0,
                    error_msg="Your Checking balance of ({row.CheckingAcctBal}) is less than 0)")
    Rule.constraint(validate=CUSTOMER,
                    as_condition=lambda row: row.SavingsAcctBal >= 0,
                    error_msg="Your Savings balance of ({row.SavingsAcctBal}) is less than 0)")

    Rule.sum(derive=SAVING.Withdrawls, as_sum_of=SAVINGSTRANS.WithdrawlAmt)
    Rule.sum(derive=SAVING.Deposits, as_sum_of=SAVINGSTRANS.DepositAmt)
    Rule.formula(derive=SAVING.AvailableBalance, as_expression=lambda row: row.Deposits - row.Withdrawls)
    Rule.count(derive=SAVING.ItemCount, as_count_of=SAVINGSTRANS)

    Rule.formula(derive=CHECKINGTRANS.Total, as_expression=lambda row: row.DepositAmt - row.WithdrawlAmt)
    Rule.formula(derive=SAVINGSTRANS.Total, as_expression=lambda row: row.DepositAmt - row.WithdrawlAmt)

    Rule.commit_row_event(on_class=TRANSFERFUND, calling=transfer_funds)