ผลต่างระหว่างรุ่นของ "CuneiForm"

จาก คูนิฟ็อกซ์ วิกิ
บรรทัดที่ 58: บรรทัดที่ 58:
** '''{{code|lang=python|'amt'}}''': Numerical value, rounded to {{code|amt}} decimal places. ''(See Company Settings)''
** '''{{code|lang=python|'amt'}}''': Numerical value, rounded to {{code|amt}} decimal places. ''(See Company Settings)''
** '''{{code|lang=python|'int'}}''': Numerical value, rounded to nearest integer.
** '''{{code|lang=python|'int'}}''': Numerical value, rounded to nearest integer.
* '''File types'''
* '''File types*''' (See note below)
** '''{{code|lang=python|'file'}}''': File field with CuneiFox custom action buttons.
** '''{{code|lang=python|'file'}}''': File field with CuneiFox custom action buttons.
** '''{{code|lang=python|'img'}}''': File field with CuneiFox custom action buttons and an associated {{code|img}} HTML element.
** '''{{code|lang=python|'img'}}''': File field with CuneiFox custom action buttons and an associated {{code|img}} HTML element.

รุ่นแก้ไขเมื่อ 18:38, 5 เมษายน 2567

CuneiForm type objects are powered by WTForms engine. However, this object type also introduce a handful of additional variables and attributes to strike a sweet balance between ease of development and flexibility.

Define

Defining a CuneiForm is essentially similar to declaring a WTForm. There are no differences in declaring fields, validations, render keywords, and validating functions. (There exist a few special functions that can dynamically generate some common fields, but we'll leave that to a later section.)

Let's first have a quick look at a very basic CuneiForm:

class LoginForm(FlaskForm, CuneiForm):
    company = StringField("Company", validators=[InputRequired("Required!")])
    username = StringField("Username", validators=[InputRequired("Required!")])
    password = PasswordField("Password", validators=[InputRequired("Required!")])
    clear_session = BoolField("Log-out of other sessions", default=True)
    submit = SubmitField("Log-in")

    def validate_company(self, company):
        # Validation goes here
    def validate_username(self, username):
        # Validation goes here
    def validate_password(self, password):
        # Validation goes here

Developers might find uses of BoolField and IntField in CuneiFox code base unfamiliar. This convention is to avoid name conflict betweem WTForm and Peewee.

Special Value Types

This feature plays a crucial role in ensuring consistent value formatting for client-side output. While it originated as a solution to address browser formatting inconsistencies, it has evolved to serve several other purposes within the CuneiFox framework.

Original Intentions

Reading through the CuneiFox code base, one is sure to notice the excessive use of StringFields where one would expect DateFields, TimeFields, FloatFields, and IntegerFields as supported by WTForms. This design choice stems was made to address a challenging browser behaviour. Modern browsers tend to enforce formatting of fields marked as certain types based on the user's locale setting, which can be tied to either the operating system or the browser itself. This automatic formatting can be difficult to override or reverse, leading to inconsistencies and confusion on the user's part especially when switching workstations.

To address this issue, CuneiFox developed its own value typing. Our approach applies custom-made JavaScript codes on unformatted and untyped (as far as the browser is aware) fields. This way, the formatting rendered on the client-side perfectly obeys the company's specific preferences within the CuneiFox system.

Current Incarnation

Form value types are specified in the variable MASTER_sp_type residing within form definition code. The variable is of format:

MASTER_sptypes = [(str field_name0, str type0), (str field_name1, str type1), ...]

# Example from Accounting Journal's withholding tax form
MASTER_sptypes = [("taxdate", "date"), ("taxmonth", "month"),
                  ("rate", "pct"), ("amt", "acc"), ("tax", "acc"),
                  ("rate_2", "pct"), ("amt_2", "acc"), ("tax_2", "acc"),
                  ...]

Available Types

Special types valid within CuneiFox system are shown below:

  • Date types
    • 'date': Value with date, month, and year.
    • 'month': Value with only date and month.
  • Time types
    • 'time': Value with hour, minute, and second.
  • Numeric types
    • 'acc': Numerical value, rounded to acc decimal places. (See Company Settings)
    • 'pct': Numerical value, rounded to pct decimal places, with "%" sign appended. (See Company Settings)
    • 'qty': Numerical value, rounded to qty decimal places. (See Company Settings)
    • 'amt': Numerical value, rounded to amt decimal places. (See Company Settings)
    • 'int': Numerical value, rounded to nearest integer.
  • File types* (See note below)
    • 'file': File field with CuneiFox custom action buttons.
    • 'img': File field with CuneiFox custom action buttons and an associated img HTML element.
  • Other types
    • 'right': Normal string field whose text is aligned right rather than the normal left.
    • 'color': String field with an associated color selector element.

NOTE THAT when using file types, the typeX value is a 3-membered list instead:

  • Member 0: The type ('file' or 'img')
  • Member 1: The source ('data', 'table', 'files', 'print', 'qr', 'report')
  • Member 2: The sub-directory (string or None)

Instant Calculation

Instant calculation function within CuneiForms, or 'instacalc', allows a change in one form field to initiate a small calculation request to the server and update other affected fields based on the calculation result. It is specified in the variable MASTER_instacalc under form definition.

MASTER_instacalc = [(str trigger_fld0, [
                                           route0, 
                                           [str collect_fld00, str collect_fld01, ...],
                                           [str result_fld00, str result_fld01, ...]]),
                                           ...
                                       ]),
                   [(str trigger_fld1, [
                                           route1, 
                                           [str collect_fld10, str collect_fld11, ...],
                                           [str result_fld10, str result_fld11, ...]]),
                                           ...
                                       ]),
                    ...]

# Example from Accounting Journal's withholding tax form
MASTER_instacalc = [("amt", ["cunei_gl.calcwht", ["amt", "rate"], ["tax"]]),
                    ("rate", ["cunei_gl.calcwht", ["amt", "rate"], ["tax"]]),
                    ...]
  • trigger_fldX is the field whose value change will trigger the instacalc routine.
  • routeX can be either:
    • A string similar to the string argument fed to Flask's url_for.
    • A dict of format {'route': str route_name, **kwargs}, where kwargs represents arguments to be fed to the instacalc route.
  • collect_fldXY are the fields whose values are collected and used in calculation routine.
  • result_fldXY are the fields to be updated with the calculation result.

Developers also have the option to modify the form object's instacalc attribute after initiation. However, at this stage, the routeX part must be a Flask's url_for result instead.

Auto-numbering Function

Other Form Definition Variables

MASTER_firstonly

Initiate

Design & Pre-made Scripts

Notable Sub-routines