class EngineerHistoryInResultForm(FlaskForm): payment_per_month = IntegerField('支払単価', render_kw={"disabled": "disabled"}) payment_rule = RadioField('支払ルール', [validators.optional()], choices=Rule.get_rule_for_select(), render_kw={"disabled": "disabled"}) payment_bottom_base_hour = IntegerField('支払下限基準時間', render_kw={"disabled": "disabled"}) payment_top_base_hour = IntegerField('支払上限基準時間', render_kw={"disabled": "disabled"}) payment_free_base_hour = StringField('支払フリー基準時間', [Length(max=128)], render_kw={"disabled": "disabled"}) payment_per_hour = StringField('支払時間単価', [Length(max=128)], render_kw={"disabled": "disabled"}) payment_per_bottom_hour = IntegerField('支払△下限時間単価', render_kw={"disabled": "disabled"}) payment_per_top_hour = IntegerField('支払+上限時間単価', render_kw={"disabled": "disabled"}) payment_fraction = SelectField('支払端数金額', [validators.Optional()], choices=Fraction.get_fraction_for_select(), filters=[lambda x: x or None], render_kw={"title": "支払端数金額", "disabled": "disabled"}) payment_fraction_rule = SelectField('支払端数ルール', [validators.optional()], choices=Round.get_round_for_select(), render_kw={"title": "支払端数ルール", "disabled": "disabled"})
class ProjectDetailInResultForm(FlaskForm): project_id = HiddenField('プロジェクトId') billing_per_month = IntegerField('請求単価', render_kw={"disabled": "disabled"}) billing_rule = RadioField('請求ルール', [validators.optional()], choices=Rule.get_rule_for_select(), render_kw={"disabled": "disabled"}) billing_bottom_base_hour = IntegerField('請求下限基準時間', render_kw={"disabled": "disabled"}) billing_top_base_hour = IntegerField('請求上限基準時間', render_kw={"disabled": "disabled"}) billing_free_base_hour = StringField('請求フリー基準時間', [Length(max=128)], render_kw={"disabled": "disabled"}) billing_per_hour = StringField('請求時間単価', [Length(max=128)], render_kw={"disabled": "disabled"}) billing_per_bottom_hour = IntegerField('請求△下限時間単価', render_kw={"disabled": "disabled"}) billing_per_top_hour = IntegerField('請求+上限時間単価', render_kw={"disabled": "disabled"}) billing_fraction = SelectField('請求端数金額', [validators.Optional()], choices=Fraction.get_fraction_for_select(), filters=[lambda x: x or None], render_kw={"title": "請求端数金額", "disabled": "disabled"}) billing_fraction_rule = SelectField('請求端数ルール', [validators.optional()], choices=Round.get_round_for_select(), render_kw={"title": "請求端数ルール", "disabled": "disabled"})
def test_parse_fail_is_none(self): self.assertIsNone(Rule.parse(0)) self.assertIsNone(Rule.parse('a'))
def test_parse(self): fixed = 1 variable = 2 self.assertEqual(Rule.parse(fixed), Rule.fixed) self.assertEqual(Rule.parse(variable), Rule.variable)
def detail(project_detail_id=None): project_id = request.args.get('project_id') project_detail = project_detail_service.find_by_id(project_detail_id) if project_detail.id is None and project_detail_id is not None \ or project_detail.project is None and project_id is None: return abort(404) form = ProjectDetailForm(request.form, obj=project_detail) form.engineer_id.choices = engineer_history_service.find_contract_for_select() # 新規作成時にはprojectを取得する。 if project_id: project_detail.project = project_service.find_by_id(project_id) if form.engineer_id.data: project_detail.engineer = engineer_service.find_by_id(form.engineer_id.data) if form.detail_type.data == str(DetailType.engineer) and project_detail.engineer is not None\ and form.billing_start_day.data is not None: engineer_history = engineer_history_service.get_history_by_start_day(project_detail.engineer.id, form.billing_start_day.data) if project_detail.engineer.company: form.company.data = project_detail.engineer.company.company_name if engineer_history: form.payment_start_day.data = engineer_history.payment_start_day form.payment_end_day.data = engineer_history.payment_end_day form.payment_per_month.data = engineer_history.payment_per_month form.payment_rule.data = str(engineer_history.payment_rule) form.payment_bottom_base_hour.data = engineer_history.payment_bottom_base_hour form.payment_top_base_hour.data = engineer_history.payment_top_base_hour form.payment_free_base_hour.data = engineer_history.payment_free_base_hour form.payment_per_hour.data = engineer_history.payment_per_hour form.payment_per_bottom_hour.data = engineer_history.payment_per_bottom_hour form.payment_per_top_hour.data = engineer_history.payment_per_top_hour form.payment_fraction.data = engineer_history.payment_fraction form.payment_fraction_rule.data = str(engineer_history.payment_fraction_rule) if form.validate_on_submit(): project_detail.project_id = project_detail.project.id project_detail.detail_type = DetailType.parse(form.detail_type.data) project_detail.work_name = form.work_name.data project_detail.engineer = project_detail.engineer project_detail.billing_money = form.billing_money.data project_detail.remarks = form.remarks.data project_detail.billing_start_day = form.billing_start_day.data project_detail.billing_end_day = form.billing_end_day.data project_detail.billing_per_month = form.billing_per_month.data project_detail.billing_rule = Rule.parse(form.billing_rule.data) project_detail.billing_bottom_base_hour = form.billing_bottom_base_hour.data project_detail.billing_top_base_hour = form.billing_top_base_hour.data project_detail.billing_free_base_hour = form.billing_free_base_hour.data project_detail.billing_per_hour = form.billing_per_hour.data project_detail.billing_per_bottom_hour = form.billing_per_bottom_hour.data project_detail.billing_per_top_hour = form.billing_per_top_hour.data project_detail.billing_fraction = Fraction.parse(form.billing_fraction.data) project_detail.billing_fraction_rule = Round.parse(form.billing_fraction_rule.data) project_detail.bp_order_no = form.bp_order_no.data project_detail.client_order_no_for_bp = form.client_order_no_for_bp.data project_detail_service.save(project_detail) flash(Message.saved.value) return redirect(url_for('.detail', project_detail_id=project_detail.id)) current_app.logger.debug(form.errors) if form.errors: flash(Message.saving_failed.value, 'error') return render_template('project/contract/detail.html', form=form, project_detail=project_detail)
class ProjectDetailForm(FlaskForm): id = IntegerField('Id') detail_type = RadioField('明細区分(必須)', [DataRequired()], choices=DetailType.get_type_for_select(), render_kw={"disabled": "disabled"}) work_name = StringField('作業名称(必須)', [Length(max=128), required_if_work], filters=[lambda x: x or None]) engineer_id = SelectFieldWithDisable('技術者名称(必須)', [required_if_engineer], render_kw={ "title": "技術者名称(必須)", "data-live-search": "true", "data-size": "8", "data-actions-box": "true" }) company = StringField('所属会社', render_kw={"disabled": "disabled"}) billing_money = IntegerField( '請求金額(必須)', [InputRequired(), NumberRange(min=-1000000000, max=1000000000)]) remarks = TextAreaField('備考', [Length(max=1024)], filters=[lambda x: x or None]) billing_start_day = BeginningOfMonthField( '請求契約開始年月(必須)', [required_if_engineer, LessThan('billing_end_day')], format='%Y/%m', render_kw={"autocomplete": "off"}) billing_end_day = EndOfMonthField('請求契約終了年月(必須)', [required_if_engineer], format='%Y/%m', render_kw={"autocomplete": "off"}) billing_per_month = IntegerField( '請求単価(必須)', [required_if_engineer, NumberRange(min=-1000000000, max=1000000000)]) billing_rule = RadioField('請求ルール(必須)', [required_if_engineer], choices=Rule.get_rule_for_select()) billing_bottom_base_hour = IntegerField( '請求下限基準時間', [NumberRange(min=-1000000000, max=1000000000)]) billing_top_base_hour = IntegerField( '請求上限基準時間', [NumberRange(min=-1000000000, max=1000000000)]) billing_free_base_hour = StringField('請求フリー入力基準時間', [Length(max=128)], filters=[lambda x: x or None]) billing_per_hour = StringField('請求時間単価', [Length(max=128), required_if_variable], filters=[lambda x: x or None]) billing_per_bottom_hour = IntegerField( '請求-時間単価', [required_if_variable, NumberRange(min=-1000000000, max=1000000000)]) billing_per_top_hour = IntegerField( '請求+時間単価', [required_if_variable, NumberRange(min=-1000000000, max=1000000000)]) billing_fraction = SelectField('請求端数金額', [validators.Optional()], choices=Fraction.get_fraction_for_select(), filters=[lambda x: x or None], render_kw={"title": "請求端数金額"}) billing_fraction_rule = SelectField('請求端数ルール', [validators.Optional()], filters=[lambda x: x or None], choices=Round.get_round_for_select(), render_kw={"title": "請求端数ルール"}) payment_start_day = BeginningOfMonthField('支払契約開始年月', [validators.Optional()], format='%Y/%m', render_kw={ "autocomplete": "off", "disabled": "disabled" }) payment_end_day = EndOfMonthField('支払契約終了年月', [validators.Optional()], format='%Y/%m', render_kw={ "autocomplete": "off", "disabled": "disabled" }) payment_per_month = IntegerField('支払単価', render_kw={"disabled": "disabled"}) payment_rule = RadioField('支払いルール', [validators.Optional()], choices=Rule.get_rule_for_select(), render_kw={"disabled": "disabled"}) payment_bottom_base_hour = IntegerField('支払下限基準時間', render_kw={"disabled": "disabled"}) payment_top_base_hour = IntegerField('支払上限基準時間', render_kw={"disabled": "disabled"}) payment_free_base_hour = StringField('支払フリー入力基準時間', [Length(max=128)], render_kw={"disabled": "disabled"}) payment_per_hour = StringField('支払時間単価', [Length(max=128)], render_kw={"disabled": "disabled"}) payment_per_bottom_hour = IntegerField('支払-時間単価', render_kw={"disabled": "disabled"}) payment_per_top_hour = IntegerField('支払+時間単価', render_kw={"disabled": "disabled"}) payment_fraction = SelectField('支払端数金額', [validators.Optional()], choices=Fraction.get_fraction_for_select(), filters=[lambda x: x or None], render_kw={ "title": "支払端数金額", "disabled": "disabled" }) payment_fraction_rule = SelectField('支払端数ルール', [validators.Optional()], choices=Round.get_round_for_select(), filters=[lambda x: x or None], render_kw={ "title": "支払端数ルール", "disabled": "disabled" }) bp_order_no = StringField('BP注文書No(BPの場合、必須)', [Length(max=64)], filters=[lambda x: x or None]) client_order_no_for_bp = StringField('顧客注文書No(BPごと)', [Length(max=64)], filters=[lambda x: x or None]) updated_user = StringField('更新者') updated_at = DateTimeField('更新日') def validate_billing_bottom_base_hour(self, field): # 請求ルールが変動の時、フリー時間が空ならエラー if self.billing_rule.data == str(Rule.variable) and field.data is None \ and self.billing_free_base_hour.data is None: raise ValidationError('入力必須項目です。') def validate_billing_top_base_hour(self, field): # 請求ルールが変動の時、フリー時間が空ならエラー if self.billing_rule.data == str(Rule.variable) and field.data is None \ and self.billing_free_base_hour.data is None: raise ValidationError('入力必須項目です。') def validate_billing_free_base_hour(self, field): # 請求ルールが変動の時、下限時間または上限時間が空ならエラー if self.billing_rule.data == str(Rule.variable) and field.data is None \ and self.billing_bottom_base_hour.data is None \ and self.billing_top_base_hour.data is None: raise ValidationError('入力必須項目です。') def validate_bp_order_no(self, field): # 新規登録、作業の場合はチェック不要 if not self.id.data or DetailType.parse( self.detail_type.data) == DetailType.work: return engineer = service.find_by_id(self.engineer_id.data) # BPの場合、新規登録時以外はBP注文Noは必須 if engineer.is_bp() and field.data is None: raise ValidationError(field.label.text + 'は必須です。') project_detail = project_detail_repository.find_by_bp_order_no( field.data) if field.data and project_detail and project_detail.id != self.id.data: raise ValidationError('このBP注文Noは既に登録されています。') def validate_engineer_id(self, field): # 明細区分で技術者を選んだ場合 if DetailType.parse(self.detail_type.data) == DetailType.engineer and field.data \ and self.billing_start_day.data: engineer = service.find_by_id(self.engineer_id.data) engineer_history = engineer_history_service.get_history_by_start_day( engineer.id, self.billing_start_day.data) if not engineer_history: raise ValidationError('この技術者の契約期間はプロジェクト期間外です。')
def history(engineer_history_id=None): engineer_id = request.args.get('engineer_id') engineer_history = engineer_history_service.find_by_id(engineer_history_id) if engineer_history.id is None and engineer_history_id is not None: return abort(404) form = EngineerHistoryForm(request.form, obj=engineer_history) # 履歴データ新規作成時にはengineer情報を取得する。 if engineer_id: engineer_history.engineer = service.find_by_id(engineer_id) if not form.payment_site.raw_data: form.payment_site.data = str( engineer_history.engineer.company.payment_site) if not form.payment_tax.raw_data: form.payment_tax.data = str( engineer_history.engineer.company.payment_tax) # 対象技術者の最新の履歴データを取得する latest_engineer_history = engineer_history_service.get_latest_history( engineer_history.engineer.id) if form.validate_on_submit(): # 支払い契約開始年月のデータに変更があった場合、履歴を切る。 if engineer_history.id and engineer_history.payment_start_day != form.payment_start_day.data: # 終了日に新しく登録する履歴の開始日の前月を登録する。 engineer_history.payment_end_day = form.payment_start_day.data - timedelta( days=1) engineer_history_service.save(engineer_history) engineer_history = engineer_history.create_new_history() engineer_history.engineer_id = engineer_history.engineer.id engineer_history.payment_start_day = form.payment_start_day.data engineer_history.payment_end_day = form.payment_end_day.data engineer_history.payment_site = Site.parse(form.payment_site.data) engineer_history.payment_tax = Tax.parse(form.payment_tax.data) engineer_history.payment_per_month = form.payment_per_month.data engineer_history.payment_rule = Rule.parse(form.payment_rule.data) engineer_history.payment_bottom_base_hour = form.payment_bottom_base_hour.data engineer_history.payment_top_base_hour = form.payment_top_base_hour.data engineer_history.payment_free_base_hour = form.payment_free_base_hour.data engineer_history.payment_per_hour = form.payment_per_hour.data engineer_history.payment_per_bottom_hour = form.payment_per_bottom_hour.data engineer_history.payment_per_top_hour = form.payment_per_top_hour.data engineer_history.payment_fraction = Fraction.parse( form.payment_fraction.data) engineer_history.payment_fraction_rule = Round.parse( form.payment_fraction_rule.data) engineer_history.payment_condition = form.payment_condition.data engineer_history.remarks = form.remarks.data engineer_history_service.save(engineer_history) flash(Message.saved.value) return redirect( url_for('.history', engineer_history_id=engineer_history.id)) current_app.logger.debug(form.errors) if form.errors: flash(Message.saving_failed.value, 'error') return render_template('master/engineer/history.html', form=form, engineer_id=engineer_history.engineer.id, latest_engineer_history=latest_engineer_history)
class EngineerHistoryForm(FlaskForm): id = IntegerField('Id') payment_start_day = BeginningOfMonthField( '支払い契約開始年月(必須)', [ DataRequired(), LessThan('payment_end_day', '支払い契約終了年月より前の年月にして下さい。') ], format='%Y/%m', render_kw={"autocomplete": "off"}) payment_end_day = EndOfMonthField('支払い契約終了年月(必須)', [DataRequired()], format='%Y/%m', render_kw={"autocomplete": "off"}) payment_site = SelectField('支払サイト(必須)', [DataRequired()], choices=Site.get_site_for_select(), render_kw={"title": "支払サイト(必須)"}) payment_tax = SelectField('支払消費税(必須)', [DataRequired()], choices=Tax.get_type_for_select(), render_kw={"title": "支払消費税(必須)"}) payment_per_month = IntegerField( '支払単価(必須)', [InputRequired(), NumberRange(min=-1000000000, max=1000000000)]) payment_rule = RadioField('支払ルール(必須)', [DataRequired()], choices=Rule.get_rule_for_select(), filters=[lambda x: x or None]) payment_bottom_base_hour = IntegerField( '支払下限基準時間(必須)', [NumberRange(min=-1000000000, max=1000000000)]) payment_top_base_hour = IntegerField( '支払上限基準時間(必須)', [NumberRange(min=-1000000000, max=1000000000)]) payment_free_base_hour = StringField('支払フリー入力基準時間(必須)', [Length(max=128)], filters=[lambda x: x or None]) payment_per_hour = StringField('支払時間単価(必須)', [Length(max=128), required_if_variable], filters=[lambda x: x or None]) payment_per_bottom_hour = IntegerField( '支払-時間単価(必須)', [required_if_variable, NumberRange(min=-1000000000, max=1000000000)]) payment_per_top_hour = IntegerField( '支払+時間単価(必須)', [required_if_variable, NumberRange(min=-1000000000, max=1000000000)]) payment_fraction = SelectField('支払端数金額', [validators.Optional()], choices=Fraction.get_fraction_for_select(), filters=[lambda x: x or None], render_kw={"title": "支払端数金額"}) payment_fraction_rule = SelectField('支払端数ルール', [validators.Optional()], choices=Round.get_round_for_select(), filters=[lambda x: x or None], render_kw={"title": "支払端数ルール"}) payment_condition = TextAreaField('支払条件', [Length(max=1024)]) remarks = TextAreaField('その他特記事項', [Length(max=1024)]) updated_user = StringField('更新者') updated_at = DateTimeField('更新日') def validate_payment_start_day(self, field): engineer_history = service.find_by_id(self.id.data) if engineer_history and engineer_history.payment_start_day is not None\ and field.data < engineer_history.payment_start_day: raise ValidationError('前回の支払い契約終了年月「{}」よりの前の年月で更新できません。'.format( engineer_history.payment_start_day.strftime('%Y/%m'))) def validate_payment_bottom_base_hour(self, field): # 支払いのルールが変動の時、フリー時間が空ならエラー if self.payment_rule.data == str(Rule.variable) and field.data is None \ and self.payment_free_base_hour.data is None: raise ValidationError('支払いのルールが変動の場合、入力必須です。') def validate_payment_top_base_hour(self, field): # 支払いのルールが変動の時、フリー時間が空ならエラー if self.payment_rule.data == str(Rule.variable) and field.data is None \ and self.payment_free_base_hour.data is None: raise ValidationError('支払いのルールが変動の場合、入力必須です。') def validate_payment_free_base_hour(self, field): # 支払いのルールが変動の時、下限時間または上限時間が空ならエラー if self.payment_rule.data == str(Rule.variable) and field.data is None \ and self.payment_bottom_base_hour.data is None \ and self.payment_top_base_hour.data is None: raise ValidationError('支払いのルールが変動の場合、入力必須です。')