summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2git <cvs2git>2009-10-11 02:42:17 +0000
committercvs2git <cvs2git>2009-10-11 02:42:17 +0000
commita83a000a027d1272e813259d09230d701d84df64 (patch)
tree71500c957e6d7db3e1ad3d59e74ca7bbb14e44ff
parent097a12385d80ef52f37d4cc2bb93bc3f81e6f8e6 (diff)
parent0b69c091543b56a45f2ae6b8718fc67f381a6686 (diff)
This commit was manufactured by cvs2svn to create branchfreeside_1_9_1
'FREESIDE_1_9_BRANCH'.
-rw-r--r--ChangeLog38946
-rw-r--r--FS/FS.pm16
-rw-r--r--FS/FS/AccessRight.pm53
-rw-r--r--FS/FS/CGI.pm2
-rw-r--r--FS/FS/ClientAPI/Bulk.pm384
-rw-r--r--FS/FS/ClientAPI/MasonComponent.pm75
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm375
-rw-r--r--FS/FS/ClientAPI/SGNG.pm277
-rw-r--r--FS/FS/ClientAPI/Signup.pm193
-rw-r--r--FS/FS/Conf.pm742
-rw-r--r--FS/FS/Conf_compat17.pm184
-rw-r--r--FS/FS/Cron/alert_expiration.pm177
-rw-r--r--FS/FS/Cron/bill.pm234
-rw-r--r--FS/FS/Cron/check.pm200
-rw-r--r--FS/FS/Cron/notify.pm4
-rw-r--r--FS/FS/Cron/upload.pm176
-rw-r--r--FS/FS/Mason.pm75
-rw-r--r--FS/FS/Misc/eps2png.pm278
-rw-r--r--FS/FS/Record.pm344
-rw-r--r--FS/FS/Report/Table/Monthly.pm77
-rw-r--r--FS/FS/Schema.pm312
-rw-r--r--FS/FS/Setup.pm2
-rw-r--r--FS/FS/TicketSystem/RT_External.pm23
-rw-r--r--FS/FS/TicketSystem/RT_Internal.pm111
-rw-r--r--FS/FS/Tron.pm46
-rw-r--r--FS/FS/UI/Web.pm7
-rw-r--r--FS/FS/UI/bytecount.pm11
-rw-r--r--FS/FS/UID.pm31
-rw-r--r--FS/FS/Upgrade.pm12
-rw-r--r--FS/FS/access_right.pm2
-rw-r--r--FS/FS/access_user.pm28
-rw-r--r--FS/FS/access_usergroup.pm2
-rw-r--r--FS/FS/agent.pm115
-rw-r--r--FS/FS/cdr.pm194
-rw-r--r--FS/FS/cdr/broadsoft.pm108
-rw-r--r--FS/FS/cdr/netcentrex.pm48
-rw-r--r--FS/FS/cdr/sansay.pm408
-rw-r--r--FS/FS/cdr/taqua.pm31
-rw-r--r--FS/FS/cdr/transnexus.pm66
-rw-r--r--FS/FS/cdr/vitelity.pm25
-rw-r--r--FS/FS/cdr_termination.pm152
-rw-r--r--FS/FS/clientapi_session_field.pm2
-rw-r--r--FS/FS/cust_attachment.pm170
-rw-r--r--FS/FS/cust_bill.pm1035
-rw-r--r--FS/FS/cust_bill_ApplicationCommon.pm17
-rw-r--r--FS/FS/cust_bill_pay.pm21
-rw-r--r--FS/FS/cust_bill_pay_pkg.pm78
-rw-r--r--FS/FS/cust_bill_pkg.pm188
-rw-r--r--FS/FS/cust_bill_pkg_detail.pm95
-rw-r--r--FS/FS/cust_bill_pkg_display.pm7
-rw-r--r--FS/FS/cust_bill_pkg_tax_rate_location.pm136
-rw-r--r--FS/FS/cust_credit.pm6
-rw-r--r--FS/FS/cust_credit_bill.pm2
-rw-r--r--FS/FS/cust_event.pm134
-rw-r--r--FS/FS/cust_main.pm2880
-rw-r--r--FS/FS/cust_main_Mixin.pm24
-rw-r--r--FS/FS/cust_main_exemption.pm128
-rw-r--r--FS/FS/cust_pay.pm323
-rw-r--r--FS/FS/cust_pay_pending.pm19
-rw-r--r--FS/FS/cust_pay_void.pm38
-rw-r--r--FS/FS/cust_pkg.pm339
-rw-r--r--FS/FS/cust_pkg_reason.pm39
-rw-r--r--FS/FS/cust_recon.pm193
-rw-r--r--FS/FS/cust_statement.pm272
-rw-r--r--FS/FS/cust_svc.pm63
-rw-r--r--FS/FS/cust_svc_option.pm2
-rw-r--r--FS/FS/cust_tax_adjustment.pm (renamed from FS/FS/cdr_upstream_rate.pm)77
-rw-r--r--FS/FS/cust_tax_location.pm24
-rw-r--r--FS/FS/h_cust_svc.pm12
-rw-r--r--FS/FS/part_device.pm134
-rw-r--r--FS/FS/part_event.pm6
-rw-r--r--FS/FS/part_event/Action.pm13
-rw-r--r--FS/FS/part_event/Action/cust_bill_email.pm23
-rw-r--r--FS/FS/part_event/Action/cust_bill_fee_percent.pm31
-rw-r--r--FS/FS/part_event/Action/cust_bill_send.pm3
-rw-r--r--FS/FS/part_event/Action/cust_bill_send_reminder.pm31
-rw-r--r--FS/FS/part_event/Action/cust_bill_spool_csv.pm1
-rw-r--r--FS/FS/part_event/Action/cust_statement.pm39
-rw-r--r--FS/FS/part_event/Action/cust_statement_send.pm26
-rw-r--r--FS/FS/part_event/Action/fee.pm26
-rw-r--r--FS/FS/part_event/Action/pkg_referral_credit_pkg.pm1
-rw-r--r--FS/FS/part_event/Action/writeoff.pm33
-rw-r--r--FS/FS/part_event/Condition.pm2
-rw-r--r--FS/FS/part_event/Condition/cust_payments.pm2
-rw-r--r--FS/FS/part_event/Condition/cust_payments_pkg.pm68
-rw-r--r--FS/FS/part_event/Condition/has_pkg_class.pm40
-rw-r--r--FS/FS/part_event/Condition/has_pkgpart.pm41
-rw-r--r--FS/FS/part_event/Condition/has_referral_custnum.pm26
-rw-r--r--FS/FS/part_event/Condition/hasnt_pkgpart.pm40
-rw-r--r--FS/FS/part_event/Condition/once.pm2
-rw-r--r--FS/FS/part_export/acct_plesk.pm2
-rw-r--r--FS/FS/part_export/amazon_ec2.pm169
-rw-r--r--FS/FS/part_export/domreg_net_dri.pm614
-rw-r--r--FS/FS/part_export/domreg_opensrs.pm512
-rw-r--r--FS/FS/part_export/globalpops_voip.pm2
-rw-r--r--FS/FS/part_export/netsapiens.pm308
-rw-r--r--FS/FS/part_export/prizm.pm12
-rw-r--r--FS/FS/part_export/shellcommands.pm71
-rw-r--r--FS/FS/part_export/shellcommands_withdomain.pm26
-rw-r--r--FS/FS/part_export/www_plesk.pm2
-rw-r--r--FS/FS/part_pkg.pm243
-rw-r--r--FS/FS/part_pkg/agent.pm175
-rw-r--r--FS/FS/part_pkg/base_rate.pm4
-rw-r--r--FS/FS/part_pkg/bulk.pm34
-rw-r--r--FS/FS/part_pkg/cdr_termination.pm207
-rw-r--r--FS/FS/part_pkg/flat.pm104
-rw-r--r--FS/FS/part_pkg/flat_delayed.pm2
-rw-r--r--FS/FS/part_pkg/flat_introrate.pm58
-rw-r--r--FS/FS/part_pkg/prepaid.pm16
-rw-r--r--FS/FS/part_pkg/prorate_delayed.pm2
-rw-r--r--FS/FS/part_pkg/recur_Common.pm59
-rw-r--r--FS/FS/part_pkg/voip_cdr.pm287
-rw-r--r--FS/FS/part_pkg_link.pm8
-rw-r--r--FS/FS/part_pkg_option.pm7
-rw-r--r--FS/FS/part_pkg_report_option.pm125
-rw-r--r--FS/FS/part_pkg_taxclass.pm75
-rw-r--r--FS/FS/part_pkg_taxproduct.pm9
-rw-r--r--FS/FS/part_pkg_taxrate.pm33
-rw-r--r--FS/FS/part_svc.pm75
-rw-r--r--FS/FS/part_svc_column.pm5
-rw-r--r--FS/FS/pay_batch.pm432
-rw-r--r--FS/FS/pay_batch/BoM.pm73
-rw-r--r--FS/FS/pay_batch/PAP.pm103
-rw-r--r--FS/FS/pay_batch/ach_spiritone.pm65
-rw-r--r--FS/FS/pay_batch/chase_canada.pm104
-rw-r--r--FS/FS/pay_batch/paymentech.pm114
-rw-r--r--FS/FS/pay_batch/td_canada_trust.pm104
-rw-r--r--FS/FS/payby.pm15
-rw-r--r--FS/FS/payment_gateway.pm49
-rw-r--r--FS/FS/phone_device.pm240
-rw-r--r--FS/FS/pkg_category.pm35
-rw-r--r--FS/FS/queue.pm17
-rw-r--r--FS/FS/queue_arg.pm3
-rw-r--r--FS/FS/rate_detail.pm345
-rw-r--r--FS/FS/svc_Common.pm26
-rw-r--r--FS/FS/svc_acct.pm209
-rwxr-xr-xFS/FS/svc_broadband.pm30
-rw-r--r--FS/FS/svc_domain.pm7
-rw-r--r--FS/FS/svc_external.pm1
-rw-r--r--FS/FS/svc_phone.pm49
-rw-r--r--FS/FS/tax_class.pm6
-rw-r--r--FS/FS/tax_rate.pm720
-rw-r--r--FS/FS/tax_rate_location.pm317
-rw-r--r--FS/MANIFEST25
-rwxr-xr-xFS/bin/freeside-addgroup2
-rwxr-xr-xFS/bin/freeside-apply_payments_and_credits79
-rwxr-xr-xFS/bin/freeside-cdr-sftp_and_import187
-rw-r--r--FS/bin/freeside-check31
-rwxr-xr-xFS/bin/freeside-daily40
-rwxr-xr-xFS/bin/freeside-expiration-alerter241
-rwxr-xr-xFS/bin/freeside-monthly3
-rw-r--r--FS/bin/freeside-queued209
-rw-r--r--FS/bin/freeside-selfservice-server23
-rwxr-xr-xFS/bin/freeside-sqlradius-reset23
-rwxr-xr-xFS/bin/freeside-upgrade33
-rwxr-xr-xFS/bin/freeside-void-payments222
-rw-r--r--FS/t/cdr_termination.t (renamed from FS/t/cdr_upstream_rate.t)2
-rw-r--r--FS/t/cust_attachment.t5
-rw-r--r--FS/t/cust_bill_pkg_tax_rate_location.t5
-rw-r--r--FS/t/cust_main_exemption.t5
-rw-r--r--FS/t/cust_recon.t5
-rw-r--r--FS/t/cust_statement.t5
-rw-r--r--FS/t/cust_tax_adjustment.t5
-rw-r--r--FS/t/part_device.t5
-rw-r--r--FS/t/part_pkg_report_option.t5
-rw-r--r--FS/t/phone_device.t5
-rw-r--r--FS/t/tax_rate_location.t5
-rw-r--r--Makefile17
-rw-r--r--bin/billco-upload20
-rwxr-xr-xbin/cdr-netsapiens.import207
-rwxr-xr-xbin/cdr-transnexus.import143
-rwxr-xr-xbin/cdr.sftp_and_import112
-rwxr-xr-xbin/confdiff27
-rwxr-xr-xbin/countdeclines22
-rw-r--r--bin/cust_main_special.pm608
-rwxr-xr-xbin/cust_pay_histogram115
-rwxr-xr-xbin/cvs2cl2
-rw-r--r--bin/drop_slony.slonik9
-rw-r--r--bin/freeside-migrate-events97
-rwxr-xr-xbin/fs-migrate-cust_tax_exempt2
-rwxr-xr-xbin/generate-table-module11
-rwxr-xr-xbin/h_cust_main-wipe_paycvv30
-rwxr-xr-xbin/make-pkg-fruit172
-rwxr-xr-xbin/mapsecrets2access_user2
-rwxr-xr-xbin/move-customers678
-rwxr-xr-xbin/ping58
-rwxr-xr-xbin/print-directory_assist12
-rwxr-xr-xbin/rebill132
-rw-r--r--bin/svc_acct-recalculate_usage110
-rwxr-xr-xbin/tax_rate_location.import48
-rw-r--r--conf/invoice_html177
-rw-r--r--conf/invoice_htmlsummary74
-rw-r--r--conf/invoice_latex162
-rw-r--r--conf/invoice_latexsummary45
-rw-r--r--conf/invoice_template2
-rw-r--r--debian/changelog12
-rw-r--r--eg/cdr_template.pm6
-rw-r--r--etc/areacodes.txt353
-rw-r--r--etc/fslongtable.sty1
-rw-r--r--fs_selfservice/FS-SelfService/MANIFEST1
-rw-r--r--fs_selfservice/FS-SelfService/Makefile.PL1
-rw-r--r--fs_selfservice/FS-SelfService/SelfService.pm128
-rw-r--r--fs_selfservice/FS-SelfService/cgi/ach_payment_results.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/bill.html2
-rw-r--r--fs_selfservice/FS-SelfService/cgi/card.html50
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/change_bill.html9
-rw-r--r--fs_selfservice/FS-SelfService/cgi/change_password.html7
-rw-r--r--fs_selfservice/FS-SelfService/cgi/change_pay.html24
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/change_ship.html9
-rw-r--r--fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi14
-rw-r--r--fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html8
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/customer_order_pkg.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/delete_svc.html7
-rw-r--r--fs_selfservice/FS-SelfService/cgi/footer.html4
-rw-r--r--fs_selfservice/FS-SelfService/cgi/header.html23
-rw-r--r--fs_selfservice/FS-SelfService/cgi/iframecontentmws.js59
-rw-r--r--fs_selfservice/FS-SelfService/cgi/login.html19
-rw-r--r--fs_selfservice/FS-SelfService/cgi/logout.html14
-rw-r--r--fs_selfservice/FS-SelfService/cgi/make_ach_payment.html21
-rw-r--r--fs_selfservice/FS-SelfService/cgi/make_payment.html37
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html37
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/misc/counties.cgi18
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/misc/part_svc-columns.cgi18
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/misc/states.cgi18
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/misc/svc_acct-domains.cgi18
-rw-r--r--fs_selfservice/FS-SelfService/cgi/myaccount.html18
-rw-r--r--fs_selfservice/FS-SelfService/cgi/myaccount_menu.html101
-rw-r--r--fs_selfservice/FS-SelfService/cgi/order_pkg.html46
-rw-r--r--fs_selfservice/FS-SelfService/cgi/overlibmws.js620
-rw-r--r--fs_selfservice/FS-SelfService/cgi/overlibmws_crossframe.js53
-rw-r--r--fs_selfservice/FS-SelfService/cgi/overlibmws_draggable.js85
-rw-r--r--fs_selfservice/FS-SelfService/cgi/overlibmws_iframe.js93
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/passwd.cgi1
-rw-r--r--fs_selfservice/FS-SelfService/cgi/payment_results.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_change_bill.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_change_password.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_change_pay.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_change_pkg.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_change_ship.html6
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/process_order_pkg.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_order_recharge.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_svc_acct.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/process_svc_external.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/provision.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/recharge_prepay.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/recharge_results.html8
-rw-r--r--fs_selfservice/FS-SelfService/cgi/selfservice.cgi143
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/signup.cgi98
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/signup.html19
-rw-r--r--fs_selfservice/FS-SelfService/cgi/success.html2
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/verify.cgi177
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_cdr_details.html54
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_invoice.html6
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_usage.html68
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_usage_details.html6
-rw-r--r--fs_selfservice/FS-SelfService/freeside-selfservice-clientd149
-rw-r--r--fs_selfservice/FS-SelfService/freeside-selfservice-soap-server53
-rw-r--r--fs_selfservice/FS-SelfService/iZoomOnlineProvisionService.pm75
-rw-r--r--htetc/freeside-base1.99.conf3
-rw-r--r--htetc/freeside-base1.conf3
-rw-r--r--htetc/freeside-base2.conf3
-rw-r--r--htetc/handler.pl12
-rwxr-xr-xhttemplate/browse/agent.cgi22
-rwxr-xr-xhttemplate/browse/agent_type.cgi4
-rwxr-xr-xhttemplate/browse/cust_main_county.cgi47
-rw-r--r--httemplate/browse/part_device.html27
-rwxr-xr-xhttemplate/browse/part_pkg.cgi98
-rw-r--r--httemplate/browse/part_pkg_report_option.html28
-rw-r--r--httemplate/browse/part_pkg_taxclass.html27
-rwxr-xr-xhttemplate/browse/part_svc.cgi27
-rw-r--r--httemplate/browse/payment_gateway.html4
-rw-r--r--httemplate/browse/pkg_category.html6
-rw-r--r--httemplate/browse/rate_region.html59
-rwxr-xr-xhttemplate/browse/svc_acct_pop.cgi1
-rw-r--r--httemplate/config/config-delete.cgi15
-rw-r--r--httemplate/config/config-image.cgi5
-rw-r--r--httemplate/config/config-process.cgi34
-rw-r--r--httemplate/config/config-view.cgi247
-rw-r--r--httemplate/config/config.cgi30
-rw-r--r--httemplate/docs/about.html8
-rw-r--r--httemplate/docs/credits.html17
-rw-r--r--httemplate/docs/license.html10
-rwxr-xr-xhttemplate/edit/REAL_cust_pkg.cgi6
-rwxr-xr-xhttemplate/edit/agent.cgi10
-rwxr-xr-xhttemplate/edit/agent_type.cgi2
-rwxr-xr-xhttemplate/edit/cust_credit.cgi10
-rwxr-xr-xhttemplate/edit/cust_main.cgi701
-rw-r--r--httemplate/edit/cust_main/billing.html194
-rw-r--r--httemplate/edit/cust_main/birthdate.html15
-rw-r--r--httemplate/edit/cust_main/bottomfixup.html19
-rw-r--r--httemplate/edit/cust_main/bottomfixup.js398
-rw-r--r--httemplate/edit/cust_main/choose_tax_location.html10
-rw-r--r--httemplate/edit/cust_main/contact.html7
-rw-r--r--httemplate/edit/cust_main/first_pkg.html55
-rw-r--r--httemplate/edit/cust_main/first_pkg/select-part_pkg.html170
-rw-r--r--httemplate/edit/cust_main/first_pkg/svc_acct.html88
-rw-r--r--httemplate/edit/cust_main/first_pkg/svc_phone.html82
-rw-r--r--httemplate/edit/cust_main/select-domain.html67
-rw-r--r--httemplate/edit/cust_main/top_misc.html97
-rwxr-xr-xhttemplate/edit/cust_main_attach.cgi59
-rwxr-xr-xhttemplate/edit/cust_pay.cgi14
-rwxr-xr-xhttemplate/edit/cust_pkg.cgi4
-rw-r--r--httemplate/edit/cust_tax_adjustment.html102
-rw-r--r--httemplate/edit/elements/edit.html160
-rw-r--r--httemplate/edit/elements/svc_Common.html28
-rwxr-xr-xhttemplate/edit/part_bill_event.cgi6
-rw-r--r--httemplate/edit/part_device.html16
-rw-r--r--httemplate/edit/part_export.cgi23
-rwxr-xr-xhttemplate/edit/part_pkg.cgi95
-rw-r--r--httemplate/edit/part_pkg_report_option.html23
-rw-r--r--httemplate/edit/part_pkg_taxclass.html43
-rwxr-xr-xhttemplate/edit/part_svc.cgi34
-rw-r--r--httemplate/edit/payment_gateway.html244
-rw-r--r--httemplate/edit/phone_device.html37
-rw-r--r--httemplate/edit/pkg_category.html2
-rw-r--r--httemplate/edit/prepay_credit.cgi12
-rwxr-xr-xhttemplate/edit/process/REAL_cust_pkg.cgi11
-rwxr-xr-xhttemplate/edit/process/cust_main.cgi152
-rw-r--r--httemplate/edit/process/cust_main_attach.cgi99
-rwxr-xr-xhttemplate/edit/process/cust_main_county-collapse.cgi67
-rwxr-xr-xhttemplate/edit/process/cust_pay.cgi6
-rw-r--r--httemplate/edit/process/cust_tax_adjustment.html41
-rwxr-xr-xhttemplate/edit/process/domreg.cgi62
-rw-r--r--httemplate/edit/process/elements/ApplicationCommon.html2
-rw-r--r--httemplate/edit/process/part_device.html11
-rw-r--r--httemplate/edit/process/part_export.cgi3
-rwxr-xr-xhttemplate/edit/process/part_pkg.cgi44
-rw-r--r--httemplate/edit/process/part_pkg_report_option.html11
-rw-r--r--httemplate/edit/process/part_pkg_taxclass.html58
-rw-r--r--httemplate/edit/process/payment_gateway.html39
-rw-r--r--httemplate/edit/process/phone_device.html18
-rw-r--r--httemplate/edit/process/quick-charge.cgi8
-rw-r--r--httemplate/edit/process/quick-cust_pkg.cgi13
-rwxr-xr-xhttemplate/edit/process/svc_domain.cgi4
-rw-r--r--httemplate/edit/quick-charge.html91
-rw-r--r--httemplate/edit/reg_code.cgi2
-rwxr-xr-xhttemplate/edit/router.cgi10
-rwxr-xr-xhttemplate/edit/svc_acct.cgi2
-rw-r--r--httemplate/edit/svc_broadband.cgi5
-rwxr-xr-xhttemplate/edit/svc_domain.cgi42
-rw-r--r--httemplate/edit/svc_www.cgi2
-rw-r--r--httemplate/elements/about_freeside.html19
-rw-r--r--httemplate/elements/about_rt.html13
-rw-r--r--httemplate/elements/checkbox.html19
-rw-r--r--httemplate/elements/checkboxes.html10
-rw-r--r--httemplate/elements/file-upload.html2
-rw-r--r--httemplate/elements/header-popup.html33
-rw-r--r--httemplate/elements/header.html175
-rw-r--r--httemplate/elements/location.html50
-rw-r--r--httemplate/elements/menu.html237
-rw-r--r--httemplate/elements/menuarrow.gifbin0 -> 68 bytes
-rw-r--r--httemplate/elements/menubar.html118
-rw-r--r--httemplate/elements/popup_link-cust_main.html2
-rw-r--r--httemplate/elements/popup_link-ping.html30
-rw-r--r--httemplate/elements/popup_link.html8
-rw-r--r--httemplate/elements/progress-popup.html2
-rw-r--r--httemplate/elements/select-county.html6
-rw-r--r--httemplate/elements/select-cust-part_pkg.html12
-rw-r--r--httemplate/elements/select-cust-pkg_class.html12
-rw-r--r--httemplate/elements/select-cust_main-status.html7
-rw-r--r--httemplate/elements/select-cust_pkg-balances.html32
-rw-r--r--httemplate/elements/select-cust_pkg-status.html7
-rw-r--r--httemplate/elements/select-did.html5
-rw-r--r--httemplate/elements/select-domain.html2
-rw-r--r--httemplate/elements/select-part_pkg.html14
-rw-r--r--httemplate/elements/select-part_svc.html18
-rw-r--r--httemplate/elements/select-svc_acct-domain.html46
-rw-r--r--httemplate/elements/select-table.html22
-rw-r--r--httemplate/elements/select-taxclass.html8
-rw-r--r--httemplate/elements/select-terms.html26
-rw-r--r--httemplate/elements/selectlayers.html42
-rw-r--r--httemplate/elements/tr-checkbox.html8
-rw-r--r--httemplate/elements/tr-input-date-field.html27
-rw-r--r--httemplate/elements/tr-justtitle.html2
-rw-r--r--httemplate/elements/tr-select-cust-part_pkg.html107
-rw-r--r--httemplate/elements/tr-select-cust_pkg-balances.html31
-rw-r--r--httemplate/elements/tr-select-did.html20
-rw-r--r--httemplate/elements/tr-select-part_svc.html7
-rw-r--r--httemplate/elements/tr-select-pkg_class.html6
-rw-r--r--httemplate/elements/tr-select-svc_acct-domain.html34
-rw-r--r--httemplate/elements/tr-select-taxclass.html10
-rw-r--r--httemplate/elements/tr-selectmultiple-part_pkg.html9
-rw-r--r--httemplate/elements/tr-textarea.html30
-rw-r--r--httemplate/elements/tr-title.html7
-rw-r--r--httemplate/elements/xmenu.css2
-rw-r--r--httemplate/elements/xmenu.top.css2
-rw-r--r--httemplate/graph/cust_bill_pkg.cgi96
-rw-r--r--httemplate/graph/cust_bill_pkg_detail.cgi137
-rw-r--r--httemplate/graph/report_cust_bill_pkg.html11
-rw-r--r--httemplate/graph/report_cust_bill_pkg_detail.html48
-rw-r--r--httemplate/images/gray-black-side.pngbin0 -> 213 bytes
-rwxr-xr-xhttemplate/misc/bulk_change_pkg.cgi25
-rwxr-xr-xhttemplate/misc/cancel_pkg.html2
-rwxr-xr-xhttemplate/misc/change_pkg.cgi22
-rw-r--r--httemplate/misc/cust-part_pkg.cgi29
-rw-r--r--httemplate/misc/cust_main-import.cgi2
-rwxr-xr-xhttemplate/misc/delay_susp_pkg.html2
-rw-r--r--httemplate/misc/delete-cust_bill.html21
-rwxr-xr-xhttemplate/misc/delete-phone_device.html23
-rw-r--r--httemplate/misc/download-batch.cgi200
-rw-r--r--httemplate/misc/email-customers.html2
-rwxr-xr-xhttemplate/misc/link.cgi1
-rw-r--r--httemplate/misc/meta-import.cgi2
-rw-r--r--httemplate/misc/order_pkg.html49
-rw-r--r--httemplate/misc/part_device-import.html53
-rw-r--r--httemplate/misc/part_svc-columns.cgi13
-rw-r--r--httemplate/misc/payment.cgi152
-rw-r--r--httemplate/misc/ping.html102
-rwxr-xr-xhttemplate/misc/process/link.cgi10
-rw-r--r--httemplate/misc/process/part_device-import.html9
-rw-r--r--httemplate/misc/process/payment.cgi23
-rw-r--r--httemplate/misc/process/rate_edit_excel.html10
-rwxr-xr-xhttemplate/misc/process/recharge_svc.html103
-rw-r--r--httemplate/misc/process/tax-fetch_and_import.cgi9
-rw-r--r--httemplate/misc/process/tax-fetch_and_replace.cgi9
-rw-r--r--httemplate/misc/process/tax-import.cgi2
-rw-r--r--httemplate/misc/rate_edit_excel.html61
-rw-r--r--httemplate/misc/send-invoice.cgi30
-rwxr-xr-xhttemplate/misc/send-statement.cgi28
-rw-r--r--httemplate/misc/states.cgi12
-rw-r--r--httemplate/misc/tax-fetch_and_import.cgi48
-rw-r--r--httemplate/misc/tax-fetch_and_replace.cgi48
-rw-r--r--httemplate/misc/tax-import.cgi8
-rw-r--r--httemplate/misc/xmlhttp-cust_main-address_standardize.html5
-rw-r--r--httemplate/misc/xmlhttp-cust_main-censustract.html105
-rw-r--r--httemplate/misc/xmlhttp-ping.html20
-rw-r--r--httemplate/pref/pref-process.html113
-rw-r--r--httemplate/pref/pref.html32
-rwxr-xr-xhttemplate/search/477.html155
-rw-r--r--httemplate/search/cdr.html156
-rw-r--r--httemplate/search/cust_bill_pkg.cgi242
-rw-r--r--httemplate/search/cust_event.html99
-rwxr-xr-xhttemplate/search/cust_main.cgi15
-rwxr-xr-xhttemplate/search/cust_main.html9
-rwxr-xr-xhttemplate/search/cust_pay_batch.cgi5
-rwxr-xr-xhttemplate/search/cust_pay_void.html13
-rwxr-xr-xhttemplate/search/cust_pkg.cgi61
-rw-r--r--httemplate/search/cust_tax_adjustment.html54
-rw-r--r--httemplate/search/elements/cust_main_dayranges.html219
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html12
-rw-r--r--httemplate/search/elements/search-csv.html48
-rw-r--r--httemplate/search/elements/search-html.html454
-rw-r--r--httemplate/search/elements/search-xls.html83
-rw-r--r--httemplate/search/elements/search.html606
-rw-r--r--httemplate/search/reg_code.html2
-rwxr-xr-xhttemplate/search/report_477.html64
-rw-r--r--httemplate/search/report_cdr.html90
-rwxr-xr-xhttemplate/search/report_cust_main.html11
-rw-r--r--httemplate/search/report_cust_pay.html43
-rwxr-xr-xhttemplate/search/report_cust_pkg.html43
-rwxr-xr-xhttemplate/search/report_newtax.cgi105
-rw-r--r--httemplate/search/report_prepaid_income.cgi38
-rw-r--r--httemplate/search/report_prepaid_income.html70
-rwxr-xr-xhttemplate/search/report_receivables.cgi168
-rwxr-xr-xhttemplate/search/report_receivables.html8
-rw-r--r--httemplate/search/report_svc_phone.html32
-rwxr-xr-xhttemplate/search/report_tax.cgi162
-rwxr-xr-xhttemplate/search/report_tax.html36
-rwxr-xr-xhttemplate/search/report_unapplied_cust_pay.html41
-rwxr-xr-xhttemplate/search/svc_broadband.cgi4
-rwxr-xr-xhttemplate/search/svc_external.cgi286
-rw-r--r--httemplate/search/svc_phone.cgi71
-rwxr-xr-xhttemplate/search/unapplied_cust_pay.html28
-rw-r--r--httemplate/view/attachment.html16
-rwxr-xr-xhttemplate/view/cust_bill-logo.cgi2
-rwxr-xr-xhttemplate/view/cust_bill-pdf.cgi22
-rwxr-xr-xhttemplate/view/cust_bill-ps.cgi21
-rwxr-xr-xhttemplate/view/cust_bill.cgi73
-rwxr-xr-xhttemplate/view/cust_main.cgi134
-rwxr-xr-xhttemplate/view/cust_main/attachments.html151
-rw-r--r--httemplate/view/cust_main/billing.html37
-rw-r--r--httemplate/view/cust_main/change_history.html302
-rw-r--r--httemplate/view/cust_main/misc.html19
-rw-r--r--httemplate/view/cust_main/one_time_charge_link.html91
-rwxr-xr-xhttemplate/view/cust_main/packages.html214
-rw-r--r--httemplate/view/cust_main/packages/package.html23
-rw-r--r--httemplate/view/cust_main/packages/services.html28
-rw-r--r--httemplate/view/cust_main/packages/status.html86
-rw-r--r--httemplate/view/cust_main/payment_history.html51
-rw-r--r--httemplate/view/cust_main/payment_history/credit.html14
-rw-r--r--httemplate/view/cust_main/payment_history/invoice.html19
-rw-r--r--httemplate/view/cust_main/payment_history/payment.html14
-rw-r--r--httemplate/view/cust_main/payment_history/statement.html34
-rw-r--r--httemplate/view/cust_main/payment_history/voided_payment.html27
-rw-r--r--httemplate/view/cust_main/tickets.html3
-rw-r--r--httemplate/view/cust_pay.html41
-rw-r--r--httemplate/view/cust_pay_void.html1
-rwxr-xr-xhttemplate/view/cust_statement-pdf.cgi28
-rwxr-xr-xhttemplate/view/cust_statement.html79
-rw-r--r--httemplate/view/elements/svc_Common.html63
-rw-r--r--httemplate/view/svc_Common.html12
-rwxr-xr-xhttemplate/view/svc_acct.cgi2
-rw-r--r--httemplate/view/svc_broadband.cgi59
-rwxr-xr-xhttemplate/view/svc_domain.cgi57
-rw-r--r--httemplate/view/svc_phone.cgi75
-rw-r--r--init.d/freeside-init9
-rw-r--r--rpm/freeside.spec65
-rw-r--r--rt/FREESIDE_MODIFIED9
-rw-r--r--rt/Makefile4
-rw-r--r--rt/etc/RT_SiteConfig.pm2
-rw-r--r--rt/html/Elements/Footer36
-rw-r--r--rt/html/Elements/FreesideSvcSearch2
-rw-r--r--rt/html/Elements/Header146
-rw-r--r--rt/html/Elements/PageLayout171
-rw-r--r--rt/html/Elements/SelectDate15
-rw-r--r--rt/html/Elements/Tabs17
-rw-r--r--rt/html/NoAuth/css/3.5-default/freeside.css75
-rwxr-xr-xrt/html/NoAuth/css/3.5-default/misc.css5
-rw-r--r--rt/html/NoAuth/css/3.5-default/titlebox.css3
-rw-r--r--rt/html/Prefs/SearchOptions.html2
-rw-r--r--rt/html/Ticket/Create.html4
-rw-r--r--rt/html/Ticket/Display.html4
-rw-r--r--rt/html/User/Prefs.html2
-rw-r--r--rt/lib/RT.pm10
-rw-r--r--rt/lib/RT/Transaction_Overlay.pm5
516 files changed, 71229 insertions, 6944 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e844a11
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,38946 @@
+2009-10-10 18:57 ivan
+
+ * ChangeLog, rpm/freeside.spec, debian/changelog: Updated for 1.9.1
+
+2009-10-10 18:50 ivan
+
+ * Makefile, bin/cvs2cl: helps to have the tool
+
+2009-10-10 18:48 ivan
+
+ * Makefile: do it
+
+2009-10-10 18:48 ivan
+
+ * rt/lib/RT.pm: huh #2
+
+2009-10-10 18:46 ivan
+
+ * rt/Makefile: huh
+
+2009-10-10 18:45 ivan
+
+ * httemplate/search/elements/search-html.html: don't try to follow
+ a blank redirect
+
+2009-10-10 18:45 ivan
+
+ * httemplate/search/report_cdr.html: end form
+
+2009-10-10 18:45 ivan
+
+ * httemplate/elements/tr-textarea.html: new rows and cols options
+
+2009-10-10 18:44 ivan
+
+ * httemplate/elements/tr-select-pkg_class.html: respect
+ element_name
+
+2009-10-10 18:43 ivan
+
+ * httemplate/browse/agent.cgi: cleanup
+
+2009-10-10 18:42 ivan
+
+ * eg/cdr_template.pm, httemplate/elements/selectlayers.html: doc
+
+2009-10-10 18:41 ivan
+
+ * FS/FS/part_export/globalpops_voip.pm: correct variable
+ initialization
+
+2009-10-10 18:40 ivan
+
+ * FS/FS/: access_right.pm, access_usergroup.pm,
+ clientapi_session_field.pm, cust_svc_option.pm: remembered to
+ customize this manpage
+
+2009-10-10 18:39 ivan
+
+ * FS/FS/Record.pm: ::1 becomes 127.0.0.1 in IP checks
+
+2009-10-09 20:22 ivan
+
+ * ChangeLog: commit message for a file about commitmessages
+
+2009-10-09 16:59 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/elements/select-terms.html, FS/FS/cust_bill.pm,
+ httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi: change invoice terms
+ for one-time charges (& bill them immediately), RT#5891
+
+2009-10-09 14:37 ivan
+
+ * FS/FS/cust_main.pm: add cust_pkg_ref option to charge
+
+2009-10-08 01:28 ivan
+
+ * httemplate/view/cust_main/packages.html: fix "show old packages"
+ accidentally hiding cancelled packages, RT#5276
+
+2009-10-07 23:00 ivan
+
+ * FS/FS/: cust_main.pm, Cron/bill.pm: freeside-daily -g and -m
+ cooperation (and no HASH() queue noise with -m)
+
+2009-10-07 22:44 ivan
+
+ * FS/FS/: cust_bill.pm, cust_main.pm: avoid some (look to be
+ harmless) warnings:
+
+ Argument "" isn't numeric in sprintf at
+ /usr/local/share/perl/5.10.0/FS/cust_bill.pm line 2358.
+
+ Argument "" isn't numeric in subtraction (-) at
+ /usr/local/share/perl/5.10.0/FS/cust_bill.pm line 2359.
+
+ Argument "" isn't numeric in addition (+) at
+ /usr/local/share/perl/5.10.0/FS/cust_main.pm line 2788.
+
+2009-10-07 22:09 ivan
+
+ * FS/FS/cust_bill.pm: tyop
+
+2009-10-07 18:15 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, conf/invoice_html,
+ conf/invoice_latex: conf switches to turn on smaller notes and
+ footer sections with stock templates, RT#5218
+
+2009-10-07 16:51 ivan
+
+ * httemplate/view/cust_statement.html: naming follow-up notices
+ from the event rather than creting a slew of separate templates,
+ RT#5217
+
+2009-10-07 16:44 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/misc/email-statement.cgi,
+ httemplate/misc/send-invoice.cgi,
+ httemplate/misc/send-statement.cgi,
+ httemplate/search/cust_event.html,
+ FS/FS/part_event/Action/cust_bill_send_reminder.pm,
+ conf/invoice_html, conf/invoice_latex, conf/invoice_template,
+ httemplate/view/cust_bill-pdf.cgi,
+ httemplate/view/cust_bill-ps.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_statement.html: naming follow-up notices
+ from the event rather than creting a slew of separate templates,
+ RT#5217
+
+2009-10-06 17:43 ivan
+
+ * FS/FS/Conf_compat17.pm: bring up-to-date wrt 1.7 Conf.pm
+ 1.180.2.52 (2009-10-03), RT#2873
+
+2009-10-06 16:51 ivan
+
+ * FS/FS/cust_bill_pkg.pm: remove inadvertant debugging warnings
+
+2009-10-06 08:49 jeff
+
+ * httemplate/edit/router.cgi: replace disappearing line
+
+2009-10-05 16:36 ivan
+
+ * FS/FS/svc_acct.pm: remove annoying warning: Use of uninitialized
+ value $FS::svc_acct::passwordmin in pattern match (m//) at
+ /usr/local/share/perl/5.10.0/FS/svc_acct.pm line 60.
+
+2009-10-05 11:17 ivan
+
+ * httemplate/misc/payment.cgi: oops, handle old cust_main.pm
+ properly (should we be bothering?) :/ RT#5889
+
+2009-10-05 09:57 ivan
+
+ * httemplate/view/cust_main/payment_history/voided_payment.html:
+ doh, fix error viewing voided payments, RT#6382
+
+2009-10-05 08:07 jeff
+
+ * httemplate/elements/tr-select-pkg_class.html: remove unused
+ option that DTWT
+
+2009-10-05 07:04 jeff
+
+ * httemplate/edit/cust_main/: bottomfixup.js,
+ choose_tax_location.html, contact.html: low hanging fruit:
+ improvement in tax location selection RT#6000
+
+2009-10-05 07:01 jeff
+
+ * httemplate/edit/router.cgi: low hanging fruit: restore router
+ virtual fields (and svcnum) in 1.9 RT#5960
+
+2009-10-04 19:40 ivan
+
+ * httemplate/misc/payment.cgi: add manual_process-skip_first
+ option, RT#5889
+
+2009-10-04 19:35 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, httemplate/misc/payment.cgi:
+ add manual_process-skip_first option, RT#5889
+
+2009-10-04 19:16 ivan
+
+ * FS/FS/Conf.pm, httemplate/misc/payment.cgi,
+ httemplate/misc/process/payment.cgi: add manual_process-display
+ config to subtract fee from amount instead of adding, RT#5889
+
+2009-10-04 18:40 jeff
+
+ * conf/invoice_html: can't revert because windows is ghei
+
+2009-10-04 18:07 jeff
+
+ * FS/FS/cust_main.pm: don't consider setup or recurring taxes when
+ billing usage on cancel
+
+2009-10-04 18:00 jeff
+
+ * FS/FS/: cust_bill.pm, cust_main.pm, part_pkg/voip_cdr.pm:
+ invoices with details in separate section but usage not separated
+
+2009-10-04 17:49 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/Upgrade.pm,
+ FS/FS/cust_bill.pm, conf/invoice_html, conf/invoice_htmlsummary,
+ conf/invoice_latex, conf/invoice_latexsummary,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_bill_pkg_display.pm,
+ FS/FS/cust_main.pm, FS/FS/pkg_category.pm,
+ FS/FS/part_event/Action/cust_bill_fee_percent.pm,
+ FS/FS/part_event/Action/fee.pm,
+ httemplate/browse/pkg_category.html,
+ httemplate/edit/pkg_category.html: leading summary page invoices
+ #RT5086
+
+2009-10-04 16:36 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: fix the same
+ problem with processing payments & masked ACH amounts, RT#6374
+
+2009-10-04 16:31 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix problems "re-saving" a masked
+ card. hopefully the last of it!
+
+2009-10-03 19:09 ivan
+
+ * httemplate/misc/delete-cust_bill.html: delete invoices, RT#4048
+
+2009-10-03 19:04 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/Setup.pm,
+ FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm,
+ FS/bin/freeside-addgroup, bin/mapsecrets2access_user,
+ httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/payment_history/invoice.html: delete
+ invoices, RT#4048
+
+2009-10-03 17:08 ivan
+
+ * httemplate/view/cust_main.cgi: more room for cancellation reason
+
+2009-10-03 17:07 ivan
+
+ * httemplate/elements/popup_link-cust_main.html: doc
+
+2009-10-03 15:09 ivan
+
+ * httemplate/edit/part_bill_event.cgi: cancel to 80, comp @ 90,
+ RT#5674
+
+2009-10-03 15:06 ivan
+
+ * httemplate/edit/part_bill_event.cgi: in old invoice events,
+ chance default weight of cancel event to 90 so you can place it
+ at the same time as a realtime event, RT#5674
+
+2009-10-03 13:22 mark
+
+ * FS/FS/: pay_batch.pm, pay_batch/paymentech.pm: Load XML::Simple
+ at runtime to avoid breakage
+
+2009-10-01 16:48 ivan
+
+ * FS/FS/cust_main.pm: hopefully fully fix bulk email errors when
+ selecting a single payby
+
+2009-10-01 16:01 ivan
+
+ * FS/FS/Schema.pm: allow svc_acct._password to be NULL in the
+ schema
+
+2009-10-01 15:02 ivan
+
+ * httemplate/view/cust_main/payment_history/voided_payment.html:
+ consistency with un-voided payments wrt display
+
+2009-09-30 17:52 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: hopefully the
+ really final fix for the problems using remembered cards in
+ self-service. *sigh*
+
+2009-09-30 17:29 ivan
+
+ * FS/: FS/Conf.pm, FS/Cron/check.pm, bin/freeside-check: add login
+ check to FS::ClientAPI::SG/SGNG checks. RT#4610
+
+2009-09-30 12:33 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: hopefully the
+ final fix for the problems using remembered cards in self-service
+
+2009-09-29 15:08 ivan
+
+ * httemplate/misc/email-customers.html: should fix newsletter
+ sending error when you select a single payby only
+
+2009-09-28 23:17 ivan
+
+ * FS/t/cust_attachment.t: forgot
+
+2009-09-28 15:45 ivan
+
+ * FS/FS/Cron/check.pm: more accurate SG check, RT#4610
+
+2009-09-28 15:35 ivan
+
+ * FS/: FS/Cron/check.pm, bin/freeside-check: correct place for use
+ Email::Send, RT#4610
+
+2009-09-28 15:23 ivan
+
+ * FS/FS/Cron/check.pm: oops, hopefully fix sg cron check, RT#4610
+
+2009-09-28 08:55 jeff
+
+ * FS/FS/cust_pkg.pm: use object copy when billing on cancel to
+ avoid very weird side effects ( including 'impossible' history )
+ RT#5723
+
+2009-09-25 05:29 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi,
+ httemplate/config/config-process.cgi,
+ httemplate/misc/payment.cgi, httemplate/misc/process/payment.cgi:
+ processing fee on credit card recharges, RT#5889
+
+2009-09-25 03:29 ivan
+
+ * FS/FS/Conf.pm: this one too
+
+2009-09-25 03:14 ivan
+
+ * FS/FS/Conf.pm, FS/FS/svc_acct.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/elements/select-part_svc.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-part_svc.html: nomadix, RT#5876
+
+2009-09-24 19:30 mark
+
+ * FS/FS/pay_batch.pm, FS/FS/Conf.pm, FS/FS/pay_batch/BoM.pm,
+ FS/FS/pay_batch/PAP.pm, FS/FS/pay_batch/ach_spiritone.pm,
+ FS/FS/pay_batch/chase_canada.pm, FS/FS/pay_batch/paymentech.pm,
+ FS/FS/pay_batch/td_canada_trust.pm,
+ httemplate/misc/download-batch.cgi,
+ httemplate/search/cust_pay_batch.cgi: Batch payment refactoring
+
+2009-09-24 18:04 mark
+
+ * FS/MANIFEST: Add cust_attachment
+
+2009-09-24 12:59 ivan
+
+ * FS/FS/: Cron/check.pm, Conf.pm: get the ping username/pass from a
+ config, good enough, RT#4610
+
+2009-09-23 20:14 ivan
+
+ * FS/FS/Cron/check.pm, FS/bin/freeside-check,
+ FS/FS/ClientAPI/SGNG.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add SG and SGNG
+ ping, RT#4610
+
+2009-09-23 16:47 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: this should fix the occasional
+ extra ticket showing up on wrong customer record
+
+2009-09-21 20:08 ivan
+
+ * FS/FS/Mason.pm: add addl_comp_root.pl and addl_handler_use.pl
+ config files, RT#4743
+
+2009-09-21 13:48 ivan
+
+ * FS/FS/cust_bill.pm: i think it is new Pg (or... new Record.pm???)
+ that causes this problem... before it just returned nothing for
+ the search instead of erroring out?
+
+2009-09-20 23:05 ivan
+
+ * FS/FS/Conf.pm: doc clarification
+
+2009-09-20 22:35 ivan
+
+ * FS/FS/TicketSystem/RT_Internal.pm: left debugging on
+
+2009-09-20 19:41 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_ApplicationCommon.pm, FS/FS/cust_bill_pay.pm,
+ FS/FS/cust_bill_pay_pkg.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/elements/ApplicationCommon.html: add
+ ability to trigger receipts when payment is used against a
+ specific package instead of when it was made, RT#5199
+
+2009-09-18 15:41 ivan
+
+ * FS/FS/: cust_main.pm,
+ part_event/Condition/has_referral_custnum.pm: add active option
+ to has_referral_custnum condition, RT#6150
+
+2009-09-18 15:35 ivan
+
+ * httemplate/elements/: select-cust_main-status.html,
+ select-cust_pkg-status.html: fix customer and package status
+ conditions not sticky on edit, noticed on RT#6150
+
+2009-09-18 12:28 ivan
+
+ * httemplate/edit/elements/edit.html: better error message when the
+ clone object isn't found, RT#6128
+
+2009-09-17 18:03 ivan
+
+ * httemplate/view/cust_main/one_time_charge_link.html: fix one-time
+ charge inadvertantly checking the "tax exempt" checkbox when the
+ tax product popup is swapped in and out, RT#6095
+
+2009-09-17 16:45 ivan
+
+ * FS/FS/cust_bill.pm: eliminate mystery "min ( N.NN, M.MM )"
+ warning
+
+2009-09-16 18:37 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: fix sales tax report
+ w/part_pkg overrides, RT#6197
+
+2009-09-15 17:52 ivan
+
+ * FS/FS/Mason.pm: quiet warning: Subroutine
+ Net::Ping::External::_ping_linux redefined
+
+2009-09-15 16:13 ivan
+
+ * FS/FS/: cdr.pm, part_pkg/voip_cdr.pm: set svcnum when rating CDR,
+ RT#5495
+
+2009-09-15 15:58 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: hopefully really finish fixing for
+ good "Real timeprocessing not enabled!" error when using signup
+ without any real-time processor, RT#6043
+
+2009-09-15 13:45 ivan
+
+ * httemplate/search/svc_phone.cgi: fix phone# usage search, RT#
+
+2009-09-15 13:44 ivan
+
+ * httemplate/search/svc_external.cgi: modernize external search
+
+2009-09-15 13:44 ivan
+
+ * FS/FS/: cust_main_Mixin.pm, UI/Web.pm: fix display_custnum on
+ reports, RT#
+
+2009-09-15 12:45 ivan
+
+ * htetc/handler.pl: eliminate "Use of uninitialized value in undef
+ operator at /etc/freeside/handler.pl line 79/80" errors
+
+2009-09-14 16:52 ivan
+
+ * FS/FS/Mason.pm, httemplate/elements/popup_link-ping.html,
+ httemplate/misc/ping.html, httemplate/misc/xmlhttp-ping.html,
+ httemplate/view/svc_broadband.cgi,
+ httemplate/view/cust_main/packages/services.html: ping tool,
+ RT#5845
+
+2009-09-11 10:40 ivan
+
+ * FS/FS/cust_bill_pkg_detail.pm: preserve allowing empty values,
+ doh, RT#6101
+
+2009-09-11 08:51 ivan
+
+ * FS/FS/: Schema.pm, cust_bill_pkg.pm, cust_bill_pkg_detail.pm: fix
+ (hopefully the rest of the) fallout from rating CDRs to sub-penny
+ amounts
+
+2009-09-10 10:55 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/success.html: remove random >
+ char from signup success.html, RT#6110
+
+2009-08-31 15:17 mark
+
+ * FS/FS/cdr/vitelity.pm: Add Vitelity CDR format
+
+2009-08-29 15:47 mark
+
+ * FS/FS/: cdr.pm, cdr/broadsoft.pm: Add Broadsoft CDR record format
+
+2009-08-29 15:45 mark
+
+ * FS/bin/freeside-cdr-sftp_and_import: Add FTP support
+
+2009-08-29 12:05 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: hopefully really fix self-service
+ when not using real-time gateway
+
+2009-08-29 11:51 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: hopefully fix self-service when not
+ using real-time gateway
+
+2009-08-27 14:41 ivan
+
+ * httemplate/elements/menu.html: oops, tax class menu item got lost
+
+2009-08-27 03:26 ivan
+
+ * bin/move-customers: try, try again
+
+2009-08-27 03:23 ivan
+
+ * bin/move-customers: doh
+
+2009-08-27 03:04 ivan
+
+ * bin/move-customers: ok
+
+2009-08-26 23:52 ivan
+
+ * FS/FS/part_export/amazon_ec2.pm: amazon ec2 provisioning
+
+2009-08-26 13:52 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: improve
+ testing need for invoicing list
+
+2009-08-26 09:19 rsiddall
+
+ * FS/FS/part_export/domreg_net_dri.pm: OpenSRS support for domain
+ registration first appears in Net::DRI 0.95.
+
+2009-08-26 04:22 ivan
+
+ * httemplate/search/: report_svc_phone.html, svc_phone.cgi: first
+ pass at balance reporting, RT#5496
+
+2009-08-26 03:18 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add granularity to single_price CDR
+ rating, RT#5495
+
+2009-08-25 12:08 jeff
+
+ * httemplate/search/: 477.html, report_477.html,
+ elements/search.html: improved 477 report #6004
+
+2009-08-25 10:03 jeff
+
+ * FS/FS/Record.pm: support listref to qsearch as UNION
+
+2009-08-24 04:09 ivan
+
+ * bin/move-customers: customer move script, RT#5351
+
+2009-08-24 01:50 ivan
+
+ * FS/FS/cust_main.pm, bin/move-customers: (start of) customer move
+ script, RT#5351
+
+2009-08-24 00:08 ivan
+
+ * bin/move-customers: (start of) customer move script, RT#5351
+
+2009-08-23 23:50 ivan
+
+ * bin/move-customers: (start of) customer move script, RT#5351
+
+2009-08-23 23:39 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm, FS/FS/part_pkg.pm,
+ bin/move-customers: (start of) customer move script, RT#5351
+
+2009-08-23 23:13 jeff
+
+ * httemplate/edit/process/part_pkg.cgi: fix select multiple report
+ option
+
+2009-08-23 22:09 jeff
+
+ * httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/cust_bill_pkg_detail.cgi,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/graph/report_cust_bill_pkg_detail.html,
+ FS/FS/Report/Table/Monthly.pm, httemplate/elements/menu.html,
+ httemplate/search/cust_bill_pkg.cgi: add rated call sales report
+ and option to sales report to count usage separately from
+ recurring #5588
+
+2009-08-21 17:31 ivan
+
+ * httemplate/view/cust_main/packages/status.html: better label
+
+2009-08-21 17:31 ivan
+
+ * httemplate/misc/states.cgi: mason style
+
+2009-08-21 17:30 ivan
+
+ * httemplate/elements/header.html: doc
+
+2009-08-21 17:29 ivan
+
+ * httemplate/edit/elements/edit.html: use name_singular if
+ available too
+
+2009-08-21 17:29 ivan
+
+ * httemplate/edit/cust_main/bottomfixup.js: comment
+
+2009-08-21 17:29 ivan
+
+ * httemplate/edit/quick-charge.html: comments
+
+2009-08-21 17:29 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/passwd.cgi: not necessary
+
+2009-08-21 17:27 ivan
+
+ * FS/FS/Cron/check.pm: fewer false positives
+
+2009-08-21 17:27 ivan
+
+ * FS/FS/cust_bill.pm: doc
+
+2009-08-21 17:26 ivan
+
+ * FS/FS/Record.pm: cleaner??
+
+2009-08-21 17:22 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi, FS/FS/Conf.pm,
+ FS/FS/ClientAPI/MasonComponent.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/misc/part_svc-columns.cgi,
+ fs_selfservice/FS-SelfService/cgi/misc/svc_acct-domains.cgi,
+ httemplate/edit/cust_main/first_pkg/select-part_pkg.html,
+ httemplate/edit/cust_main/first_pkg/svc_acct.html: order
+ svc_phone services from self-service too, RT#5085
+
+2009-08-20 13:44 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: mitigate harmless
+ warnings spamming logs
+
+2009-08-20 02:55 ivan
+
+ * FS/FS/part_event/Condition.pm: allow generic conditions for
+ cust_statement, RT#4860
+
+2009-08-20 02:47 ivan
+
+ * FS/FS/Mason.pm, FS/FS/cust_statement.pm, FS/FS/Cron/bill.pm,
+ FS/FS/part_event/Action/cust_statement.pm,
+ FS/FS/part_event/Action/cust_statement_send.pm,
+ FS/FS/part_event/Condition/has_pkg_class.pm,
+ FS/FS/part_event/Condition/has_pkgpart.pm,
+ FS/FS/part_event/Condition/hasnt_pkgpart.pm,
+ httemplate/misc/email-statement.cgi,
+ httemplate/view/cust_statement-pdf.cgi,
+ httemplate/view/cust_statement.html: email statements, RT#4860
+
+2009-08-20 02:26 ivan
+
+ * bin/generate-table-module: tired of asking
+
+2009-08-19 21:03 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_statement.pm, FS/FS/part_event.pm,
+ FS/t/cust_statement.t, FS/FS/Cron/bill.pm,
+ FS/FS/part_event/Action/cust_statement.pm,
+ FS/FS/part_event/Action/cust_statement_send.pm,
+ httemplate/view/cust_statement.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/payment_history/statement.html:
+ Emailing statements of accounts, RT#4860
+
+2009-08-19 19:40 ivan
+
+ * FS/FS/part_event/Action/cust_bill_send.pm: eliminate unnecessary
+ lookup
+
+2009-08-19 14:27 ivan
+
+ * FS/FS/part_event/Action/: cust_bill_fee_percent.pm, fee.pm,
+ pkg_referral_credit_pkg.pm: add option to disable late fee taxes
+
+2009-08-19 00:05 mark
+
+ * FS/FS/part_export/shellcommands_withdomain.pm: Turn off
+ userdel_no_queue for MagicMail export
+
+2009-08-18 23:15 jeff
+
+ * FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/search/cust_bill_pkg.cgi: option to count subpackages
+ outside packages in sales report #5588
+
+2009-08-18 05:21 jeff
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main/bottomfixup.js: support
+ 2009 - a better way?
+
+2009-08-17 16:08 mark
+
+ * FS/FS/part_export/: shellcommands.pm,
+ shellcommands_withdomain.pm: Add more fine-grained queue options
+
+2009-08-17 13:48 jeff
+
+ * FS/FS/: Record.pm, Schema.pm, cust_bill.pm, cust_bill_pkg.pm,
+ cust_bill_pkg_detail.pm, cust_svc.pm, part_pkg/voip_cdr.pm:
+ improve emailed cdr csv file (#5727 again)
+
+2009-08-16 15:45 jeff
+
+ * httemplate/edit/cust_main/bottomfixup.js: include a census
+ zipcode link and other minor improvements
+
+2009-08-14 15:13 jeff
+
+ * FS/FS/svc_acct.pm: add svcnum lookup for svc_acct
+
+2009-08-14 14:51 jeff
+
+ * FS/FS/part_export/shellcommands.pm: add pkgnum and custnum to use
+ as external ids
+
+2009-08-14 10:26 mark
+
+ * httemplate/edit/cust_main_attach.cgi: Fix incorrect access right
+
+2009-08-14 10:24 mark
+
+ * FS/FS/AccessRight.pm: Move note/attachment rights to new section
+
+2009-08-13 15:53 mark
+
+ * FS/bin/freeside-void-payments: Add option to
+ freeside-void-payments to cancel customers
+
+2009-08-13 08:13 jeff
+
+ * FS/FS/cust_pkg.pm: fix fix multiple pkgpart search (need sanity
+ check): don't let empty set limit search
+
+2009-08-13 02:35 ivan
+
+ * ChangeLog: adding autogen changelog on 1.9
+
+2009-08-13 02:25 ivan
+
+ * httemplate/view/cust_main.cgi: fix reverted changes. grr.
+ RT#4964
+
+2009-08-12 17:26 ivan
+
+ * init.d/freeside-init: useful stuff for webdemo & profiling
+
+2009-08-12 07:58 jeff
+
+ * bin/billco-upload, Makefile, FS/FS/Conf.pm, FS/FS/Cron/upload.pm,
+ FS/bin/freeside-daily, FS/bin/freeside-monthly,
+ httemplate/config/config-view.cgi: internalize billco-upload and
+ automate the transfer to the provider RT#5902
+
+2009-08-12 04:57 ivan
+
+ * httemplate/: docs/about.html, docs/credits.html,
+ docs/license.html, elements/header-popup.html: slight
+ about/credits UI tweak
+
+2009-08-11 22:22 ivan
+
+ * FS/FS/: cust_main.pm, part_event/Action.pm,
+ part_event/Action/cust_bill_fee_percent.pm,
+ part_event/Action/fee.pm: add pre-bill event stage for late fees,
+ RT#5589
+
+2009-08-11 19:36 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/misc/bulk_change_pkg.cgi,
+ httemplate/search/cust_pkg.cgi: fix multiple pkgpart search,
+ RT#5924
+
+2009-08-11 14:33 rsiddall
+
+ * rpm/freeside.spec: Back out kludge to show CVS snapshot date in
+ version number in GUI. You can get the snapshot date from the
+ release number using "rpm -q freeside".
+
+2009-08-11 14:29 rsiddall
+
+ * Makefile: Reset RPM release number back to 1 on a new version
+ release.
+
+2009-08-10 19:45 ivan
+
+ * FS/FS/part_event/Action/writeoff.pm: fix bad debt writeoff
+ action, RT#5798
+
+2009-08-10 19:34 ivan
+
+ * FS/FS/cust_main.pm: add $company_name and $company_address to
+ decline template, RT#5869
+
+2009-08-10 16:04 mark
+
+ * FS/FS/AccessRight.pm, httemplate/edit/cust_main_attach.cgi,
+ httemplate/edit/process/cust_main_attach.cgi,
+ httemplate/view/attachment.html, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/attachments.html: Improve handling of
+ deleted attachments
+
+2009-08-10 14:44 ivan
+
+ * FS/FS/part_export/netsapiens.pm: last nits on netsapiens export,
+ RT#5226
+
+2009-08-10 11:05 mark
+
+ * FS/FS/part_export/shellcommands_withdomain.pm: Add preset for
+ magicmail
+
+2009-08-10 04:57 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/process_svc_external.html: when
+ using pkg-balances, limit self-service access when a customer
+ with multiple packages logs on, RT#4189
+
+2009-08-10 04:50 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/login.html,
+ fs_selfservice/FS-SelfService/cgi/logout.html,
+ fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html:
+ when using pkg-balances, limit self-service access when a
+ customer with multiple packages logs on, RT#4189
+
+2009-08-09 16:53 jeff
+
+ * FS/FS/part_event/Action/cust_bill_spool_csv.pm: whoops: theory
+ should match practice
+
+2009-08-09 16:45 jeff
+
+ * FS/FS/part_event/Action/cust_bill_spool_csv.pm: fix per agent
+ spools
+
+2009-08-09 15:47 jeff
+
+ * FS/FS/cust_bill_pkg.pm: don't bomb when the line item has no
+ start date
+
+2009-08-09 02:05 mark
+
+ * FS/FS/cust_attachment.pm, httemplate/edit/cust_main_attach.cgi,
+ httemplate/edit/process/cust_main_attach.cgi,
+ httemplate/view/attachment.html, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/attachments.html, FS/FS/AccessRight.pm,
+ FS/FS/Conf.pm, FS/FS/Mason.pm, FS/FS/Record.pm, FS/FS/Schema.pm:
+ Add cust_attachment stuff
+
+2009-08-07 16:08 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/top_misc.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/elements/tr-input-date-field.html: add ability to edit
+ signup dates (turn on cust_main-edit_signupdate config), RT#4644
+
+2009-08-06 17:39 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/elements/tr-input-date-field.html,
+ httemplate/misc/order_pkg.html,
+ httemplate/view/cust_main/packages.html: don't start recurring
+ billing when a start date hasn't been reached yet either... and
+ since that works, add the start date to new package order,
+ RT#5347
+
+2009-08-05 17:41 ivan
+
+ * FS/FS/part_export/netsapiens.pm: pass mac addresses as lower-case
+ to netsapiens, RT#5226
+
+2009-08-05 17:39 ivan
+
+ * FS/FS/svc_phone.pm: delete phone_device records when svc_phone is
+ deleted, RT#5226
+
+2009-08-05 16:32 ivan
+
+ * FS/FS/part_pkg/: agent.pm, base_rate.pm, flat.pm,
+ flat_delayed.pm, prorate_delayed.pm: fix cancellation errors with
+ updated flat_introrate, RT#5865
+
+2009-08-04 19:27 ivan
+
+ * FS/FS/: svc_acct.pm: export negative byte values to chillispot
+ attributes as 0, RT#5815
+
+2009-08-04 16:43 ivan
+
+ * FS/: FS/svc_acct.pm, bin/freeside-sqlradius-reset: hopefully
+ ignore errors about deleted accounts and properly finish
+ freeside-sqlradius-reset, RT#5868
+
+2009-08-04 15:04 ivan
+
+ * FS/: FS/svc_Common.pm, bin/freeside-sqlradius-reset: ignore
+ problams calling ->overlimit during sqlradius-reset, wtf?!
+ RT#5868
+
+2009-08-03 17:19 ivan
+
+ * FS/FS/cust_pkg.pm: don't reset usage on package change when
+ usage_rollover is on, it adds twice...
+
+2009-08-03 12:54 ivan
+
+ * httemplate/elements/header.html: looks slightly better in default
+ IE hopefully
+
+2009-08-03 07:17 jeff
+
+ * FS/FS/part_export/shellcommands.pm: new doesn't exist
+
+2009-08-03 07:07 jeff
+
+ * FS/FS/part_export/shellcommands.pm: bad tyops
+
+2009-08-01 12:16 jeff
+
+ * FS/FS/: Schema.pm, queue.pm, queue_arg.pm: support broader array
+ of queue args #5855, fallout from #5495
+
+2009-07-31 06:20 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/ach_payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/change_bill.html,
+ fs_selfservice/FS-SelfService/cgi/change_password.html,
+ fs_selfservice/FS-SelfService/cgi/change_pay.html,
+ fs_selfservice/FS-SelfService/cgi/change_ship.html,
+ fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/delete_svc.html,
+ fs_selfservice/FS-SelfService/cgi/footer.html,
+ fs_selfservice/FS-SelfService/cgi/header.html,
+ fs_selfservice/FS-SelfService/cgi/login.html,
+ fs_selfservice/FS-SelfService/cgi/logout.html,
+ fs_selfservice/FS-SelfService/cgi/make_ach_payment.html,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_bill.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_password.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_pay.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_ship.html,
+ fs_selfservice/FS-SelfService/cgi/process_order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/process_order_recharge.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/provision.html,
+ fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/recharge_prepay.html,
+ fs_selfservice/FS-SelfService/cgi/recharge_results.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_invoice.html,
+ fs_selfservice/FS-SelfService/cgi/view_usage_details.html: skin
+ up self-service according to config passed from backend, RT#5530
+
+2009-07-31 00:58 ivan
+
+ * bin/cdr-transnexus.import: only need Customer-CDRs, RT#5229
+
+2009-07-31 00:51 ivan
+
+ * bin/cdr-transnexus.import: only need Customer-CDRs, RT#5229
+
+2009-07-30 02:19 ivan
+
+ * FS/FS/: cust_main.pm, ClientAPI/MyAccount.pm: pass a pkgnum from
+ self-service if applicable, RT#4339
+
+2009-07-30 01:43 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: lost fix for
+ illegal state?
+
+2009-07-30 00:39 ivan
+
+ * httemplate/view/cust_main/change_history.html: small fix to
+ change history to not error out with svc_acct services, RT#1005
+
+2009-07-30 00:35 mark
+
+ * FS/FS/part_export/shellcommands.pm: Make no_queue option work
+ correctly
+
+2009-07-29 23:52 ivan
+
+ * httemplate/view/cust_main/payment_history.html: didn't mean to
+ leave a Dump(er) there
+
+2009-07-29 23:50 ivan
+
+ * httemplate/edit/cust_pay.cgi: another accidentally (alliterated)
+ vestigial variable
+
+2009-07-29 23:49 ivan
+
+ * httemplate/edit/cust_credit.cgi: don't need to lookup cust_main
+ here
+
+2009-07-29 23:48 ivan
+
+ * httemplate/elements/select-cust_pkg-balances.html: fix for
+ stickiness on errors
+
+2009-07-29 23:42 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_ApplicationCommon.pm, FS/FS/cust_bill_pay.pm,
+ FS/FS/cust_credit.pm, FS/FS/cust_credit_bill.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pay_pending.pm,
+ FS/FS/cust_pay_void.pm, FS/FS/cust_pkg.pm, FS/FS/cust_main.pm,
+ httemplate/edit/cust_credit.cgi, httemplate/edit/cust_pay.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/elements/select-cust_pkg-balances.html,
+ httemplate/elements/tr-select-cust_pkg-balances.html,
+ httemplate/view/cust_bill.cgi, httemplate/view/cust_pay.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/packages/status.html,
+ httemplate/view/cust_main/payment_history/payment.html,
+ httemplate/view/cust_main/payment_history/credit.html,
+ httemplate/view/cust_main/payment_history/voided_payment.html:
+ experimental package balances, RT#4339
+
+2009-07-28 15:21 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, httemplate/edit/cust_main/billing.html,
+ httemplate/view/cust_main/billing.html: feature to email CSV of
+ CDRs with invoices #5727
+
+2009-07-28 14:17 ivan
+
+ * FS/FS/Conf.pm, FS/FS/AccessRight.pm, FS/FS/Mason.pm,
+ FS/FS/svc_external.pm, httemplate/pref/pref.html,
+ httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/change_history.html: adding a basic
+ change history using history tables, RT#1005, RT#4357
+
+2009-07-27 19:12 mark
+
+ * FS/FS/part_export/: shellcommands.pm,
+ shellcommands_withdomain.pm: Add no_queue option to shellcommands
+ exports
+
+2009-07-27 12:51 ivan
+
+ * httemplate/misc/cancel_pkg.html: fix spacing
+
+2009-07-27 02:59 ivan
+
+ * httemplate/search/: report_cust_pay.html,
+ elements/cust_pay_or_refund.html: searching for voided payments
+ by void date as well, RT#5786
+
+2009-07-27 02:07 ivan
+
+ * httemplate/: elements/menu.html, search/cust_pay_void.html,
+ search/report_cust_pay.html,
+ search/elements/cust_pay_or_refund.html, view/cust_pay.html,
+ view/cust_pay_void.html: voided payment report, RT#5786
+
+2009-07-26 23:17 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-view.cgi: add deprecated
+ config options back to Conf.pm to fix "unapplypayments" fails
+ existential comparison errors, RT#2927
+
+2009-07-26 20:26 jeff
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/bottomfixup.js,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/elements/location.html,
+ httemplate/misc/xmlhttp-cust_main-censustract.html,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/view/cust_main/misc.html: FCC from 477 improvements
+ #4912
+
+2009-07-26 13:23 jeff
+
+ * httemplate/search/svc_broadband.cgi: fix links
+
+2009-07-26 12:36 ivan
+
+ * rt/: FREESIDE_MODIFIED, html/Elements/PageLayout,
+ html/Elements/SelectDate: fix the date picker in RT to use
+ jscalendar instead of an HTML popup (that had acquired the page
+ header, eek), RT#1682
+
+2009-07-26 11:40 ivan
+
+ * FS/FS/Conf_compat17.pm: bring up-to-date wrt 1.7 Conf.pm
+ 1.180.2.49 (2009-7-26), RT#2873
+
+2009-07-25 23:38 jeff
+
+ * FS/bin/freeside-apply_payments_and_credits: command line tool to
+ apply payments and credits
+
+2009-07-25 15:00 ivan
+
+ * htetc/handler.pl: set a character encoding for all pages; this
+ should fix problems with diamond question marks even when the
+ server gets an UTF-8 default setting, RT#3094
+
+2009-07-25 14:33 ivan
+
+ * FS/FS/cust_event.pm, httemplate/search/cust_event.html: this
+ should fix the re-email/print links on event search pages sending
+ too much, RT#5740, RT#5570
+
+2009-07-25 00:57 ivan
+
+ * FS/FS/Record.pm: teach Record.pm about BYTEA handling in order to
+ store files in the db, RT#4964
+
+2009-07-24 02:38 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add handling of ChilliSpot (and
+ CoovaChilli) Max attributes, specifically
+ ChilliSpot-Max-{Input,Output,Total}-{Octets,Gigawords}, RT#5815
+
+2009-07-23 22:51 mark
+
+ * FS/bin/freeside-void-payments: Add -v switch (verbose) to
+ freeside-void-payments
+
+2009-07-23 12:46 ivan
+
+ * FS/FS/cust_pay.pm: avoid harmless warning: Use of uninitialized
+ value in string ne
+
+2009-07-23 12:40 ivan
+
+ * FS/bin/freeside-void-payments: fix -r option, RT#5675
+
+2009-07-23 09:48 jeff
+
+ * httemplate/browse/svc_acct_pop.cgi: restore svc_acct_pop editing
+
+2009-07-23 06:25 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/process/cust_main_county-collapse.cgi: add back remove
+ ("collapse") links again. on each line this time. RT#2973
+
+2009-07-22 23:58 ivan
+
+ * FS/FS/Tron.pm: need to see who is still on deb 4 & pg 7.4
+
+2009-07-22 15:05 ivan
+
+ * httemplate/view/cust_main/misc.html: fix bombing out on new
+ DateTime
+
+2009-07-21 11:44 ivan
+
+ * FS/FS/: Schema.pm, part_pkg/cdr_termination.pm: sub-penny
+ termination pricing too, RT#5495
+
+2009-07-21 00:03 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: yow. fix spurious charge errors
+ w/single_price, round to four decimal places (wtf?) instead of 2,
+ RT#5495
+
+2009-07-20 22:29 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: and fix min_charge option, RT#5495
+
+2009-07-20 22:27 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: if we're going to do recur_Common,
+ have to use and @ISA (and capitalize) it
+
+2009-07-20 17:20 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: don't have a money type in package
+ definitions at the moment
+
+2009-07-20 16:01 jeff
+
+ * FS/FS/: Conf.pm, cust_bill.pm: config setting to have emailed
+ invoices include call details #5275
+
+2009-07-20 07:26 jeff
+
+ * httemplate/elements/checkbox.html,
+ httemplate/elements/tr-checkbox.html,
+ httemplate/elements/tr-justtitle.html,
+ httemplate/elements/tr-title.html, FS/FS/Schema.pm,
+ FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm, FS/FS/cust_main.pm,
+ FS/FS/part_pkg.pm, FS/FS/part_pkg_link.pm,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/elements/edit.html,
+ httemplate/edit/process/part_pkg.cgi: bundle bill linked packages
+ into top line total when desired #5724
+
+2009-07-19 21:51 ivan
+
+ * FS/FS/cust_pkg.pm: one $conf is enough
+
+2009-07-19 21:40 ivan
+
+ * rt/: FREESIDE_MODIFIED, lib/RT/Transaction_Overlay.pm: slightly
+ improve terrible quoting behavior when you change MessageBoxWidth
+
+2009-07-19 21:19 ivan
+
+ * httemplate/elements/header.html: fix preferences links showing as
+ blue/purple on RT side
+
+2009-07-19 21:14 ivan
+
+ * rt/: FREESIDE_MODIFIED, html/Ticket/Create.html: fix badly styled
+ links on ticket create (fallout from RT borging/styling)
+
+2009-07-17 16:33 ivan
+
+ * FS/FS/cdr.pm: remove unused cdr_upstream_rate
+
+2009-07-17 16:10 rsiddall
+
+ * rpm/freeside.spec: Filter out requirements for specific Freeside
+ modules so that you can install an RPM which requires missing
+ Freeside modules.
+
+2009-07-17 15:26 ivan
+
+ * FS/: FS/cust_main.pm, FS/Cron/bill.pm, bin/freeside-daily: commit
+ pkgpart exclusion for billing run, RT#5495
+
+2009-07-17 07:58 jeff
+
+ * bin/billco-upload: add mutex and commit changes found on
+ installed system
+
+2009-07-16 19:29 jeff
+
+ * httemplate/search/cust_pkg.cgi: FSM, another missed file for 477
+ reporting
+
+2009-07-16 18:44 jeff
+
+ * FS/FS/: Conf.pm, cust_main.pm, cust_pkg.pm, part_pkg/voip_cdr.pm:
+ bill usage when cancelling package
+
+2009-07-16 18:08 jeff
+
+ * bin/generate-table-module: black magic to edit Mason.pm as well
+
+2009-07-16 17:35 ivan
+
+ * FS/FS/part_pkg/: voip_cdr.pm: add single_price option so you can
+ do one per-minute price without rate tables, RT#5495
+
+2009-07-16 17:33 ivan
+
+ * FS/MANIFEST: get rid of cdr_upstream_rate table and some other
+ old convergent cruft
+
+2009-07-16 17:10 ivan
+
+ * FS/: FS/Schema.pm, FS/cdr.pm, FS/cdr_upstream_rate.pm,
+ FS/part_pkg/voip_cdr.pm, FS.pm, t/cdr_upstream_rate.t: get rid of
+ cdr_upstream_rate table and some other old convergent cruft
+
+2009-07-16 15:16 jeff
+
+ * FS/FS/Mason.pm: dark magic coming soon
+
+2009-07-15 18:57 jeff
+
+ * httemplate/search/477.html: duh! more 477 files
+
+2009-07-15 18:35 jeff
+
+ * httemplate/search/report_477.html: missed file for 477 reporting
+
+2009-07-15 16:06 ivan
+
+ * FS/FS/part_pkg/cdr_termination.pm: unused for now
+
+2009-07-15 15:49 ivan
+
+ * FS/FS/: Conf.pm, cdr.pm: add option to trim leading zeros when
+ setting charged_party to accountcode, RT#5495
+
+2009-07-14 12:06 rsiddall
+
+ * FS/FS/part_export/domreg_net_dri.pm: Minor bug fix, spotted by
+ Jeff.
+
+2009-07-14 12:05 rsiddall
+
+ * FS/FS/svc_domain.pm: Changed description of "action" field to
+ match domain registration exports.
+
+2009-07-13 20:14 ivan
+
+ * htetc/handler.pl: fix warnings, from RT merge fallout
+
+2009-07-13 19:53 ivan
+
+ * FS/FS/part_export/netsapiens.pm: fix netsapiens device
+ provisioning? or at least better debugging, RT#5226
+
+2009-07-13 19:52 ivan
+
+ * httemplate/elements/tr-select-did.html: stop Dumper spew
+
+2009-07-13 17:28 rsiddall
+
+ * Makefile, FS/FS/svc_domain.pm,
+ FS/FS/part_export/domreg_net_dri.pm,
+ httemplate/edit/process/domreg.cgi: New export to
+ register/transfer/renew/revoke domains using Net::DRI. Currently
+ optimized for OpenSRS. Should become more generalized in later
+ releases. Modified Makefile to insert the Freeside log folder
+ into the new export. Modified svc_domain.pm to prevent
+ generation of transfer requests when a domain is moved to a
+ different package with a domain registration attached to one of
+ the included services. Modified domreg.cgi to display errors on
+ a separate page.
+
+2009-07-13 09:02 jeff
+
+ * FS/FS/: tax_rate.pm, tax_rate_location.pm: correct ordering and
+ other bugs in tax updates
+
+2009-07-13 03:12 ivan
+
+ * FS/FS/part_pkg/recur_Common.pm: eliminate harmless "no %info hash
+ found in FS::part_pkg::recur_Common, skipping" warning
+
+2009-07-13 02:19 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi: fix
+ self-service agent-specific logos
+
+2009-07-13 02:10 ivan
+
+ * httemplate/view/cust_bill-logo.cgi: fix old-style agent-virt
+ logo?
+
+2009-07-13 00:21 ivan
+
+ * conf/invoice_html: thank you IE8
+
+2009-07-13 00:10 ivan
+
+ * httemplate/search/report_unapplied_cust_pay.html: clarify wording
+
+2009-07-12 20:24 ivan
+
+ * rt/html/Elements/PageLayout: think that should be it, fix bar
+ when there's no primary $page_tabs
+
+2009-07-12 20:15 ivan
+
+ * rt/html/Elements/Footer: no need for Time to display either
+
+2009-07-12 19:33 ivan
+
+ * rt/html/Elements/PageLayout: style RT's menubars like ours
+
+2009-07-12 18:50 ivan
+
+ * httemplate/elements/: header.html, menubar.html: style nits
+
+2009-07-12 16:45 ivan
+
+ * httemplate/elements/header.html: fix header sizes :/
+
+2009-07-12 16:38 ivan
+
+ * FS/FS/CGI.pm: this should fix $fsurl under the unified RT? sure
+ hope so
+
+2009-07-12 16:27 ivan
+
+ * rt/html/NoAuth/css/3.5-default/titlebox.css: fix excessive RT
+ margins
+
+2009-07-12 16:25 ivan
+
+ * httemplate/edit/cust_main.cgi: ACL on customer edit
+
+2009-07-12 16:22 ivan
+
+ * httemplate/elements/header.html, httemplate/elements/menu.html,
+ httemplate/elements/xmenu.css, httemplate/elements/xmenu.top.css,
+ rt/FREESIDE_MODIFIED, rt/etc/RT_SiteConfig.pm,
+ rt/html/Elements/Header,
+ rt/html/NoAuth/css/3.5-default/freeside.css,
+ rt/html/NoAuth/css/3.5-default/misc.css,
+ rt/html/Ticket/Display.html: resolve style weirdness (fallout
+ from RT integration), especially non-fixed-width comment boxes,
+ menu/searchbar differences, RT#1169
+
+2009-07-12 12:32 ivan
+
+ * httemplate/elements/menu.html: update tickting config
+ descriptions
+
+2009-07-12 06:27 jeff
+
+ * FS/FS/Record.pm: stop gratuitous hash manipulatoin during enum
+ untaint
+
+2009-07-10 19:40 ivan
+
+ * bin/drop_slony.slonik: notes
+
+2009-07-10 10:50 ivan
+
+ * httemplate/elements/: select-did.html, tr-select-did.html: fix
+ svc_phone provisioning!
+
+2009-07-09 17:36 ivan
+
+ * FS/FS/cdr.pm: fix sansay CDR import to ignore "NA" in dates,
+ RT#5495
+
+2009-07-09 16:59 ivan
+
+ * FS/FS/cdr.pm, FS/FS/cdr/sansay.pm, eg/cdr_template.pm: sansay
+ CDRs, RT#5495
+
+2009-07-09 16:58 ivan
+
+ * FS/bin/freeside-cdr-sftp_and_import: add -r option
+
+2009-07-09 14:05 ivan
+
+ * FS/FS/cust_main.pm, httemplate/elements/menu.html,
+ httemplate/search/report_unapplied_cust_pay.html,
+ httemplate/search/unapplied_cust_pay.html: unapplied payments
+ report, RT#4861
+
+2009-07-09 13:36 ivan
+
+ * httemplate/search/elements/cust_main_dayranges.html: no idea how
+ i missed fixing this before
+
+2009-07-09 13:18 ivan
+
+ * httemplate/search/report_receivables.cgi: oops
+
+2009-07-08 19:34 ivan
+
+ * rt/html/Elements/Header: doh, fix RT onLoadHook; this fixes
+ "Undefined subroutine &HTML::Mason::Commands::onLoadHook" error
+ on ticket creation and otherwise, RT#1169
+
+2009-07-08 04:12 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm,
+ FS/FS/TicketSystem/RT_Internal.pm, httemplate/elements/menu.html,
+ FS/FS/Conf.pm, FS/FS/Mason.pm, htetc/handler.pl,
+ httemplate/elements/about_freeside.html,
+ httemplate/elements/about_rt.html,
+ httemplate/elements/header.html,
+ httemplate/elements/popup_link.html, rt/FREESIDE_MODIFIED,
+ rt/html/Elements/Header, rt/html/Elements/PageLayout,
+ rt/html/Elements/Tabs, rt/html/Prefs/SearchOptions.html,
+ rt/html/User/Prefs.html: borg RT menus, RT#1169
+
+2009-07-07 20:33 ivan
+
+ * httemplate/search/: report_receivables.cgi,
+ report_unapplied_cust_pay.html, unapplied_cust_pay.html,
+ elements/cust_main_dayranges.html: factor out the range-handling
+ portions of receivables report, start on a similar unapplied
+ payment report, RT#4861
+
+2009-07-07 02:53 ivan
+
+ * FS/FS/Schema.pm, httemplate/view/svc_broadband.cgi: allow null
+ svc_broadband.ip_addr
+
+2009-07-07 02:23 ivan
+
+ * FS/FS/: Conf.pm, Schema.pm, svc_broadband.pm: allow null
+ svc_broadband.ip_addr
+
+2009-07-07 02:22 ivan
+
+ * httemplate/edit/svc_broadband.cgi: UI nit - double #
+
+2009-07-07 00:32 mark
+
+ * FS/bin/freeside-void-payments: Add freeside-void-payments script
+ for returned check processing
+
+2009-07-06 17:53 ivan
+
+ * FS/FS/cdr/netcentrex.pm: for netcentrex CDRs, import duration to
+ duration field (previously only billsec)
+
+2009-07-06 17:47 ivan
+
+ * FS/FS/cdr.pm: on CDR date parse, consider 1970-01-01 NULL like
+ 1900-01-01, RT#4081
+
+2009-07-06 16:14 ivan
+
+ * httemplate/search/: cdr.html, report_cdr.html: search cdr by
+ acctid
+
+2009-07-06 14:34 ivan
+
+ * httemplate/browse/rate_region.html: align, display countrycode
+ with +, space between prefixes allowing wrapping
+
+2009-07-05 17:28 ivan
+
+ * httemplate/view/svc_phone.cgi: fix incoming CDR links wrt
+ cdrbatch field
+
+2009-07-05 17:10 ivan
+
+ * httemplate/elements/: select-did.html, tr-select-did.html: doh
+
+2009-07-05 16:56 ivan
+
+ * httemplate/elements/: select-did.html, tr-select-did.html: allow
+ svc_phone.phonenum to be edited when a DID selector is not in use
+
+2009-07-05 16:17 ivan
+
+ * httemplate/search/cdr.html: format start/answer/end dates and
+ link svcnum to service
+
+2009-07-05 14:35 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cdr.pm,
+ httemplate/elements/checkboxes.html, httemplate/search/cdr.html,
+ httemplate/search/report_cdr.html: CDR search by dcontext,
+ charged_party, toggle of display fields, RT#4081
+
+2009-07-03 17:47 ivan
+
+ * FS/FS/part_event/Condition/: cust_payments.pm,
+ cust_payments_pkg.pm: add condition based on total customer
+ payments as a multiplier of a specific package, RT#3983
+
+2009-07-03 17:08 ivan
+
+ * FS/FS/part_event/Condition/once.pm: spealing
+
+2009-07-02 04:22 ivan
+
+ * FS/FS/cdr.pm, FS/FS/Schema.pm, FS/FS/cdr_termination.pm,
+ FS/FS/part_pkg/cdr_termination.pm,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/search/cdr.html, httemplate/search/report_cdr.html:
+ settlement cdr processing, RT#5495
+
+2009-07-01 19:02 ivan
+
+ * FS/FS/: cust_main.pm, part_event/Action/cust_bill_fee_percent.pm,
+ part_event/Action/fee.pm: fix late fees, RT#5665
+
+2009-07-01 18:26 jeff
+
+ * FS/FS/ClientAPI/MyAccount.pm, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/flat_introrate.pm, httemplate/search/cust_pkg.cgi:
+ update flat_introrate plan to better fit current codebase RT#4912
+
+2009-07-01 03:28 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/cdr_termination.pm,
+ FS/FS/cust_main.pm, FS/FS/part_pkg/cdr_termination.pm,
+ FS/FS/part_pkg/recur_Common.pm, FS/t/cdr_termination.t,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/view/cust_main/billing.html: start of settlement CDR
+ processing, RT#5495
+
+2009-06-30 22:34 ivan
+
+ * FS/FS/part_event/Action/cust_bill_fee_percent.pm,
+ FS/FS/part_event/Action/fee.pm,
+ httemplate/elements/select-taxclass.html,
+ httemplate/elements/tr-select-taxclass.html: add tax class
+ selection back for late charges w/1.9 events, RT#5665
+
+2009-06-30 13:18 jeff
+
+ * FS/FS.pm, httemplate/elements/menu.html: documentation
+ corrections
+
+2009-06-30 12:38 ivan
+
+ * FS/FS/Schema.pm, FS/FS/part_pkg_taxclass.pm,
+ httemplate/browse/part_pkg_taxclass.html,
+ httemplate/edit/part_pkg_taxclass.html,
+ httemplate/edit/process/part_pkg_taxclass.html,
+ httemplate/elements/menu.html,
+ httemplate/elements/select-taxclass.html,
+ httemplate/elements/tr-select-taxclass.html: disabling a
+ taxclass, RT#5472
+
+2009-06-30 05:32 ivan
+
+ * httemplate/edit/quick-charge.html: remove debugging
+
+2009-06-30 05:28 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/quick-charge.html,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/view/cust_main/packages/status.html,
+ FS/FS/Cron/bill.pm, httemplate/edit/process/quick-charge.cgi:
+ one-time charge "hold for later" / any package future start date,
+ RT#5347
+
+2009-06-30 04:09 ivan
+
+ * FS/FS/part_export/netsapiens.pm: this will help
+
+2009-06-30 02:38 ivan
+
+ * FS/FS/: phone_device.pm, part_export/netsapiens.pm: more steps to
+ netsapiens export, RT#5226
+
+2009-06-29 19:54 ivan
+
+ * FS/FS/part_export/netsapiens.pm: add DID association w/user?
+ docs from netsapiens rough... RT#5226
+
+2009-06-29 18:42 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Mason.pm, FS/FS/Schema.pm,
+ FS/FS/part_device.pm, FS/FS/phone_device.pm, FS/FS/svc_phone.pm,
+ FS/t/part_device.t, FS/t/phone_device.t,
+ httemplate/browse/part_device.html,
+ httemplate/edit/part_device.html,
+ httemplate/edit/phone_device.html,
+ httemplate/edit/process/part_device.html,
+ httemplate/edit/process/phone_device.html,
+ httemplate/misc/delete-phone_device.html,
+ httemplate/misc/part_device-import.html,
+ httemplate/elements/menu.html,
+ httemplate/misc/process/part_device-import.html,
+ httemplate/view/svc_phone.cgi: phone devices (for netsapiens
+ integration), RT#5226
+
+2009-06-29 15:48 rsiddall
+
+ * rpm/freeside.spec: Fix PDF invoice generation, including
+ requirement for ghostscript.
+
+2009-06-29 07:45 jeff
+
+ * bin/cust_pay_histogram: show total number of payments
+
+2009-06-29 06:55 jeff
+
+ * bin/cust_pay_histogram: commandline tool for examining cust_pay
+ records by date range #5652
+
+2009-06-29 06:53 jeff
+
+ * FS/FS/part_pkg_report_option.pm, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ FS/t/part_pkg_report_option.t, FS/FS.pm, FS/MANIFEST,
+ httemplate/browse/part_pkg_report_option.html,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_pkg_report_option.html,
+ httemplate/edit/cust_main/bottomfixup.html,
+ httemplate/edit/cust_main/bottomfixup.js,
+ httemplate/edit/cust_main/choose_tax_location.html,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/part_pkg_report_option.html,
+ httemplate/misc/xmlhttp-cust_main-censustract.html,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/elements/location.html, httemplate/elements/menu.html,
+ httemplate/search/cust_main.html,
+ httemplate/search/report_cust_main.html,
+ httemplate/search/report_cust_pkg.html: FCC form 477 reporting
+ #4912
+
+2009-06-28 23:21 ivan
+
+ * FS/MANIFEST: remove freeside-expiration-alerter
+
+2009-06-26 17:55 ivan
+
+ * FS/bin/freeside-expiration-alerter: replaced by
+ FS::Cron::alert_expiration
+
+2009-06-26 16:21 ivan
+
+ * FS/bin/freeside-queued: doh, brainfart, RT#5572
+
+2009-06-26 16:12 ivan
+
+ * FS/bin/freeside-queued: add -s and -n flags to freeside-daily to
+ specify the kinds of jobs to be run, RT#5572
+
+2009-06-26 11:53 ivan
+
+ * FS/FS/cust_main.pm: in smart_search, move duplicate elimination
+ bits so that they're used even when doing an exact search on a
+ browser-remembered result
+
+2009-06-25 23:55 mark
+
+ * FS/: FS/Conf.pm, bin/freeside-daily: Add expiration alerts to
+ freeside-daily routine
+
+2009-06-25 13:23 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: finish fixing "Real time processing
+ not enabled!" error when using signup without any real-time
+ processor
+
+2009-06-25 12:55 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: eliminate harmless warning log spam:
+ Argument "" isn't numeric in numeric eq (==) at
+ /usr/local/share/perl/5.8.8/FS/ClientAPI/Signup.pm line 57
+
+2009-06-25 12:47 ivan
+
+ * FS/FS/: agent.pm, ClientAPI/Signup.pm: fix signups for the
+ no-gateway-at-all case, RT#5673
+
+2009-06-25 12:06 ivan
+
+ * httemplate/search/cust_tax_adjustment.html: fix tax adjustment
+ report
+
+2009-06-24 18:28 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/AccessRight.pm, FS/FS/Conf.pm,
+ FS/FS/Schema.pm, FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_tax_adjustment.pm,
+ FS/t/cust_tax_adjustment.t,
+ httemplate/edit/cust_tax_adjustment.html,
+ httemplate/edit/process/cust_tax_adjustment.html,
+ httemplate/search/cust_tax_adjustment.html,
+ httemplate/view/cust_main/payment_history.html: tax adjustments,
+ RT#5595
+
+2009-06-24 18:22 ivan
+
+ * httemplate/view/cust_main/one_time_charge_link.html: fix extra
+ whitespace in IE
+
+2009-06-24 11:36 ivan
+
+ * init.d/freeside-init, FS/bin/freeside-queued: add support for db
+ profiling, RT#5662
+
+2009-06-24 02:07 mark
+
+ * FS/: FS/Cron/alert_expiration.pm, bin/freeside-daily: Move
+ expiration alerts into FS::Cron::alert_expiration
+
+2009-06-23 21:42 ivan
+
+ * FS/FS/part_pkg.pm: fix upgrade issue w/ black part_pkg.comment,
+ RT#3988
+
+2009-06-23 18:40 ivan
+
+ * httemplate/graph/cust_bill_pkg.cgi: fix total links on
+ agent-specific sales report, RT#5449
+
+2009-06-23 13:33 rsiddall
+
+ * httemplate/view/svc_domain.cgi: Remove ability to renew domain
+ registration for more than one year as we can't automatically
+ bill for multi-year renewals at this time.
+
+2009-06-22 16:42 ivan
+
+ * FS/FS/cust_pay.pm: fix using encryption produces non-decrypted
+ data in payment receipts, RT#5536
+
+2009-06-22 15:55 ivan
+
+ * FS/FS/Mason.pm, httemplate/search/cust_main.html: fix advanced
+ customer report failure, RT#5515
+
+2009-06-22 10:00 jeff
+
+ * FS/FS/cust_main.pm: wtf? the tax applies but it doesn't? RT#5574
+
+2009-06-22 03:45 ivan
+
+ * FS/FS/part_pkg.pm: eliminate harmless upgrade error: Argument ""
+ isn't numeric in numeric eq (==) at
+ /usr/local/share/perl/5.8.8/FS/part_pkg.pm line 371.
+
+2009-06-22 03:39 ivan
+
+ * FS/FS/access_user.pm: fix pod
+
+2009-06-22 03:28 ivan
+
+ * FS/FS/part_pkg.pm: fix setup/recur -> setup_fee/recur_fee upgrade
+
+2009-06-22 03:06 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_tax.cgi: finish basic implemention of
+ tax exemption by tax name hack, RT#5127
+
+2009-06-22 00:50 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_exemption.pm,
+ FS/t/cust_main_exemption.t,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/view/cust_main/billing.html: tax exemption by tax
+ name, RT#5127
+
+2009-06-21 15:00 ivan
+
+ * FS/FS/part_pkg/agent.pm: eliminate leaky debugging and a warning
+ about it
+
+2009-06-21 08:42 jeff
+
+ * FS/FS/part_export/: www_plesk.pm, acct_plesk.pm: link to docs
+ #5855
+
+2009-06-21 08:21 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_pkg.pm, FS/FS/part_pkg.pm,
+ httemplate/browse/agent_type.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/agent_type.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/reg_code.cgi,
+ httemplate/edit/cust_main/first_pkg/select-part_pkg.html,
+ httemplate/misc/bulk_change_pkg.cgi,
+ httemplate/misc/cancel_pkg.html,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/delay_susp_pkg.html,
+ httemplate/misc/meta-import.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/reg_code.html,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/view/cust_main/packages/package.html,
+ httemplate/view/cust_main/packages/status.html: CUSTOM
+ packages/actual flag for custom packages #3988
+
+2009-06-19 14:49 jeff
+
+ * FS/FS/: cust_bill_pkg_detail.pm, tax_rate.pm: support some older
+ Pg when upgrading tax rates and cust_bill_pkg_details
+
+2009-06-19 10:53 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/verify.cgi: treat webpay type
+ payments as manual
+
+2009-06-19 05:08 ivan
+
+ * FS/FS/part_pkg/agent.pm: fix the prorating for the package's
+ first month (whew!) add an option not to prorate the accounts
+ themselves
+
+2009-06-19 00:46 ivan
+
+ * FS/FS/cust_main.pm: AND helps alot, RT#5572 for real
+
+2009-06-19 00:14 ivan
+
+ * FS/FS/cust_main.pm: attempt to optimize the easy parts of billing
+ run, RT#18737
+
+2009-06-18 04:09 ivan
+
+ * FS/FS/part_pkg/agent.pm: omit listing spurious customer details
+
+2009-06-18 04:07 ivan
+
+ * FS/FS/part_pkg/bulk.pm: bulk price plan fix - don't omit setup
+ fee
+
+2009-06-18 04:04 ivan
+
+ * FS/FS/part_pkg/agent.pm: add agent wholsale price plan, RT#4696
+
+2009-06-18 04:03 ivan
+
+ * FS/FS/Schema.pm, FS/FS/part_pkg.pm, httemplate/edit/part_pkg.cgi:
+ add basic part_pkg cost columns for agent wholsale price plan,
+ RT#4696
+
+2009-06-18 03:07 ivan
+
+ * FS/FS/cust_main.pm: uuh, don't bomb out if there *isn't* a postal
+ fee package
+
+2009-06-18 02:52 ivan
+
+ * httemplate/images/gray-black-side.png: forgot this
+
+2009-06-17 18:17 mark
+
+ * httemplate/: elements/menu.html, search/report_receivables.cgi,
+ search/report_receivables.html: Fix receivables report ACL checks
+ and menu
+
+2009-06-16 23:43 mark
+
+ * FS/FS/AccessRight.pm, httemplate/elements/menu.html,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/report_receivables.html: Added separate access
+ right for receivables report
+
+2009-06-16 19:39 ivan
+
+ * FS/FS/Conf.pm, FS/FS/access_user.pm,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/elements/menubar.html,
+ httemplate/misc/process/link.cgi, httemplate/pref/pref.html,
+ httemplate/search/cust_event.html,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/view/cust_main.cgi: finish up initial work on customer
+ view tabs (ensure links back to customer view call include
+ show=packages if default view isn't jumbo or packages already),
+ RT#5586
+
+2009-06-15 20:29 ivan
+
+ * httemplate/: elements/menubar.html, pref/pref-process.html,
+ pref/pref.html, view/cust_main.cgi, view/cust_main/packages.html,
+ view/cust_main/payment_history.html, view/cust_main/tickets.html:
+ basic customer view tabs, RT#5586
+
+2009-06-15 14:41 rsiddall
+
+ * FS/FS/AccessRight.pm, httemplate/view/svc_domain.cgi: Add a new
+ access right for managing domain registration (registering,
+ transferring, revoking, renewing, etc.).
+
+2009-06-15 13:43 jeff
+
+ * FS/FS/cust_main.pm: check for need for postal fee before charging
+ the customer, not after
+
+2009-06-15 12:41 rsiddall
+
+ * FS/FS/part_export/domreg_opensrs.pm,
+ httemplate/edit/process/domreg.cgi,
+ httemplate/view/svc_domain.cgi: Add domain registration
+ operations to the View Domain screen, if the domain has an
+ associated export supporting registration. Shows the domain
+ status and allows registration, transfer, revocation, or renewal.
+ Revocation almost never works since the registries impose very
+ short windows after initial registration. Also updated the
+ OpenSRS registration export to support the additional operations.
+
+2009-06-12 20:13 rsiddall
+
+ * rpm/freeside.spec: Default configuration files had
+ directory-style permission values.
+
+2009-06-11 19:48 rsiddall
+
+ * rpm/freeside.spec: Freeside no longer uses a datasource-specific
+ configuration folder. Configuration is kept in the RDBMS and
+ initialized from the default_conf folder. RT 5579.
+
+2009-06-10 16:30 jeff
+
+ * conf/invoice_latex: prevent notes from bleeding onto coupon
+ RT#5537
+
+2009-06-10 14:58 ivan
+
+ * FS/FS/: cust_bill.pm, cust_bill_pkg.pm: should hopefully fix old
+ services showing up on invoices, RT#5451/RT#5514/RT#5564/RT#3032
+
+2009-06-10 12:50 ivan
+
+ * FS/FS/Cron/bill.pm: don't add another queued_bill job to the
+ queue if there's already one waiting to run for a customer,
+ RT#5572
+
+2009-06-10 00:58 ivan
+
+ * httemplate/search/cust_pkg.cgi: this should add the info s1 was
+ looking for, RT#5539
+
+2009-06-09 20:06 ivan
+
+ * FS/bin/freeside-upgrade: doh, semicolon
+
+2009-06-09 20:00 ivan
+
+ * FS/bin/freeside-upgrade: don't attempt to create h_queue indices,
+ for SG upgradability
+
+2009-06-09 19:08 ivan
+
+ * httemplate/edit/payment_gateway.html: update gateway list in
+ order to add WesternACH, RT#5409
+
+2009-06-09 17:02 ivan
+
+ * FS/FS/cust_main.pm: eliminate harmless
+
+ Argument "" isn't numeric in numeric comparison (<=>) at
+ /usr/local/share/perl/5.8.8/FS/cust_main.pm line 6759.
+
+ warning, sort batched payments on a column that actually exists
+
+2009-06-04 07:27 ivan
+
+ * httemplate/docs/credits.html: fix scrolling
+
+2009-06-04 07:09 ivan
+
+ * rpm/freeside.spec: there are lots of contributors too!
+
+2009-06-04 07:08 ivan
+
+ * httemplate/docs/credits.html: $core->add("jeremyd");
+
+2009-06-03 20:49 ivan
+
+ * bin/freeside-migrate-events: much more efficient event migration:
+ let the database do the work, RT#5426
+
+2009-06-03 17:49 ivan
+
+ * bin/freeside-migrate-events: add a -m mode to improve performance
+ so upgrade can complete for large databases, RT#5426
+
+2009-06-03 14:09 rsiddall
+
+ * rpm/freeside.spec: Incorrect permissions on the default
+ configuration folder caused installation to fail with an
+ incomplete database initialization. Failure to remove the
+ ticket_system file from the default configuration folder caused
+ Freeside to try to use RT.
+
+2009-06-03 12:52 ivan
+
+ * FS/FS/UID.pm: add a hack to set default schema, cf.
+ http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration:PostgreSQL_Schema
+
+2009-05-31 22:43 jeff
+
+ * FS/FS/part_pkg_taxproduct.pm, FS/FS/tax_rate.pm,
+ httemplate/misc/tax-fetch_and_replace.cgi,
+ httemplate/misc/process/tax-fetch_and_replace.cgi: a 'start over'
+ function for the taxproduct based tax data loading
+
+2009-05-31 02:57 ivan
+
+ * FS/FS/cust_bill.pm: wtf
+
+2009-05-31 02:45 ivan
+
+ * FS/FS/cust_bill.pm: don't fallback to 'Payable upon receipt'
+ invoice terms anymore. or in other words, honor setting
+ 'invoice_default_terms' blank, like in 1.7. RT#5415
+
+2009-05-31 01:39 ivan
+
+ * httemplate/browse/part_pkg.cgi: add "hide one-time charges"
+ toggle, RT#5255
+
+2009-05-30 23:59 ivan
+
+ * httemplate/: browse/part_pkg.cgi, elements/select-table.html:
+ package definition browse/search, filter by package class,
+ RT#5255
+
+2009-05-30 22:15 ivan
+
+ * bin/cdr-netsapiens.import: start of netsapeins cdr import, will
+ finish up when can connect again, RT#5226
+
+2009-05-30 21:57 ivan
+
+ * FS/FS/part_export/netsapiens.pm: necessary for
+ bin/cdr-netsapeins.import
+
+2009-05-30 05:15 ivan
+
+ * FS/FS/Schema.pm: very long transnexus filenames, RT#5229
+
+2009-05-30 04:21 ivan
+
+ * FS/FS/cdr/transnexus.pm: clid is base-64 encoded, huh, RT#5229
+
+2009-05-30 04:14 ivan
+
+ * bin/cdr-transnexus.import: quick hacked-up copy of
+ freeside-cdr-sftp_and_import for transnexus directory structure,
+ RT#5229
+
+2009-05-30 03:45 ivan
+
+ * FS/FS/: cdr.pm, cdr/transnexus.pm: add transnexus format, RT#5229
+
+2009-05-29 20:40 ivan
+
+ * FS/FS/part_pkg/prepaid.pm: and enable overlimit_action, RT#4995
+
+2009-05-29 20:14 ivan
+
+ * FS/FS/: svc_acct.pm, part_pkg/flat.pm, part_pkg/prepaid.pm: add
+ ability for prepaid packages to have usage limits and cancel if
+ they're hit, RT#4995
+
+2009-05-29 19:31 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: require svc_acct-usage_threshold to
+ be set explicitly, don't default to 80%
+
+2009-05-29 16:36 ivan
+
+ * httemplate/search/cdr.html: slightly better labels and field
+ order for CDR report, RT#4081
+
+2009-05-29 16:17 ivan
+
+ * FS/FS/: Conf.pm, cdr.pm, cdr/netcentrex.pm: fixup pivot code
+ handling in netcentrex CDR handling, RT#4081
+
+2009-05-28 21:43 jeff
+
+ * FS/FS/Conf.pm: correct description to reflect previous changes
+
+2009-05-28 17:22 jeff
+
+ * httemplate/edit/: quick-charge.html, process/quick-charge.cgi:
+ don't require a leading 0 in the quick charge amount
+
+2009-05-27 15:32 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: and multiple taxlcasses. i
+ think that should actually do it for now on RT#5446
+
+2009-05-27 15:23 ivan
+
+ * httemplate/search/report_tax.cgi: and the "tax invoiced" link
+ too! woo, working, RT#5446
+
+2009-05-27 15:13 ivan
+
+ * httemplate/search/: cust_bill_pkg.cgi: maybe this willf inally
+ fix total line links on tax report when using report_group
+ kludge? (still possibly not in all corner cases), RT#5446
+
+2009-05-27 15:10 ivan
+
+ * httemplate/search/: cust_bill_pkg.cgi, report_tax.cgi: maybe this
+ willf inally fix total line links on tax report when using
+ report_group kludge? (still possibly not in all corner cases),
+ RT#5446
+
+2009-05-27 14:35 ivan
+
+ * httemplate/search/report_tax.cgi: fix total line links on tax
+ report when using report_group kludge? (possibly not in all
+ corner cases), RT#5446
+
+2009-05-27 14:27 ivan
+
+ * httemplate/search/report_tax.cgi: fix total line links on tax
+ report when using report_group kludge? (possibly not in all
+ corner cases), RT#5446
+
+2009-05-27 14:24 jeff
+
+ * httemplate/elements/menuarrow.gif: close ticket 1517
+
+2009-05-27 10:18 ivan
+
+ * httemplate/search/: cust_bill_pkg.cgi, report_tax.cgi: fix total
+ line links on tax report when using report_group kludge?
+ (possibly not in all corner cases), RT#5446
+
+2009-05-27 00:50 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_recon.pm, FS/MANIFEST, FS/FS/cust_pkg.pm,
+ FS/FS/svc_acct.pm, FS/FS/ClientAPI/Bulk.pm,
+ FS/FS/part_pkg/voip_cdr.pm, FS/bin/freeside-selfservice-server,
+ FS/t/cust_recon.t, fs_selfservice/FS-SelfService/MANIFEST,
+ fs_selfservice/FS-SelfService/Makefile.PL,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd,
+ fs_selfservice/FS-SelfService/freeside-selfservice-soap-server,
+ fs_selfservice/FS-SelfService/iZoomOnlineProvisionService.pm:
+ bulk provisioning via ftp and SOAP #5202
+
+2009-05-26 05:32 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/: overlibmws.js,
+ overlibmws_crossframe.js, overlibmws_draggable.js,
+ overlibmws_iframe.js, iframecontentmws.js: include overlib in
+ selfservice
+
+2009-05-25 19:48 ivan
+
+ * httemplate/search/report_tax.cgi: and also fix "tax invoiced"
+ portion of total line when using config option for some basic tax
+ grouping by name, RT#5446
+
+2009-05-25 19:03 ivan
+
+ * httemplate/search/report_tax.cgi: mostly fix total line when
+ using config option for some basic tax grouping by name, RT#5446
+
+2009-05-25 18:41 ivan
+
+ * httemplate/search/: report_tax.html, report_tax.cgi: add a config
+ option for some basic tax grouping by name, RT#5446
+
+2009-05-25 18:35 ivan
+
+ * FS/FS/Conf.pm, httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html: add a config option for some
+ basic tax grouping by name, RT#5446
+
+2009-05-25 15:42 ivan
+
+ * httemplate/graph/cust_bill_pkg.cgi: fix total links on sales
+ graph when a package class is specified, RT#5449
+
+2009-05-24 20:59 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: international
+ self-service payments, RT#1592
+
+2009-05-24 18:49 ivan
+
+ * FS/FS/ClientAPI/MasonComponent.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/card.html,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/misc/counties.cgi,
+ fs_selfservice/FS-SelfService/cgi/misc/states.cgi,
+ httemplate/elements/location.html,
+ httemplate/elements/select-county.html: international
+ self-service payments, RT#1592
+
+2009-05-21 20:22 ivan
+
+ * FS/bin/freeside-upgrade: commit before sqlradius upgrade so
+ sqlradius upgrade errors from permissions can be ignored for now
+
+2009-05-21 20:02 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/search/report_cust_pkg.html: add
+ ability to report on packages w/status "not yet billed" as well,
+ RT#5409
+
+2009-05-20 08:27 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/packages/services.html: add "manage
+ device" link & config, RT#5438
+
+2009-05-20 01:27 ivan
+
+ * FS/FS/part_export/netsapiens.pm: get subscriber deletion working
+ and remove devel cruft, RT#5226
+
+2009-05-19 18:06 ivan
+
+ * FS/FS/part_export/netsapiens.pm: first pass at netsapiens
+ integration, RT#5226
+
+2009-05-18 12:23 jeff
+
+ * FS/FS/tax_rate_location.pm: miss use
+
+2009-05-18 12:21 jeff
+
+ * FS/FS/Schema.pm: allow empty state
+
+2009-05-18 11:21 jeff
+
+ * FS/bin/freeside-upgrade: prevent death on meritless sqlradius
+ upgrade attempts
+
+2009-05-18 02:55 ivan
+
+ * FS/FS/cust_svc.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/UI/bytecount.pm,
+ fs_selfservice/FS-SelfService/cgi/header.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_cdr_details.html,
+ fs_selfservice/FS-SelfService/cgi/view_usage.html,
+ fs_selfservice/FS-SelfService/SelfService.pm: basic CDR viewing
+ from self-service, RT#4018
+
+2009-05-18 01:40 ivan
+
+ * FS/bin/freeside-cdr-sftp_and_import: it would help to use the
+ correct port, RT#4081
+
+2009-05-17 21:56 jeff
+
+ * FS/FS/: part_pkg_taxrate.pm, tax_rate.pm: handle dates before
+ 1970
+
+2009-05-16 13:07 rsiddall
+
+ * FS/FS/part_export/domreg_opensrs.pm: Added information on common
+ failure causes to the perldoc.
+
+2009-05-16 12:27 rsiddall
+
+ * FS/FS/part_export/domreg_opensrs.pm: Defer use of Net::OpenSRS so
+ that failure to install the module doesn't stop Apache from
+ starting. (This causes attempts to register domains to fail
+ instead.)
+
+2009-05-15 19:29 rsiddall
+
+ * FS/FS/part_export/domreg_opensrs.pm: Provide better diagnostics
+ when the cust_main owning this domain does not provide fields
+ required for use as a contact handle in the domain registration
+ record. Also temporarily disable the ability to have the export
+ do only registration or only transfers.
+
+2009-05-15 12:41 rsiddall
+
+ * FS/FS/svc_domain.pm, FS/FS/part_export/domreg_opensrs.pm,
+ httemplate/edit/part_export.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/process/part_export.cgi,
+ httemplate/edit/process/svc_domain.cgi: Simple domain
+ registration at Tucows OpenSRS using an export based on
+ Net::OpenSRS. When a domain is added and the export runs, it
+ will register the domain or initiate a transfer. You can also
+ choose no action. There's currently no provision for revoking
+ domains or renewing registrations. Depending on the settings at
+ OpenSRS, orders may look like they've succeeded in Freeside but
+ actually be queued pending input by the reseller at OpenSRS. The
+ part_export CGIs were modified to allow a multi-valued select to
+ be used to control which TLDs are enabled for registration.
+
+2009-05-14 09:26 jeff
+
+ * httemplate/edit/cust_main/bottomfixup.js: ask for help assignting
+ geocode more often
+
+2009-05-14 09:25 jeff
+
+ * httemplate/view/cust_main/billing.html: show geocode when
+ taxproducts enabled
+
+2009-05-13 15:27 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_bill_pkg_tax_rate_location.pm, FS/FS/cust_main.pm,
+ FS/FS/tax_rate_location.pm, FS/MANIFEST, FS/FS/tax_rate.pm,
+ FS/t/cust_bill_pkg_tax_rate_location.t, FS/t/tax_rate_location.t,
+ bin/tax_rate_location.import, httemplate/misc/tax-import.cgi,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_newtax.cgi: improved taxproduct tax
+ report RT#4783
+
+2009-05-12 17:51 ivan
+
+ * conf/invoice_latex: remove obsolete comments
+
+2009-05-09 17:45 ivan
+
+ * FS/FS/svc_phone.pm: label phone_name correctly
+
+2009-05-09 16:54 ivan
+
+ * FS/bin/freeside-cdr-sftp_and_import, bin/cdr.sftp_and_import:
+ move cdr-sftp_and_import script to FS/bin, add -p option, RT#4081
+
+2009-05-09 00:56 ivan
+
+ * FS/FS/: Conf.pm, cdr.pm: add
+ cdr-charged_party-truncate_{length,prefix} in order to trim
+ charged_party to a certain length, RT#4081
+
+2009-05-08 18:44 ivan
+
+ * httemplate/: edit/elements/svc_Common.html,
+ edit/elements/edit.html, view/elements/svc_Common.html: use
+ service-def specific labels, at least for service pages that use
+ {view,edit}/elements/svc_Common.html RT#4081
+
+2009-05-08 17:39 ivan
+
+ * FS/FS/Schema.pm, FS/FS/part_svc.pm, FS/FS/part_svc_column.pm,
+ FS/FS/svc_acct.pm, httemplate/browse/part_svc.cgi,
+ httemplate/edit/part_svc.cgi: add ability to configure service
+ labels per-package (still need to actually use the labels),
+ RT#4081
+
+2009-05-08 01:41 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix cloning of custom packages
+ where you've changed '(CUSTOM)', RT#5350
+
+2009-05-05 15:02 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/agent.cgi: hide
+ agent.invoice_template edit by default, with a config to turn
+ back on, RT#5218
+
+2009-05-05 10:58 ivan
+
+ * FS/FS/cust_pay.pm: add company_name to payment receipt
+
+2009-05-05 03:40 ivan
+
+ * FS/FS/rate_detail.pm, httemplate/elements/file-upload.html,
+ httemplate/misc/rate_edit_excel.html,
+ httemplate/misc/process/rate_edit_excel.html: finish the import
+ portion of excel rate edit, RT#5108
+
+2009-05-04 18:41 jeff
+
+ * bin/cust_main_special.pm: ignore fee based taxes and eliminate
+ unused code
+
+2009-05-04 11:33 jeff
+
+ * bin/: cust_main_special.pm, rebill: this is a quick hack to
+ rebill customers when a cdr didn't happen
+
+2009-05-03 19:01 ivan
+
+ * httemplate/search/: report_prepaid_income.cgi,
+ report_prepaid_income.html: agent-virt prepaid income report,
+ RT#5311
+
+2009-05-03 18:17 ivan
+
+ * FS/FS/svc_acct.pm: eliminate Argument "" isn't numeric in
+ addition (+) warning
+
+2009-05-03 17:22 ivan
+
+ * httemplate/: browse/rate_region.html, elements/menu.html,
+ misc/rate_edit_excel.html, search/elements/search-xls.html,
+ search/elements/search.html: add menu item and page for d/ling
+ and edit rates with excel. RT#5108
+
+2009-05-03 15:45 ivan
+
+ * httemplate/search/elements/: search-csv.html, search-html.html,
+ search-xls.html, search.html: break down search.html into
+ components, RT#5108
+
+2009-05-03 11:34 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/search/cust_pay_batch.cgi: add
+ "Redownload resolved batches" ACL for s1, RT#4271
+
+2009-05-02 20:13 ivan
+
+ * httemplate/config/config.cgi: edit any config item
+
+2009-05-02 18:45 ivan
+
+ * httemplate/config/config-view.cgi: add ability to delete
+ invoice_latexreturnaddress and invoice_htmlreturnaddress too,
+ RT#5218
+
+2009-05-02 18:11 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-delete.cgi,
+ httemplate/config/config-view.cgi: add ability to remove
+ suffix-ed config items, RT#5218
+
+2009-05-02 17:40 ivan
+
+ * bin/confdiff: confdiff
+
+2009-05-02 15:11 ivan
+
+ * FS/FS/Misc/eps2png.pm: fix eps preview
+
+2009-05-01 17:01 ivan
+
+ * httemplate/: browse/agent.cgi, config/config-delete.cgi,
+ config/config-process.cgi, config/config-view.cgi: finish up
+ useful agent stuff on the config editor: adding, deleting
+ overrides too. also add a confirmation to override deletion from
+ the agent browse page. RT#5218
+
+2009-05-01 13:21 jeff
+
+ * FS/FS/cust_main.pm: calculate tax on tax per line and not on
+ aggregate
+
+2009-04-30 19:43 ivan
+
+ * httemplate/config/config-view.cgi: view all overrides when asked,
+ even the ones without values. hmm :/ RT#5218
+
+2009-04-30 19:08 ivan
+
+ * FS/FS/cust_event.pm: fix re-print/email from event page, yow.
+ RT#5293
+
+2009-04-30 18:07 ivan
+
+ * httemplate/config/: config-process.cgi, config-view.cgi: add
+ ability to edit the agent overrides from the main config, RT#4218
+
+2009-04-29 11:25 ivan
+
+ * httemplate/edit/svc_www.cgi: fix inadvertant select box, RT#5277
+
+2009-04-28 15:38 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/bill.html: UI
+
+2009-04-27 21:36 ivan
+
+ * FS/FS/cust_main.pm: add cancelled_cust-noevents flag to emulate
+ SG billing-daily -r behavior, RT#4412
+
+2009-04-27 21:13 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: add cancelled_cust-noevents flag
+ to emulate SG billing-daily -r behavior
+
+2009-04-27 16:06 ivan
+
+ * FS/FS/Mason.pm: typo
+
+2009-04-27 16:01 ivan
+
+ * FS/FS/Mason.pm: refuse to run w/CGI.pm 3.38. all lenny upgrades
+ will need libcgi-pm-perl removed, suck
+
+2009-04-26 16:43 ivan
+
+ * FS/FS/Schema.pm: would help to have an index on priority if we're
+ going to order based on it
+
+2009-04-26 16:19 ivan
+
+ * FS/bin/freeside-queued: start small jobs more efficiently,
+ RT#4412
+
+2009-04-26 16:09 ivan
+
+ * FS/FS/Conf.pm: add a config option for max # of queued kids,
+ RT#4412
+
+2009-04-25 15:42 ivan
+
+ * FS/: FS/Cron/bill.pm, bin/freeside-daily: add dry run to
+ multi-process mode for testing, RT#4412
+
+2009-04-23 13:34 jeff
+
+ * FS/FS/: Upgrade.pm, part_pkg_option.pm, part_pkg/voip_cdr.pm: add
+ subscription option to voip_cdr
+
+2009-04-23 13:31 jeff
+
+ * httemplate/misc/tax-fetch_and_import.cgi,
+ httemplate/misc/process/tax-fetch_and_import.cgi, FS/FS/Conf.pm,
+ FS/FS/cust_tax_location.pm, FS/FS/part_pkg_taxrate.pm,
+ FS/FS/tax_class.pm, FS/FS/tax_rate.pm,
+ httemplate/elements/menu.html: autodownload and update of cch tax
+ data
+
+2009-04-22 21:57 ivan
+
+ * FS/FS/Cron/bill.pm: we don't actually need the results ordered,
+ and i'm sure it doesn't help the planner get us results sooner.
+ last chance to try and get cursor approach working? RT#4412
+
+2009-04-22 21:14 ivan
+
+ * FS/FS/Cron/bill.pm: does pg try to finish the query when the job
+ addition is committed? well, if this works, that answers that.
+ RT#4412
+
+2009-04-22 13:24 ivan
+
+ * FS/FS/Cron/bill.pm: hopefully better performance running the big
+ query once and then fetching results with a cursor, rather than
+ running it multiple times with an OFFSET and LIMIT, RT#4412
+
+2009-04-22 11:58 ivan
+
+ * httemplate/edit/process/cust_main.cgi: fix not allowing
+ "on-demand" card or ACH, RT#5238 RT#5237 RT#5230
+
+2009-04-21 23:52 ivan
+
+ * FS/FS/Cron/bill.pm: perhaps a happier medium, RT#4412
+
+2009-04-21 17:54 ivan
+
+ * FS/FS/Cron/bill.pm: have the big query find customers in batches.
+ this should be way more efficient in multi-process mode, can
+ start billing before the big query completes. RT#4412
+
+2009-04-21 13:59 ivan
+
+ * httemplate/browse/rate_region.html: rate download/edit/upload,
+ RT#5108
+
+2009-04-21 13:28 ivan
+
+ * httemplate/browse/rate_region.html: rate download/edit/upload,
+ RT#5108
+
+2009-04-21 09:42 ivan
+
+ * FS/FS/Cron/bill.pm: yow. fix fallout from cust_main.archived
+ stuff causing nothing to bill. RT#4412
+
+2009-04-20 19:23 jeff
+
+ * FS/FS/UI/Web.pm, httemplate/elements/progress-popup.html: more
+ descriptive progress popups
+
+2009-04-20 13:57 rsiddall
+
+ * rpm/freeside.spec: Acceptance testing of the RPM build system
+ flushed out a place where /bin/rm stops waiting for input if
+ you're /bin/su as the user doing the build. Added a -f flag to
+ stop it waiting for input.
+
+2009-04-20 09:57 ivan
+
+ * FS/FS/: Schema.pm, cust_main.pm, Cron/bill.pm: add
+ cust_main.archived field, skip billing if Y, RT#4412
+
+2009-04-19 16:55 ivan
+
+ * bin/h_cust_main-wipe_paycvv: no, it was only cause their db is
+ somehow corrupt
+
+2009-04-19 16:52 ivan
+
+ * bin/h_cust_main-wipe_paycvv: warning about this not terminating
+
+2009-04-17 16:30 ivan
+
+ * bin/: fs-migrate-cust_tax_exempt, h_cust_main-wipe_paycvv:
+ something to wipe the CVV from very large databases
+
+2009-04-17 12:50 ivan
+
+ * FS/: FS/Schema.pm, FS/Cron/bill.pm, bin/freeside-queued: add
+ priority to job queue so billing jobs don't don't drown out
+ provisioning jobs
+
+2009-04-17 12:21 ivan
+
+ * FS/FS/Cron/bill.pm: 1 helps alot
+
+2009-04-17 12:20 ivan
+
+ * FS/bin/freeside-daily: backport freeside-daily -m and
+ cust_main::bill_and_collect to 1.7, RT#4412
+
+2009-04-17 01:25 ivan
+
+ * httemplate/docs/about.html: AFFERO BITCHES
+
+2009-04-17 01:16 ivan
+
+ * httemplate/docs/about.html: what time is now
+
+2009-04-17 01:02 ivan
+
+ * httemplate/config/: config-process.cgi, config-view.cgi,
+ config.cgi: show labels for select(select_hash) config options,
+ RT#3997
+
+2009-04-17 00:21 ivan
+
+ * FS/FS/cust_bill.pm: add invoice number to PDF filename in email
+ attachments, RT#3403
+
+2009-04-17 00:03 ivan
+
+ * httemplate/elements/header.html,
+ rt/html/Elements/FreesideSvcSearch: hide service search unless
+ user has "View customer services" ACL, RT#3478
+
+2009-04-16 18:17 ivan
+
+ * httemplate/search/: report_receivables.cgi,
+ report_receivables.html: add customer status to receivables
+ report selection, hopefully help enet, RT#5187
+
+2009-04-15 20:57 rsiddall
+
+ * rpm/freeside.spec: More fixes for SuSE self-service: 1/ Put
+ binaries in the right folder 2/ Make sure freeside group is
+ created 3/ Make sure freeside home directory is created
+
+2009-04-15 00:14 ivan
+
+ * httemplate/view/: svc_Common.html, elements/svc_Common.html:
+ should fix view of unlinked phone numbers, RT#5171
+
+2009-04-14 22:52 ivan
+
+ * httemplate/view/svc_acct.cgi: s/GECOS/Real Name/ RT#3519
+
+2009-04-14 19:44 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix 1.7->1.9 upgrade glitch with
+ self-service where process_payment required "payby" instead of
+ defaulting to CARD, RT#3905
+
+2009-04-14 19:29 ivan
+
+ * FS/FS/cust_bill.pm: show 60 chars on typeset invoices but only 32
+ on plaintext, RT#3905
+
+2009-04-14 19:15 ivan
+
+ * FS/FS/cust_bill.pm: this should fix credits pushing typeset
+ invoices off the right
+
+2009-04-14 14:01 ivan
+
+ * httemplate/view/cust_main/packages.html: remove debugging
+
+2009-04-14 13:27 ivan
+
+ * httemplate/view/cust_main/packages.html: don't hide old packages
+ that have services, RT#5179
+
+2009-04-14 10:15 ivan
+
+ * FS/FS/: cust_main.pm, agent.pm: add configuration option to
+ control recurring_flag behavior, RT#3843
+
+2009-04-14 10:12 ivan
+
+ * FS/FS/: Conf.pm, Schema.pm: add configuration option to control
+ recurring_flag behavior, RT#3843
+
+2009-04-14 09:14 jeff
+
+ * httemplate/misc/process/tax-import.cgi: hmmm
+
+2009-04-14 09:12 jeff
+
+ * httemplate/misc/process/tax-import.cgi: better at least
+
+2009-04-13 17:09 ivan
+
+ * FS/FS/Conf.pm: add configuration option to control recurring_flag
+ behavior, RT#3843
+
+2009-04-13 16:37 ivan
+
+ * FS/FS/cust_main.pm: debugging
+
+2009-04-11 23:24 ivan
+
+ * httemplate/elements/tr-select-svc_acct-domain.html: adding
+
+2009-04-11 23:14 ivan
+
+ * httemplate/elements/selectlayers.html: add svc_phone on new
+ customer first package, RT#4315
+
+2009-04-11 23:09 ivan
+
+ * FS/FS/part_pkg.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/birthdate.html,
+ httemplate/edit/cust_main/bottomfixup.html,
+ httemplate/edit/cust_main/bottomfixup.js,
+ httemplate/edit/cust_main/first_pkg.html,
+ httemplate/edit/cust_main/top_misc.html,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_main/choose_tax_location.html,
+ httemplate/edit/cust_main/select-domain.html,
+ httemplate/edit/cust_main/first_pkg/select-part_pkg.html,
+ httemplate/edit/cust_main/first_pkg/svc_acct.html,
+ httemplate/edit/cust_main/first_pkg/svc_phone.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/elements/select-domain.html,
+ httemplate/misc/part_svc-columns.cgi,
+ httemplate/elements/select-svc_acct-domain.html: add svc_phone on
+ new customer first package, RT#4315
+
+2009-04-11 18:33 jeff
+
+ * etc/fslongtable.sty: sheesh
+
+2009-04-11 18:24 jeff
+
+ * Makefile, etc/fslongtable.sty, conf/invoice_latex: find and
+ correct the real double counting culprit
+
+2009-04-11 14:42 ivan
+
+ * FS/FS/part_event/Action/writeoff.pm, bin/freeside-migrate-events:
+ migrate send_email, suspend_if_balance and credit events, RT#3905
+
+2009-04-11 14:29 ivan
+
+ * FS/FS/part_event/Action/cust_bill_email.pm: add cust_bill_email
+ action
+
+2009-04-11 13:51 ivan
+
+ * FS/bin/freeside-upgrade: don't run configuration update when -s
+ is used for schema-only slony slave update
+
+2009-04-10 12:33 ivan
+
+ * FS/FS/Conf.pm: better description for enable_taxproducts and a
+ warning about tax-pkg_address with it
+
+2009-04-09 20:43 jeff
+
+ * FS/FS/cust_main.pm: orders of magnitude faster
+
+2009-04-09 15:51 jeff
+
+ * FS/FS/cdr/taqua.pm: used BillingNumber and not CallingPartyNumber
+ for non-toll-free calls
+
+2009-04-08 15:42 ivan
+
+ * FS/FS/cust_pkg.pm: fix 'agent X can't purchase pkgpart YY' error
+ w/agent packages, RT#5119
+
+2009-04-08 01:08 ivan
+
+ * FS/FS/Cron/check.pm: don't want to throw false positives, RT#5101
+
+2009-04-08 00:32 ivan
+
+ * FS/FS/: Record.pm, Upgrade.pm, cust_main.pm: eliminate all trace
+ of cvv from history records, RT#5093
+
+2009-04-07 18:13 ivan
+
+ * httemplate/misc/link.cgi: when linking a legacy phone number the
+ phone number could be typed in and not the service #. RT#3407
+
+2009-04-07 13:45 jeff
+
+ * FS/FS/: cdr.pm, cdr/taqua.pm: quick option to allow importing gmt
+ cdrs
+
+2009-04-07 11:20 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add a config to allow colon in
+ usernames, RT#5145
+
+2009-04-07 11:15 ivan
+
+ * FS/FS/svc_acct.pm: truncate long labels that are TOO long...
+ RT#3519
+
+2009-04-06 19:50 jeff
+
+ * FS/FS/cdr.pm: a tollfree regex that captures 88x and works with
+ +1
+
+2009-04-06 19:18 ivan
+
+ * FS/FS/cdr.pm: stop smoking crack
+
+2009-04-06 18:20 jeff
+
+ * FS/FS/: Record.pm, cdr.pm, cdr/taqua.pm, part_pkg/voip_cdr.pm:
+ correct taqua toll free handling and hasten cdr import (skip
+ uninteresting records)
+
+2009-04-06 16:19 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: better auto toll free regex
+
+2009-04-06 11:31 jeff
+
+ * FS/FS/cdr/taqua.pm: calltype 6 is international
+
+2009-04-05 17:52 jeff
+
+ * Makefile, etc/fslongtable.sty: stop doublecounting
+ extracouponspace but do not gratuitiously change existing
+ installs
+
+2009-04-05 16:18 jeff
+
+ * FS/FS/cust_main.pm: cleanup tax-pkg_location tax on tax fallout
+
+2009-04-04 09:22 jeff
+
+ * FS/FS/: Schema.pm, cust_bill_pkg_detail.pm: correct bad schema
+ bug in cust_bill_pkg_detail
+
+2009-04-03 09:57 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: add option for available rather than
+ provisioned svc_phones as unit count
+
+2009-04-02 13:22 jeff
+
+ * httemplate/edit/cust_main/billing.html: Net 20 as well
+
+2009-04-02 10:47 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: separate checkbox for enabling
+ prorate feature
+
+2009-04-02 08:46 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: prorating for the fixed recurring
+ portion of voip
+
+2009-04-02 07:56 jeff
+
+ * httemplate/edit/cust_main.cgi: obey tax-ship_address in 'manual'
+ geocoding
+
+2009-04-01 22:27 jeff
+
+ * FS/FS/part_pkg_taxrate.pm: noise reduction
+
+2009-04-01 19:36 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: more than you ever wanted to know
+ about rounding. http://en.wikipedia.org/wiki/Rounding RT#4666
+
+2009-04-01 17:14 ivan
+
+ * httemplate/browse/part_pkg.cgi: add some
+ (undocumented/unaccessable to web UI yet) options to package
+ browse to track down packages missing recurring fees
+
+2009-03-31 21:27 ivan
+
+ * FS/FS/cdr.pm: show post-granularity duration if available for all
+ export formats
+
+2009-03-31 20:51 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add options to skip CDRs under a
+ defined length and with specific lastapp
+
+2009-03-31 20:44 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add options to skip CDRs under a
+ defined length and with specific lastapp
+
+2009-03-31 12:51 ivan
+
+ * FS/FS/Cron/notify.pm: really fix notify for Pg 8.3
+
+2009-03-31 12:47 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: quiet warning: Argument "" isn't
+ numeric in numeric eq (==) at
+ /usr/local/share/perl/5.10.0/FS/part_pkg/voip_cdr.pm line 201
+
+2009-03-31 12:46 ivan
+
+ * FS/FS/Cron/notify.pm: fix impending billing notification for Pg
+ 8.3's more strict type checking
+
+2009-03-30 09:33 jeff
+
+ * FS/FS/cust_tax_location.pm: schema and module should agree on
+ column names
+
+2009-03-29 23:10 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ httemplate/view/cust_main/packages.html: okay. counts are needed
+ for the package sort, so push the embedded counting into
+ cust_main.pm. sure hope this does it. RT#5083
+
+2009-03-29 22:08 ivan
+
+ * FS/FS/cust_pkg.pm: and hopefully actually using the count will
+ finally do it, RT#5083
+
+2009-03-29 21:50 ivan
+
+ * FS/FS/cust_pkg.pm: and hopefully actually using the count will
+ finally do it, RT#5083
+
+2009-03-29 21:41 ivan
+
+ * httemplate/view/cust_main/packages.html: double doh! RT#5083
+
+2009-03-29 21:35 ivan
+
+ * httemplate/view/cust_main/packages.html: doh! underscore,
+ RT#5083
+
+2009-03-29 21:31 ivan
+
+ * httemplate/view/cust_main/packages.html: try not to search for
+ nothing in cust_svc so much, RT#5083
+
+2009-03-29 21:15 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/view/cust_main/packages.html: try
+ not to search for nothing in cust_svc so much, RT#5083
+
+2009-03-29 20:47 ivan
+
+ * FS/FS/cust_main.pm: didn't need this, but more future-proof,
+ RT#5083
+
+2009-03-29 20:12 ivan
+
+ * httemplate/view/cust_main/packages.html: really prevent separate
+ part_pkg query, RT#5083
+
+2009-03-29 18:39 ivan
+
+ * httemplate/view/cust_main/packages.html: doh, fix pkg display,
+ RT#5083
+
+2009-03-29 18:28 ivan
+
+ * httemplate/view/cust_main/packages.html: fix setup date display,
+ RT#5083
+
+2009-03-29 18:09 ivan
+
+ * httemplate/view/cust_main/packages.html: forget caching, instead
+ scoop up cust_pkg and part_pkg in one query, RT#5083
+
+2009-03-29 18:05 ivan
+
+ * FS/FS/cust_main.pm, httemplate/view/cust_main/packages.html:
+ forget caching, instead scoop up cust_pkg and part_pkg in one
+ query, RT#5083
+
+2009-03-29 17:32 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/view/cust_main/packages.html:
+ part_pkg caching should speedup display of lots of packages,
+ RT#5083
+
+2009-03-29 16:44 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main/packages.html: hide over
+ 2 (or configured) cancelled and one-time charge packages, RT#5083
+
+2009-03-29 04:56 ivan
+
+ * FS/FS/Schema.pm: index pkg_svc.quantity, RT#5083
+
+2009-03-29 04:52 ivan
+
+ * FS/FS/cust_pkg.pm: seems to benchmark faster, RT#5083
+
+2009-03-29 03:39 ivan
+
+ * httemplate/view/cust_main/packages/package.html: avoid looking up
+ part_pkg redundantly in the pkg loop, RT#5083
+
+2009-03-29 03:34 ivan
+
+ * httemplate/view/cust_main/packages/package.html: avoid looking up
+ package details redundantly in the pkg loop, RT#5083
+
+2009-03-29 03:17 ivan
+
+ * FS/FS/: Record.pm, cust_pkg.pm: add "extra_param" option to
+ qsearch for more realisitic profiling data, RT#5083
+
+2009-03-29 02:38 ivan
+
+ * httemplate/view/cust_main/: one_time_charge_link.html,
+ packages.html, packages/status.html: optimize customer view when
+ there's lots of packages; *really* avoid looking up any config
+ inside the package loop, RT#5083
+
+2009-03-28 15:59 ivan
+
+ * httemplate/elements/select-cust-part_pkg.html,
+ httemplate/elements/select-cust-pkg_class.html,
+ httemplate/elements/select-part_pkg.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-cust-part_pkg.html,
+ httemplate/elements/tr-selectmultiple-part_pkg.html,
+ FS/FS/Conf.pm, FS/FS/part_pkg.pm, httemplate/misc/change_pkg.cgi,
+ httemplate/misc/cust-part_pkg.cgi,
+ httemplate/misc/order_pkg.html: package selector, split by
+ package class, RT#5077
+
+2009-03-25 20:59 ivan
+
+ * FS/FS/svc_acct.pm: yow
+
+2009-03-25 20:53 ivan
+
+ * FS/FS/cust_main.pm: sort packages by label of first (primary)
+ service, RT#5041
+
+2009-03-25 02:36 ivan
+
+ * httemplate/pref/pref-process.html: throw a proper error message
+ instead of a mason error on pw chagne problems, RT#5073
+
+2009-03-25 02:36 ivan
+
+ * httemplate/pref/pref.html: we're defaulting to a top menu in 1.9
+
+2009-03-25 01:45 ivan
+
+ * FS/FS/cdr.pm: correct headers on accountcode_default CDR output,
+ RT#5042
+
+2009-03-24 02:42 ivan
+
+ * bin/countdeclines: quick tool for RT#3843
+
+2009-03-23 23:31 ivan
+
+ * FS/FS/Schema.pm: add indices for analyzing cc failures, RT#3843
+
+2009-03-23 19:36 ivan
+
+ * FS/FS/: part_pkg/bulk.pm, Record.pm, cust_bill.pm, cust_svc.pm,
+ h_cust_svc.pm, part_pkg.pm: bulk price plan: label as Name
+ <email>, supress extraneous service list, RT#3519
+
+2009-03-23 16:33 jeff
+
+ * FS/FS/cust_pkg.pm, FS/FS/svc_acct.pm, FS/FS/part_pkg/flat.pm,
+ httemplate/misc/process/recharge_svc.html: more DTRT with usage
+ on service transfer between packages and recharges RT #2884,
+ #5040 + #4995 fallout
+
+2009-03-23 15:45 ivan
+
+ * httemplate/edit/svc_acct.cgi: change label for svc_acct.finger
+ from GECOS to "Real Name", RT#3519
+
+2009-03-23 10:02 ivan
+
+ * FS/FS/: svc_Common.pm, svc_acct.pm, part_pkg/bulk.pm: add name
+ (svc_acct.finger) to bulk billing detail, RT#3519
+
+2009-03-21 20:33 ivan
+
+ * FS/FS/Cron/check.pm: 10 is too few, throwing false positives
+
+2009-03-21 19:47 ivan
+
+ * httemplate/misc/xmlhttp-cust_main-address_standardize.html: fix
+ usps address standardization when the zip returned has no zip+4,
+ RT#4882
+
+2009-03-21 16:37 ivan
+
+ * FS/bin/freeside-check: Locale::SubCountry warnings clogging up
+ cron output not useful
+
+2009-03-21 16:32 ivan
+
+ * FS/FS/Cron/check.pm: 403 forbidden is okay, at lest the server's
+ up
+
+2009-03-21 15:14 ivan
+
+ * Makefile, FS/FS/Cron/check.pm, FS/bin/freeside-check:
+ freeside-check local monitoring, RT#4610
+
+2009-03-19 19:14 ivan
+
+ * bin/ping: adding quick remote ping & alert script, RT#4610
+
+2009-03-18 08:11 jeff
+
+ * FS/FS/part_pkg_taxrate.pm: more error information
+
+2009-03-17 17:30 jeff
+
+ * FS/FS/svc_acct.pm, FS/FS/part_pkg/flat.pm,
+ httemplate/edit/part_svc.cgi: hide unused usage columns
+
+2009-03-17 15:02 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: add
+ payment_info_renew_info method to ClientAPI/MyAccount and
+ SG-equivalent previous_payment_info_renew_info to ClientAPI/SGNG
+
+2009-03-17 14:38 ivan
+
+ * FS/FS/ClientAPI/SGNG.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add
+ payment_info_renew_info method to ClientAPI/MyAccount and
+ SG-equivalent previous_payment_info_renew_info to ClientAPI/SGNG
+
+2009-03-17 13:41 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: add SG stuff
+
+2009-03-17 13:13 ivan
+
+ * FS/FS/Conf.pm: add a conf switch to enable sg multicust stuff,
+ since it could be dangerous
+
+2009-03-17 13:04 ivan
+
+ * FS/FS/Conf.pm: apacheip isn't actually deprecated yet
+
+2009-03-17 12:48 ivan
+
+ * FS/FS/ClientAPI/SGNG.pm: adding ClientAPI/SGNG.pm
+
+2009-03-17 09:06 jeff
+
+ * FS/FS/: Upgrade.pm, tax_rate.pm: column upgrade for tax_rate
+ RT#4903)
+
+2009-03-17 05:01 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm: agent-virt
+ invoice_*{notes,footer,smallfooter,coupon}, RT#5025
+
+2009-03-17 02:59 ivan
+
+ * FS/FS/Misc/eps2png.pm: less debugging
+
+2009-03-17 02:58 ivan
+
+ * httemplate/docs/credits.html, FS/FS/Conf.pm, FS/FS/Mason.pm,
+ FS/FS/Misc/eps2png.pm, httemplate/config/config-image.cgi,
+ httemplate/config/config-view.cgi, httemplate/docs/license.html:
+ add eps preview to config, for RT#5025
+
+2009-03-16 16:28 jeff
+
+ * FS/FS/Schema.pm: avoid the need for approximate comparisons
+ RT#4903
+
+2009-03-16 10:06 jeff
+
+ * FS/FS/Schema.pm, FS/FS/part_export/prizm.pm,
+ httemplate/edit/svc_broadband.cgi: have prizm use service data
+ rather than package data to select a profile RT#4853
+
+2009-03-16 08:52 jeff
+
+ * bin/make-pkg-fruit: a tool for migrating package elements to
+ services
+
+2009-03-16 01:08 jeff
+
+ * FS/FS/svc_broadband.pm: get the dup checking right
+
+2009-03-16 00:13 ivan
+
+ * httemplate/: misc/payment.cgi, misc/process/payment.cgi,
+ elements/location.html: allow country selection on credit card
+ entry, RT#4997
+
+2009-03-16 00:13 ivan
+
+ * htetc/: freeside-base1.99.conf, freeside-base1.conf,
+ freeside-base2.conf: eliminate black diamond arrows on iso-8859-1
+ chars in Locale::SubCountry states, RT#4997
+
+2009-03-15 23:22 ivan
+
+ * Makefile: 5.10! welcome to the future
+
+2009-03-15 22:54 ivan
+
+ * httemplate/view/svc_domain.cgi: fix custnum display on domain
+ view
+
+2009-03-15 21:21 jeff
+
+ * FS/FS/svc_broadband.pm: use part_svc_router
+
+2009-03-15 17:57 jeff
+
+ * FS/FS/svc_broadband.pm: comment change
+
+2009-03-15 15:44 ivan
+
+ * bin/svc_acct-recalculate_usage: adding quick usage resetting tool
+
+2009-03-15 15:33 ivan
+
+ * FS/FS/cust_svc.pm: don't throw 'Use of uninitialized value in
+ addition (+) at /usr/local/share/perl/5.8.8/FS/cust_svc.pm line
+ 626.' error when using attribute_since_sqlradacct
+
+2009-03-15 12:42 ivan
+
+ * FS/FS/cust_pkg_reason.pm: should give better performance if we
+ search for what we want instead of using a string match
+
+2009-03-15 03:46 ivan
+
+ * FS/FS/cust_main.pm: fix application of data fields from prepaid
+ cards in addition to time field
+
+2009-03-15 03:34 ivan
+
+ * httemplate/misc/process/recharge_svc.html: apply byte values from
+ prepaid cards as well as time value, RT#4995
+
+2009-03-15 03:30 ivan
+
+ * FS/FS/UI/bytecount.pm, httemplate/edit/prepay_credit.cgi: we're
+ not a disk drive manufacturer, don't use halfass base-10
+ megs/gigs
+
+2009-03-15 00:33 ivan
+
+ * FS/FS/cust_main.pm: cust_main::payment_info, for
+ ClientAPI::MyAccount
+
+2009-03-14 16:44 ivan
+
+ * FS/FS/cust_bill.pm: fix emailed logos to come from db config, not
+ old files, RT#3093 / RT#4963
+
+2009-03-13 11:22 jeff
+
+ * FS/FS/svc_broadband.pm: prevent more duplicate MACs from sneaking
+ in in the interim
+
+2009-03-11 03:03 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm: add previous_balance-summary_only
+ config, RT#4404
+
+2009-03-11 02:41 ivan
+
+ * FS/FS/cdr.pm: add cdr display with accountcode included, RT#4405
+
+2009-03-11 01:57 ivan
+
+ * bin/print-directory_assist: comma
+
+2009-03-11 01:46 ivan
+
+ * bin/print-directory_assist, etc/areacodes.txt: quick list of area
+ codes and a kludge to print DA numbers for all of them
+
+2009-03-10 09:14 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/change_pay.html,
+ fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html,
+ fs_selfservice/FS-SelfService/cgi/verify.cgi,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html, FS/FS/Conf.pm,
+ FS/FS/Schema.pm, FS/FS/agent.pm, FS/FS/cust_main.pm,
+ httemplate/elements/tr-textarea.html, FS/FS/cust_pay_pending.pm,
+ FS/FS/cust_pkg.pm, FS/FS/payby.pm, FS/FS/payment_gateway.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ httemplate/browse/payment_gateway.html,
+ httemplate/edit/payment_gateway.html,
+ httemplate/edit/process/payment_gateway.html: merge webpay
+ support in with autoselection of old realtime_bop and
+ realtime_refund_bop
+
+2009-03-08 17:15 ivan
+
+ * httemplate/misc/svc_acct-domains.cgi: mistake, its back
+
+2009-03-08 17:15 ivan
+
+ * httemplate/misc/svc_acct-domains.cgi: doh
+
+2009-03-03 17:47 ivan
+
+ * FS/FS/UID.pm: mpm-itk hack, commented-out for now
+
+2009-03-03 15:56 ivan
+
+ * FS/FS/UID.pm: show the euid/ruid when throwing the "Not running
+ uid freeside" error
+
+2009-03-03 15:41 ivan
+
+ * FS/FS/queue.pm: eliminate harmless "Odd number of elements in
+ hash assignment" warning
+
+2009-03-02 00:49 ivan
+
+ * FS/FS/: part_export/vitelity.pm, Schema.pm, phone_avail.pm:
+ preliminary vitelity export, RT#4868
+
+2009-03-01 20:58 ivan
+
+ * FS/: bin/freeside-cdrrewrited, FS/Conf.pm, FS/cdr.pm: option to
+ do charged_party rewriting in the cdrrewrited daemon, RT#4342
+
+2009-03-01 16:10 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.html: have perl
+ signup.html use selfserice skin config too: selfservice-head,
+ selfserfice-body_header, selfservice-body_footer,
+ selfservice-body_bgcolor, selfservice-box_bgcolor
+
+2009-02-28 10:27 ivan
+
+ * Makefile: avoid erroring out running install-perl-modules when
+ you have a pristine, un-updated CVS checkout
+
+2009-02-25 19:51 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.html: make signup for a
+ bit friendlier for BILL signups for testingm RT#4018
+
+2009-02-25 12:05 ivan
+
+ * bin/japan.pl: adding quick tool to change the "states" for japan
+
+2009-02-24 02:15 ivan
+
+ * FS/FS/Setup.pm: be quiet
+
+2009-02-24 02:09 ivan
+
+ * conf/report_template: more bootstrapping bs
+
+2009-02-24 02:06 ivan
+
+ * FS/FS/part_referral.pm: bootstrapping issues
+
+2009-02-24 02:00 ivan
+
+ * FS/FS/Setup.pm: bootstrapping issues, aaargh
+
+2009-02-24 01:58 ivan
+
+ * FS/FS/Setup.pm: bootstrapping issues, ugh
+
+2009-02-24 01:50 ivan
+
+ * FS/FS/part_pkg.pm, FS/bin/freeside-setup,
+ bin/freeside-create-initial-data: bootstrapping issues
+
+2009-02-24 01:41 ivan
+
+ * bin/freeside-create-initial-data: somehow rc install wound up
+ without any data
+
+2009-02-24 00:45 ivan
+
+ * FS/bin/freeside-cdrrewrited: exact match, RT#3196
+
+2009-02-24 00:41 ivan
+
+ * FS/bin/freeside-cdrrewrited, FS/FS/Schema.pm, FS/FS/cdr.pm,
+ init.d/freeside-init: rewrite CDRs for forwarded Asterisk calls
+ to be billable, RT#3196
+
+2009-02-23 15:52 ivan
+
+ * FS/FS/Conf.pm: fix 1.7 -> 1.9 config upgrade for new "image"
+ config type
+
+2009-02-22 13:11 ivan
+
+ * httemplate/view/svc_www.cgi: remove flailing ", RT#4902
+
+2009-02-22 13:08 ivan
+
+ * FS/: FS/Upgrade.pm, bin/freeside-upgrade: a better rough idea of
+ where freeside-upgrade spends time
+
+2009-02-22 12:42 ivan
+
+ * httemplate/edit/svc_www.cgi: fix apache config editing, doh,
+ RT#4902
+
+2009-02-22 12:12 ivan
+
+ * bin/apache.export: add exportnum to apache export files so they
+ all get preserved in the case where you're using multiple apache
+ exports to the same machine, RT#4901
+
+2009-02-22 11:46 ivan
+
+ * FS/: MANIFEST, FS/h_cust_pkg.pm, FS/h_cust_pkg_reason.pm,
+ t/h_cust_pkg.t, t/h_cust_pkg_reason.t, FS/cust_pkg_reason.pm: add
+ h_cust_pkg and h_cust_pkg_reason packages, RT#4896
+
+2009-02-22 02:58 ivan
+
+ * FS/FS/part_pkg/flat.pm: don't do a credit for unused time for
+ packages that don't have a last bill date. really. RT#4881
+
+2009-02-22 02:34 ivan
+
+ * FS/FS/cust_pkg.pm: this would seem to be right, but...?
+
+2009-02-22 00:41 ivan
+
+ * httemplate/browse/part_pkg.cgi, FS/FS/part_pkg.pm,
+ FS/FS/type_pkgs.pm: add agent type list to package def browse,
+ RT#4880
+
+2009-02-21 18:37 ivan
+
+ * httemplate/search/: cust_bill_pkg.cgi, report_tax.cgi: fix tax
+ report for more complex situations with counties and taxclasses,
+ make taxable line items clickable, RT#4878
+
+2009-02-21 16:19 ivan
+
+ * FS/FS/cust_pkg.pm: okay, so no_empty_county was on crack. but
+ this fixes up tax reports nicely. RT#4878
+
+2009-02-21 12:56 ivan
+
+ * FS/FS/cust_pkg.pm: hmm, add no_empty_county option to
+ location_sql search, for tax reports. RT#4878
+
+2009-02-21 12:14 ivan
+
+ * FS/FS/cust_pkg.pm: hmm, add no_empty_county option to
+ location_sql search, for tax reports. RT#4878
+
+2009-02-21 09:56 ivan
+
+ * bin/follow-tax-rename, FS/FS/cust_bill_pkg.pm: adding
+ follow-tax-rename tool (well, quick hack), RT#4878
+
+2009-02-20 20:28 ivan
+
+ * FS/FS/Record.pm: and for obj creation too
+
+2009-02-20 20:27 ivan
+
+ * FS/FS/Record.pm: it would help to actually finish
+ nowarn_classload kludge
+
+2009-02-20 20:23 ivan
+
+ * FS/FS/Record.pm: add nowarn_classload kludge
+
+2009-02-20 07:07 jeff
+
+ * httemplate/edit/cust_main.cgi: support a default tax location
+ outside us/ca with cch data and better handling of response from
+ USPS (RT 4857)
+
+2009-02-19 18:55 ivan
+
+ * FS/FS/access_user.pm: oops, adding multiple-rightname support
+ broke ACL caching, bringing it back should be a good perf win for
+ large customer views, whew. RT#4830
+
+2009-02-19 18:41 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main/packages/status.html:
+ disable display of auto-suspend dates unless enabled by config.
+ at least until it can be made more efficient. this is slowing
+ down customer view waaaaaaaaaay too much. RT#4830
+
+2009-02-19 18:22 ivan
+
+ * httemplate/autohandler: harmless tyop
+
+2009-02-19 05:38 jeff
+
+ * httemplate/edit/: cust_main.cgi,
+ cust_main/choose_tax_location.html: do not attempt to assign a
+ geocode to non us/ca addresses (RT 4857)
+
+2009-02-18 23:57 ivan
+
+ * httemplate/search/: elements/cust_pay_or_refund.html,
+ elements/search.html, cust_pay_pending.html: redirect pending
+ payment report back to customer when the pending payment is
+ resolved, RT#4837, and fix otaker fallout from the pending stuff,
+ RT#4866
+
+2009-02-18 22:42 ivan
+
+ * httemplate/: autohandler, pref/pref-process.html, pref/pref.html:
+ add profiling to a file OOM situations, RT#4830
+
+2009-02-18 17:50 ivan
+
+ * FS/FS/Record.pm: fix "improved" float searching problems, RT#4878
+
+2009-02-16 23:43 ivan
+
+ * httemplate/edit/part_pkg.cgi: kludge to clone customer packages
+ you otherwise couldn't see, RT#4854
+
+2009-02-16 23:40 ivan
+
+ * httemplate/edit/part_pkg.cgi: kludge to clone customer packages
+ you otherwise couldn't see, RT#4854
+
+2009-02-16 18:28 ivan
+
+ * FS/FS/Mason.pm, httemplate/autohandler,
+ httemplate/pref/pref-process.html, httemplate/pref/pref.html:
+ per-user preference for turning on profiling display when
+ DBIx::Profile is loaded, RT#4830
+
+2009-02-16 18:01 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/view/cust_main/packages.html: add tax-exempt checkbox
+ to one-time charges, RT#4858
+
+2009-02-16 15:54 ivan
+
+ * FS/FS/cust_pay_pending.pm, FS/FS/AccessRight.pm,
+ FS/FS/cust_main.pm, httemplate/search/cust_pay_pending.html,
+ httemplate/search/elements/cust_pay_or_refund.html,
+ httemplate/edit/cust_pay_pending.html,
+ httemplate/edit/process/cust_pay_pending.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/elements/menu.html: add reporting on (and resolution
+ of) stuck pending transactions, RT#4837 (RT#3572)
+
+2009-02-15 22:40 jeff
+
+ * bin/cch_tax_tool: a cheesy little tool to assist in syncing cch
+ updates to the initial install
+
+2009-02-15 22:02 jeff
+
+ * FS/FS/: cust_tax_location.pm, part_pkg_taxrate.pm, tax_class.pm:
+ allow completely empty updates (again?)
+
+2009-02-15 21:59 jeff
+
+ * FS/FS/cust_tax_location.pm: wrong operator
+
+2009-02-15 09:38 jeff
+
+ * FS/FS/tax_rate.pm: remove useless line
+
+2009-02-15 09:23 jeff
+
+ * FS/FS/tax_rate.pm: tyop
+
+2009-02-15 09:20 jeff
+
+ * FS/FS/tax_rate.pm: trim whitespace on import
+
+2009-02-15 05:51 jeff
+
+ * FS/FS/Record.pm: improved float searching
+
+2009-02-13 16:40 ivan
+
+ * httemplate/: elements/select-agent.html,
+ elements/tr-select-agent.html, browse/addr_block.cgi: clean up
+ select-agent agent virtualization, RT#1405
+
+2009-02-12 11:48 jeff
+
+ * FS/FS/: cust_tax_location.pm, tax_rate.pm: proper match arguments
+ help
+
+2009-02-12 07:55 jeff
+
+ * httemplate/: misc/tax-import.cgi, elements/form-file_upload.html:
+ better upload error handling and correction of tax upload
+ filecount
+
+2009-02-11 10:44 ivan
+
+ * httemplate/search/cdr.html: fix select and unselect all buttons
+ on CDR bulk actions, RT#4766
+
+2009-02-11 08:06 jeff
+
+ * FS/FS/Schema.pm: mac is unique
+
+2009-02-10 08:25 jeff
+
+ * httemplate/edit/part_pkg.cgi: fix taxproduct fallout from IE 2083
+ limit workaround
+
+2009-02-10 02:35 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/misc/cdr.cgi,
+ httemplate/search/cdr.html: quick n' dirty CDR deletion from web
+ interface, RT#4766 / RT#4731
+
+2009-02-09 07:03 ivan
+
+ * httemplate/browse/agent.cgi: try for slightly better UI on agent
+ config overrides
+
+2009-02-09 06:05 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_pay.pm, FS/bin/freeside-expiration-alerter,
+ conf/invoice_html, conf/invoice_html_statement,
+ httemplate/config/config-image.cgi,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/elements/header.html, httemplate/view/REAL_logo.cgi,
+ httemplate/view/cust_bill-logo.cgi: rest of per-agent config for
+ company_name, company_address, logo, etc.. RT#3989
+
+2009-02-09 03:45 ivan
+
+ * FS/FS/UI/Web.pm: pull out the data for address fields too!
+ RT#4583
+
+2009-02-09 03:35 ivan
+
+ * FS/FS/ConfDefaults.pm: more consistent labeling, RT#4583
+
+2009-02-09 03:32 ivan
+
+ * FS/FS/: UI/Web.pm, ConfDefaults.pm: add some more customer output
+ formats that include service address, RT#4583
+
+2009-02-09 02:38 ivan
+
+ * FS/bin/freeside-fetch: increase LWP timeout, some reports can
+ take a while
+
+2009-02-08 21:59 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add skip_dcontext and
+ skip_dstchannel_prefix options, RT#3196
+
+2009-02-08 17:49 ivan
+
+ * FS/FS/access_user.pm, FS/FS/part_pkg.pm,
+ httemplate/browse/access_group.html,
+ httemplate/browse/part_pkg.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/elements/select-part_pkg.html: further work on agents
+ editing own packages: fix fallout on package customization from
+ turning agent_virt on in edit/part_pkg.cgi, add a "clone package"
+ to package browse, like clone service, and have agent type
+ selection disappear when you set an agentnum. RT#1331
+
+2009-02-07 18:05 ivan
+
+ * FS/FS/access_user.pm, FS/FS/cust_pkg.pm,
+ httemplate/browse/part_pkg.cgi, httemplate/edit/cust_main.cgi,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/elements/edit.html,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/elements/select-agent_types.html,
+ httemplate/elements/select-cust-part_pkg.html,
+ httemplate/elements/select-part_pkg.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-agent_types.html,
+ httemplate/search/elements/search.html,
+ FS/FS/ClientAPI/Signup.pm: further work on agents editing own
+ packages: allow them to see (but not edit) global packages for
+ their type, RT#1331
+
+2009-02-07 12:16 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add more
+ documentation on order_pkg and the ability to order svc_phone
+ too, RT#4722
+
+2009-02-07 11:35 ivan
+
+ * httemplate/view/cust_main/payment_history.html: right-align
+ amount in prev history row
+
+2009-02-07 11:34 ivan
+
+ * FS/FS/Record.pm: don't look up encryption config every search,
+ this should help perf a lot with database config in 1.9
+
+2009-02-07 11:05 ivan
+
+ * bin/pod2x: no, it doesn't look like we have query
+
+2009-02-07 00:23 ivan
+
+ * httemplate/view/cust_main/: payment_history.html, packages.html,
+ packages/location.html, packages/services.html,
+ packages/status.html, payment_history/payment.html,
+ payment_history/refund.html: optimize customer view: avoid
+ looking up config values inside loops, RT#4728
+
+2009-02-06 17:45 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: fix up POD
+ formatting, RT#4727
+
+2009-02-06 17:33 ivan
+
+ * bin/pod2x: don't need this
+
+2009-02-06 17:26 ivan
+
+ * bin/pod2x: update pod2x to use Mediawiki module instead of
+ WWW:::Mediawiki::Client. whew, that wasn't so bad. RT#4727
+
+2009-02-06 10:31 ivan
+
+ * httemplate/elements/location.html: fix spurious "Unit #" label
+ showing up, RT#4745
+
+2009-02-05 13:02 jeff
+
+ * FS/FS/tax_rate.pm: pluralization agreement
+
+2009-02-05 08:57 jeff
+
+ * FS/FS/: Conf.pm, tax_rate.pm: add a config flag to ignore new
+ style taxes instead of throwing fatal errors
+
+2009-02-04 07:58 jeff
+
+ * FS/FS/cust_main.pm: with usage classes, the probability of a
+ taxless line item tranche is too high for this to be a fatal
+ error. we risk overlooking misconfigured taxes/packages
+
+2009-02-03 13:33 jeff
+
+ * FS/FS/part_pkg.pm: the taxproductnum is ALWAYS one of the
+ filtering conditions
+
+2009-02-01 05:52 ivan
+
+ * bin/test_scrub: adding scrub tool
+
+2009-02-01 04:48 ivan
+
+ * httemplate/elements/menu.html: yow, don't hide the config menu
+ unnecessarily
+
+2009-02-01 04:28 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/: ach_payment_results.html,
+ agent_delete_svc.html, agent_main.html, agent_order_pkg.html,
+ agent_provision.html, agent_provision_svc_acct.html,
+ change_bill.html, change_password.html, change_pay.html,
+ change_ship.html, customer_change_pkg.html,
+ customer_order_pkg.html, delete_svc.html, footer.html,
+ list_customers.html, make_ach_payment.html, make_payment.html,
+ myaccount.html, payment_results.html, process_change_bill.html,
+ process_change_password.html, process_change_pay.html,
+ process_change_pkg.html, process_change_ship.html,
+ process_order_pkg.html, process_order_recharge.html,
+ process_svc_acct.html, process_svc_external.html, provision.html,
+ provision_svc_acct.html, recharge_prepay.html,
+ recharge_results.html, selfservice.cgi, view_customer.html,
+ view_invoice.html, view_support_details.html, view_usage.html,
+ view_usage_details.html: put the footer in one frigging file,
+ whew
+
+2009-02-01 02:37 ivan
+
+ * FS/FS/Schema.pm: indexing cust_bill_event.eventpart should help
+ speed up freeside-migrate-events slightly... RT#4277
+
+2009-01-31 20:13 ivan
+
+ * FS/FS/Upgrade.pm: commit after each table upgrade, helps with
+ getting huge dbs upgraded, RT#4679
+
+2009-01-31 01:53 ivan
+
+ * FS/FS/access_user.pm: cache the results of ACL queries, should
+ improve performance of customer view page for customers with
+ shitloads of packages/services, RT#4696
+
+2009-01-30 12:44 ivan
+
+ * FS/FS/ClientAPI_SessionCache.pm: should use FS::Conf
+
+2009-01-29 16:40 ivan
+
+ * FS/FS/UI/bytecount.pm: we're not a disk drive manufacturer
+
+2009-01-29 11:21 ivan
+
+ * FS/FS/cust_pkg.pm: fix unsuspend-always_adjust_next_bill_date
+ config, RT#4271
+
+2009-01-28 08:28 rsiddall
+
+ * rpm/freeside.spec: Removed conflict between core billing package
+ and self-service RPMs so you can install them all on the same
+ machine. This may have applications if you're using XMLRPC to
+ talk to the self-service interface from PHP, Python, etc.
+
+2009-01-27 01:39 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/search/elements/search.html: add
+ ACL to allow download of browse/ stuff too, when possible.
+ RT#4681
+
+2009-01-25 20:22 ivan
+
+ * FS/FS/cust_main.pm: i think this was right after all, we do want
+ to look for a county-less state+country match before country only
+ and giving up, RT#4681
+
+2009-01-25 18:14 ivan
+
+ * FS/FS/cust_bill.pm: should fix: Argument "\\dollar 2.69" isn't
+ numeric in sprintf at /usr/local/share/perl/5.8.8/FS/cust_bill.pm
+ line 2193. Hopefully no problems with invoice with 0 tax
+ printing :/. RT#4681
+
+2009-01-25 17:36 ivan
+
+ * FS/FS/cust_main.pm: should be better error message for inability
+ to find tax rates, RT#4681. also pull in the add_freq changes.
+ *think* they're safe. famous last words.
+
+2009-01-25 17:07 ivan
+
+ * FS/FS/cust_pkg.pm: fix harmless warning, RT#4681: Argument ""
+ isn't numeric in numeric eq (==) at
+ /usr/local/share/perl/5.8.8/FS/cust_pkg.pm line 443.
+
+2009-01-25 15:58 ivan
+
+ * FS/FS/Record.pm, FS/FS/part_pkg.pm, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/elements/edit.html: fix one-time charges and
+ package customization for employees who don't have 'Edit global
+ package definition' ACL, RT#4668
+
+2009-01-25 14:20 ivan
+
+ * httemplate/browse/: access_group.html, access_user.html:
+ normalize terminology: s/internal users/employees/
+
+2009-01-25 12:43 ivan
+
+ * FS/bin/: freeside-cdrd, freeside-queued: reduce waiting time for
+ -cdrd and -queued, RT#4667
+
+2009-01-24 17:27 ivan
+
+ * FS/FS/cust_svc.pm: add some debugging to RADIUS db calls
+
+2009-01-24 13:53 ivan
+
+ * fs_selfservice/php/: order_renew.php,
+ process_payment_order_renew.php: finish up prepay example,
+ RT#4623
+
+2009-01-24 13:53 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: have the prepay amounts include the
+ current balance, RT#4623
+
+2009-01-24 13:49 ivan
+
+ * httemplate/edit/cust_main.cgi: wtf, don't pop up the geocode
+ chooser when taxproducts are off
+
+2009-01-24 13:04 ivan
+
+ * httemplate/: elements/select-domain.html,
+ elements/select-table.html, elements/tr-select-domain.html,
+ search/report_svc_acct.html, search/svc_acct.cgi: add domain
+ selection to advanced account report (side effect on RT#4623)
+
+2009-01-22 17:23 ivan
+
+ * fs_selfservice/php/: freeside.class.php, login.php, main.php,
+ order_renew.php, process_login.php,
+ process_payment_order_renew.php: add the start at PHP
+ self-service as a quick early renew example
+
+2009-01-22 16:49 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: typo in rounding the amounts
+ returned by renew_info, RT#4623
+
+2009-01-22 16:23 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: round the amounts returned by
+ renew_info, RT#4623
+
+2009-01-22 09:29 ivan
+
+ * FS/FS/part_pkg.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add self-service
+ methods renew_info, order_renew and process_payment_order_renew
+ to enable self-renewal through self-service. RT#4623
+
+2009-01-20 18:02 ivan
+
+ * httemplate/edit/: part_pkg.cgi, elements/edit.html: fix
+ (hopefully last of the) customize package bogosity in 1.9,
+ RT#4662
+
+2009-01-20 16:52 ivan
+
+ * FS/FS/cust_bill_pkg_tax_location.pm: stupid typo preventing
+ service addresses from working, RT#4663
+
+2009-01-20 12:08 ivan
+
+ * FS/FS/: cust_main.pm: whew, hopefully that will actually fix
+ agent-specific invoices migrated from 1.7->1.9, RT#4645
+
+2009-01-20 11:35 ivan
+
+ * FS/FS/cust_bill.pm: fix agent-specific logos migrated from 1.7,
+ RT#4645
+
+2009-01-19 15:53 ivan
+
+ * FS/FS/tax_rate.pm, httemplate/misc/process/tax-import.cgi:
+ tax-pkg_location changes broke new taxation, this should fix
+
+2009-01-19 15:44 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: turn debugging off
+
+2009-01-19 14:32 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: don't ignore the cdrtypenum rule for
+ 0, hopefully finally fix DA for QIS, RT#4502
+
+2009-01-19 09:37 ivan
+
+ * httemplate/edit/process/cust_pkg.cgi: fix error on bulk package
+ order/cancel, RT#4645
+
+2009-01-18 22:36 ivan
+
+ * httemplate/: elements/tr-select-cust_location.html,
+ view/cust_main/packages/location.html: default service location
+ is cust_main ship_ address when present! RT#4499
+
+2009-01-18 19:50 ivan
+
+ * FS/FS/Schema.pm, FS/FS/rate.pm,
+ httemplate/edit/process/rate_region.cgi: 10 digit prefix
+ matching, RT#4403
+
+2009-01-18 15:51 ivan
+
+ * FS/FS/cust_pkg.pm: finish package location tax reporing, RT#4499
+
+2009-01-18 15:43 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_bill_pkg_tax_location.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_county.pm, FS/FS/tax_rate.pm,
+ FS/t/cust_bill_pkg_tax_location.t,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_tax.cgi,
+ httemplate/view/cust_main/packages/location.html: finish package
+ location tax reporing, RT#4499
+
+2009-01-18 13:05 rsiddall
+
+ * rpm/freeside.sysconfig: bash didn't like spaces on each side of
+ an equals sign.
+
+2009-01-13 05:00 ivan
+
+ * FS/FS/part_export/internal_diddb.pm: fix internal_diddb delete &
+ return number to availability, RT#4603
+
+2009-01-12 19:25 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: whew, works fine, rewrite to 411 was
+ sticky that's why calls were being skipped for wrong carrierid,
+ RT#4502
+
+2009-01-12 18:39 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: by his noodly appendage, i hope this
+ is just a precendece problem, RT#4502
+
+2009-01-12 18:13 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: WORKING avoid looking up options
+ inside the rating loop, RT#4502
+
+2009-01-12 17:58 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: avoid looking up options inside the
+ rating loop, RT#4502
+
+2009-01-12 17:34 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: refactor out the ignoring rules into
+ check_chargable; ignore carrierid rule w/411 rewrite, RT#4502
+
+2009-01-12 16:17 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: wtf is up with 411_rewrite, RT#4502
+
+2009-01-12 15:51 ivan
+
+ * FS/FS/: Conf.pm, Record.pm, cdr/taqua.pm: taqua config to rewrite
+ DA calls, RT#4502
+
+2009-01-12 13:16 jeff
+
+ * FS/FS/cust_main.pm: tickets only exist when a ticket system
+ exists
+
+2009-01-12 12:59 jeff
+
+ * FS/FS/cust_main.pm: doc tyop
+
+2009-01-12 01:01 jeff
+
+ * FS/FS/svc_acct.pm: vfw callback failure
+
+2009-01-10 15:56 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, httemplate/misc/change_pkg.cgi,
+ httemplate/edit/process/change-cust_pkg.html,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/elements/location.html,
+ httemplate/elements/tr-select-cust_location.html,
+ httemplate/view/cust_main/packages/location.html,
+ httemplate/view/cust_main/packages/package.html: implement
+ package changes w/location change, RT#4499
+
+2009-01-09 16:43 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ httemplate/elements/location.html,
+ httemplate/elements/tr-select-cust_location.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/misc/location.cgi, httemplate/misc/order_pkg.html:
+ more work on package service addresses: hide locations when
+ they're all the default, config to show them anyway / finish
+ implementing package ordering, fix all the state/county weirdness
+ when changing the location dropdown. RT#4499
+
+2009-01-08 20:06 ivan
+
+ * httemplate/edit/cust_main/contact.html,
+ httemplate/elements/location.html,
+ httemplate/elements/select-country.html,
+ httemplate/elements/select-county.html,
+ httemplate/elements/select-state.html,
+ httemplate/elements/tr-select-part_referral.html,
+ httemplate/misc/location.cgi, httemplate/misc/order_pkg.html,
+ FS/FS/Mason.pm, FS/FS/cust_location.pm, FS/FS/cust_main.pm,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/packages/location.html: pick/enter a
+ location when ordering a package, RT#4499
+
+2009-01-07 17:45 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/cust_location.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ FS/t/cust_location.t, eg/table_template.pm,
+ eg/table_template-svc.pm,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/packages/location.html,
+ httemplate/view/cust_main/packages/package.html,
+ httemplate/view/cust_main/packages/services.html,
+ httemplate/view/cust_main/packages/status.html: start adding
+ package locations, RT#4499
+
+2009-01-07 08:59 jeff
+
+ * conf/invoice_latex: allow tex to do more column sizing
+
+2009-01-06 16:27 ivan
+
+ * httemplate/browse/rate_region.html: country code is two words
+
+2009-01-06 16:18 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: fixup error message, this is all for
+ RT#4524
+
+2009-01-06 16:14 ivan
+
+ * httemplate/browse/: rate.cgi, rate_region.html: add a dropdown to
+ help browse regions by countrycode
+
+2009-01-06 15:30 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: throw a fatal error if a call is
+ unrateable and add an ignore_unrateable flag to go back to the
+ old skip behavior
+
+2009-01-06 13:16 ivan
+
+ * FS/FS/: cdr.pm, part_pkg/voip_cdr.pm: swap price to last column
+ in default CDR output format; fix "all 0 prices" when using
+ simple output format w/internal rating, RT#4503
+
+2009-01-05 13:12 jeff
+
+ * FS/FS/tax_rate.pm: doh! change the interface here, too
+
+2009-01-04 16:26 ivan
+
+ * httemplate/elements/checkboxes-table-name.html,
+ httemplate/elements/checkboxes.html,
+ httemplate/elements/select-rate.html,
+ httemplate/elements/tr-select-rate.html, FS/FS/rate_prefix.pm,
+ httemplate/browse/rate.cgi,
+ httemplate/misc/copy-rate_detail.html,
+ httemplate/misc/process/copy-rate_detail.html: add rate copying,
+ RT#4431
+
+2009-01-04 14:07 ivan
+
+ * Makefile, init.d/freeside-init: don't run a self-service server
+ against localhost OOTB; eliminate those gigantic useless logfiles
+
+2009-01-02 17:52 ivan
+
+ * bin/cdr.http_and_import, bin/cdr.import, bin/cdr.sftp_and_import,
+ FS/FS/Record.pm, FS/FS/cdr.pm, FS/FS/cdr/indosoft.pm: indosoft
+ CDR format, RT#4425
+
+2009-01-02 14:03 ivan
+
+ * FS/FS/Record.pm, FS/FS/cdr.pm, FS/FS/cdr/bell_west.pm,
+ FS/FS/cdr/troop.pm, bin/cdr.import, bin/cdr.sftp_and_import: add
+ troop CDRs, RT#4413
+
+2009-01-02 10:01 ivan
+
+ * eg/cdr_template.pm: cdr template, RT#4413 and RT#4412
+
+2009-01-02 09:58 ivan
+
+ * FS/FS/cdr/troop.pm: commiting initial troop CDR template, RT#4413
+
+2009-01-01 12:11 rsiddall
+
+ * rpm/freeside-selfservice.conf: New Apache configuration file for
+ the self-service interface.
+
+2009-01-01 12:10 rsiddall
+
+ * rpm/freeside.spec: Modifications to let self-service work if you
+ really insist on installing it on the same machine as the billing
+ server. Also more fixes for SuSE, and a couple of changes to
+ minimize differences from the 1.7 branch.
+
+2008-12-31 14:04 ivan
+
+ * FS/FS/: Record.pm, cdr/bell_west.pm: finish up working bell_west
+ CDR format, RT#4403
+
+2008-12-31 10:07 jeff
+
+ * FS/FS/cust_main.pm: one got missed?
+
+2008-12-30 19:28 ivan
+
+ * FS/FS/Record.pm, FS/FS/cdr.pm, FS/FS/phone_avail.pm,
+ FS/FS/cdr/bell_west.pm, FS/FS/cdr/simple.pm,
+ FS/FS/part_pkg/voip_cdr.pm, httemplate/edit/rate_detail.html,
+ httemplate/misc/cdr-import.html,
+ httemplate/misc/process/cdr-import.html: bell west CDR format,
+ RT#4403
+
+2008-12-30 14:00 jeff
+
+ * FS/FS/: cust_pkg.pm, cust_pkg_reason.pm: yet more timestamping
+ improvements and corrections to reasons based on history records
+
+2008-12-30 13:45 jeff
+
+ * FS/FS/cdr.pm: move price to last column for default_source
+
+2008-12-30 11:13 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: allow upstream_simple to specify a
+ usage_class for tax purposes in calltypenum
+
+2008-12-29 10:06 jeff
+
+ * Makefile, conf/invoice_latex, conf/longtable.sty.patch,
+ etc/fslongtable.sty: ease deployment of patched longtable
+
+2008-12-28 11:10 ivan
+
+ * httemplate/browse/cust_main_county.cgi: finish dealing with
+ counties with spaces, etc., RT#4496
+
+2008-12-28 11:08 ivan
+
+ * httemplate/edit/process/cust_main_county-expand.cgi: allow normal
+ ut_textn strings in county expansion, RT#4496
+
+2008-12-28 10:59 ivan
+
+ * httemplate/browse/cust_main_county.cgi: deal with counties with
+ spaces, etc., RT#4496
+
+2008-12-28 10:52 ivan
+
+ * httemplate/browse/cust_main_county.cgi: put the
+ country/state/county selections on their own line, RT#4496
+
+2008-12-28 10:48 ivan
+
+ * httemplate/elements/: select-country.html, select-county.html,
+ select-state.html, select-did.html: fix browse results for
+ selecting counties (resulting from separating tax classes), also
+ add dropdowns to browse by state and county, RT#4496
+
+2008-12-28 10:44 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/cust_main/contact.html, edit/cust_main/billing.html,
+ misc/payment.cgi, edit/cust_main/select-country.html,
+ edit/cust_main/select-county.html,
+ edit/cust_main/select-state.html: fix browse results for
+ selecting counties (resulting from separating tax classes), also
+ add dropdowns to browse by state and county, RT#4496
+
+2008-12-24 16:45 jeff
+
+ * FS/FS/: cust_bill_pkg.pm, cust_main.pm, cust_main_county.pm: fix
+ "texas tax" in 1.9
+
+2008-12-23 13:41 jeff
+
+ * FS/FS/cust_main.pm: miss use
+
+2008-12-23 12:35 jeff
+
+ * FS/FS/cust_main.pm: correct bad tax calculation
+
+2008-12-22 16:32 ivan
+
+ * FS/FS/: cust_bill.pm: truncate package descriptions over 50 chars
+ to avoid pushing the total column out to the right, RT#4449
+
+2008-12-22 15:28 ivan
+
+ * httemplate/config/config.cgi: textareas are much less annoying to
+ work with when their scrollbar isn't scrolled off the side itself
+
+2008-12-22 14:30 rsiddall
+
+ * rpm/freeside.spec: Copying over modifications to support SuSE
+ from the 1.7 branch.
+
+2008-12-22 13:16 ivan
+
+ * httemplate/edit/: part_pkg.cgi, quick-charge.html: soft-limit
+ package names to 50 chars to avoid problems with typeset
+ invoices, RT#4449
+
+2008-12-21 13:53 ivan
+
+ * FS/FS/svc_phone.pm: and fix msgcat usage, this should do it?,
+ RT#4204
+
+2008-12-21 13:49 ivan
+
+ * FS/FS/svc_acct.pm: svc_acct.pm bogosity too, wtf?!, RT#4204
+
+2008-12-21 13:44 ivan
+
+ * FS/FS/: msgcat.pm: msgcat.pm upgrade bogosity, shrug, RT#4204
+
+2008-12-21 13:37 ivan
+
+ * FS/FS/: svc_Common.pm, Upgrade.pm: unique checking for svc_phone
+ like svc_acct, closes: RT#4204 (also a few lines of the new
+ per-agent config snuck in Conf.pm from RT#3989)
+
+2008-12-21 13:33 ivan
+
+ * FS/: FS/svc_phone.pm, FS/Conf.pm, FS/Record.pm, FS/Setup.pm,
+ FS/msgcat.pm, FS/svc_Common.pm, FS/svc_acct.pm,
+ bin/freeside-upgrade: unique checking for svc_phone like
+ svc_acct, closes: RT#4204 (also a few lines of the new per-agent
+ config snuck in Conf.pm from RT#3989)
+
+2008-12-21 10:38 ivan
+
+ * FS/bin/freeside-cdrd: cdrd brainfart, finishing up RT#4423
+
+2008-12-21 10:09 ivan
+
+ * FS/: FS/Schema.pm, FS/queue.pm, bin/freeside-cdrd: have
+ freeside-queued put billing jobs in the queue, so they run in
+ their own short-lived processes, RT#4423
+
+2008-12-21 09:40 ivan
+
+ * FS/FS/queue.pm: doc
+
+2008-12-15 16:08 jeff
+
+ * FS/FS/cust_pkg.pm: proper dates on expire and suspend reasons
+
+2008-12-11 13:11 jeff
+
+ * FS/FS/cust_main.pm: place tax on invoice only once
+
+2008-12-10 13:43 ivan
+
+ * httemplate/search/: cust_bill_event.html, report_cust_bill.html,
+ report_cust_credit.html, report_cust_event.html,
+ report_cust_main-zip.html, report_cust_main.html,
+ report_cust_pay.html, report_cust_pay_batch.html,
+ report_cust_pkg.html, report_newtax.html, report_svc_acct.html,
+ report_tax.html: allow all-agent reporting again
+
+2008-12-10 13:33 ivan
+
+ * httemplate/graph/: report_cust_bill_pkg.html,
+ report_cust_pkg.html, report_money_time.html: allow all-agent
+ reporting again
+
+2008-12-10 12:20 ivan
+
+ * FS/FS/cust_main/Import.pm: referral import fixes, RT#4427
+
+2008-12-10 11:43 rsiddall
+
+ * rpm/freeside.spec: Cleanup to quieten rpmlint. Fixes to cope
+ with moving code out of handler.pl, etc.
+
+2008-12-10 11:42 rsiddall
+
+ * rpm/rpm2Bundle: Further modifications to handle Perl RPM names
+ and map them back to Perl module names.
+
+2008-12-09 18:47 jeff
+
+ * FS/FS/cust_tax_location.pm: space is empty
+
+2008-12-08 17:49 ivan
+
+ * FS/FS/Record.pm: oops
+
+2008-12-08 17:46 ivan
+
+ * FS/FS/Record.pm, FS/FS/inventory_item.pm,
+ httemplate/misc/inventory_item-import.html,
+ httemplate/misc/process/inventory_item-import.html: use common
+ base for inventory import too, fixes problems with errors due to
+ dos line endings and allows Excel upload, RT#4346
+
+2008-12-08 02:13 ivan
+
+ * FS/FS/cust_bill_pkg.pm: make CDRs smaller, so we can fit more
+ columns, RT#4376
+
+2008-12-08 01:08 ivan
+
+ * FS/FS/Schema.pm: make room for CDRs, RT#4387
+
+2008-12-08 00:52 ivan
+
+ * FS/FS/: cdr.pm, part_pkg/voip_cdr.pm: respect output_format and
+ add an header for rating_method=prefix too, RT#4387
+
+2008-12-08 00:46 ivan
+
+ * conf/invoice_html: normal ext_desc shouldn't shove the second+
+ columns of CDRs out
+
+2008-12-05 09:23 jeff
+
+ * FS/FS/tax_rate.pm: passthrough support for gross revenue taxes
+
+2008-12-05 09:19 jeff
+
+ * FS/FS/part_pkg.pm: avoid taxation on products with no assigned
+ taxes
+
+2008-12-05 00:24 jeff
+
+ * FS/FS/cust_main.pm: missing uses, corrects 4388
+
+2008-12-04 20:20 jeff
+
+ * FS/FS/cust_main_county.pm: bad shortcut causes taxes not to be
+ charged
+
+2008-12-03 21:16 jeff
+
+ * FS/FS/part_export/soma.pm: wtf?
+
+2008-12-03 18:19 jeff
+
+ * httemplate/edit/cust_main.cgi: better placement of script
+ sourcing
+
+2008-12-03 18:03 jeff
+
+ * httemplate/elements/init_overlib.html: better placement of script
+ sourcing
+
+2008-12-03 17:46 jeff
+
+ * httemplate/edit/cust_main/choose_tax_location.html: better
+ behavior when zip code is missing
+
+2008-12-03 15:29 ivan
+
+ * httemplate/search/report_receivables.html: allow an all-agent
+ receivables report again
+
+2008-12-03 13:15 ivan
+
+ * httemplate/misc/whois.cgi: fix real customer numbers showing on
+ view pages, RT#4099/4379
+
+2008-12-03 13:12 ivan
+
+ * httemplate/view/: cust_pay.html, cust_refund.html, cust_bill.cgi,
+ svc_broadband.cgi, svc_domain.cgi, svc_external.cgi,
+ svc_forward.cgi, svc_www.cgi: fix real customer numbers showing
+ on view pages, RT#4099/4379
+
+2008-12-03 09:25 ivan
+
+ * FS/FS/part_export/internal_diddb.pm: fix internal_diddb to
+ default to countrycode 1
+
+2008-12-02 21:53 ivan
+
+ * httemplate/edit/: part_pkg.cgi, elements/edit.html: 60 char soft
+ max length for packages, so invoices don't wrap, RT#4328
+
+2008-12-02 17:42 jeff
+
+ * bin/import-tax-rates,
+ httemplate/edit/cust_main/choose_tax_location.html,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/elements/ajaxcontentmws.js, FS/FS/Misc.pm,
+ FS/FS/Schema.pm, FS/FS/cust_main.pm, FS/FS/cust_tax_location.pm,
+ FS/FS/part_pkg_taxrate.pm, FS/FS/tax_class.pm, FS/FS/tax_rate.pm,
+ httemplate/edit/cust_main.cgi, httemplate/misc/tax-import.cgi,
+ httemplate/misc/xmlhttp-cust_main-address_standardize.html:
+ support zip5 tax lookups, correct errors with fixed format cch
+ import, inital import performance improvements, noise reduction
+ on imports, tool for inital import
+
+2008-11-30 23:52 ivan
+
+ * FS/FS/: Conf.pm, cdr.pm: set charged_party to accoutncode for
+ vedeye, RT#4342
+
+2008-11-30 15:37 ivan
+
+ * httemplate/edit/access_user.html: s/Internal Access
+ Groups/Employee Groups/
+
+2008-11-30 15:34 ivan
+
+ * httemplate/: browse/access_user.html, edit/access_user.html:
+ s/Internal Users/Employees/
+
+2008-11-30 15:26 ivan
+
+ * httemplate/: browse/access_group.html, edit/access_group.html:
+ s/Internal Access Groups/Employee Groups/
+
+2008-11-30 13:01 ivan
+
+ * FS/FS/cdr.pm: _cdr_min_parser_maker fix for correct setting of
+ duration/billsec with simple & simple2 rate plans
+
+2008-11-29 13:54 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm, FS/FS/svc_phone.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/login.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: add
+ selfservice_server-single_domain config, and login_info
+ self-service method to give the login page a bit more
+ configurability
+
+2008-11-29 12:32 ivan
+
+ * FS/FS/Conf.pm: add selfservice_server-single_domain config, and
+ login_info self-service method to give the login page a bit more
+ configurability
+
+2008-11-25 16:30 ivan
+
+ * FS/FS/ClientAPI/PrepaidPhone.pm: don't set a Session-Timeout if
+ the rate is 0
+
+2008-11-25 16:20 ivan
+
+ * FS/FS/: Record.pm, cust_main/Import.pm: should fix importing from
+ excel, closes: RT#4337
+
+2008-11-24 07:40 jeff
+
+ * FS/FS/part_export/soma.pm: more caffiene, please
+
+2008-11-24 07:36 jeff
+
+ * FS/FS/part_export/soma.pm: doh
+
+2008-11-24 07:18 jeff
+
+ * FS/FS/part_export/soma.pm: be more accepting
+
+2008-11-24 06:48 jeff
+
+ * FS/FS/part_export/soma.pm: esn's are hex
+
+2008-11-24 04:22 ivan
+
+ * FS/FS/cdr/genband.pm: update genband import to agree with
+ reality, RT#4177
+
+2008-11-24 02:59 ivan
+
+ * FS/FS/part_export/internal_diddb.pm: add countrycode option to
+ internal_diddb; throw a warning instead of an error if a number
+ couldn't be returned to inventory
+
+2008-11-24 02:47 ivan
+
+ * FS/FS/part_export/: phone_sqlradius.pm, sqlradius.pm: fix
+ phone_sqlradius CDR population?, RT#4100
+
+2008-11-24 02:11 ivan
+
+ * FS/FS/ClientAPI/PrepaidPhone.pm: add debugging, hopefully fix
+ seconds returned finally, RT#4100
+
+2008-11-24 00:47 ivan
+
+ * FS/FS/ClientAPI/PrepaidPhone.pm: look for a voip rate in pricing
+ add-ons too... eek. also correct rating to destination RT#4100
+
+2008-11-22 14:17 ivan
+
+ * FS/FS/: Conf.pm, Schema.pm, cust_credit.pm, cust_main.pm,
+ cust_pkg.pm, part_event.pm, part_event/Action/addpost.pm,
+ part_event/Condition.pm, part_event/Action/apply.pm,
+ part_event/Action/bill.pm, part_event/Action/cancel.pm,
+ part_event/Action/collect.pm,
+ part_event/Action/cust_bill_batch.pm,
+ part_event/Action/cust_bill_comp.pm,
+ part_event/Action/cust_bill_fee_percent.pm,
+ part_event/Action/cust_bill_realtime_card.pm,
+ part_event/Action/cust_bill_realtime_check.pm,
+ part_event/Action/cust_bill_realtime_lec.pm,
+ part_event/Action/cust_bill_send.pm,
+ part_event/Action/cust_bill_send_agent.pm,
+ part_event/Action/cust_bill_send_alternate.pm,
+ part_event/Action/cust_bill_send_csv_ftp.pm,
+ part_event/Action/cust_bill_send_if_newest.pm,
+ part_event/Action/cust_bill_spool_csv.pm,
+ part_event/Action/cust_bill_suspend_if_balance.pm,
+ part_event/Action/fee.pm,
+ part_event/Action/pkg_referral_credit.pm,
+ part_event/Action/pkg_referral_credit_pkg.pm,
+ part_event/Action/suspend.pm,
+ part_event/Action/suspend_if_pkgpart.pm,
+ part_event/Action/suspend_unless_pkgpart.pm,
+ part_event/Condition/balance.pm,
+ part_event/Condition/balance_age.pm,
+ part_event/Condition/balance_under.pm,
+ part_event/Condition/cust_bill_age.pm,
+ part_event/Condition/cust_bill_has_service.pm,
+ part_event/Condition/cust_bill_owed.pm,
+ part_event/Condition/cust_bill_owed_under.pm,
+ part_event/Condition/cust_payments.pm,
+ part_event/Condition/has_referral_custnum.pm,
+ part_event/Condition/once_percust.pm,
+ part_event/Condition/pkg_age.pm,
+ part_event/Condition/pkg_notchange.pm,
+ part_event/Condition/pkg_pkgpart.pm,
+ part_event/Condition/pkg_recurring.pm,
+ part_event/Condition/pkg_unless_pkgpart.pm, part_pkg/flat.pm:
+ referral credits overhaul, use billing events, agents can
+ self-configure, limit to once-per-customer, depend on any time
+ from referred package, referred customer payment, specific
+ packages, partial staged credits, RT#3983
+
+2008-11-21 23:10 ivan
+
+ * httemplate/: browse/part_event.html, edit/elements/edit.html:
+ billing event cloning
+
+2008-11-20 19:36 jeff
+
+ * FS/FS/part_export/soma.pm: initial somanetworks support
+
+2008-11-20 18:57 ivan
+
+ * httemplate/edit/elements/edit.html: remove debugging accidentally
+ left in
+
+2008-11-20 18:55 ivan
+
+ * httemplate/edit/process/elements/process.html: document
+ viewall_ext
+
+2008-11-20 17:58 ivan
+
+ * httemplate/: edit/elements/edit.html,
+ elements/tr-select-agent.html: undo voodoo, find real problem
+
+2008-11-20 16:06 ivan
+
+ * httemplate/edit/elements/edit.html: voodoo
+
+2008-11-20 11:02 jeff
+
+ * FS/FS/rate.pm: this must be what is meant
+
+2008-11-20 09:49 jeff
+
+ * FS/bin/freeside-dedup-cust_bill_pkg_detail-header: tool to remove
+ extra cdr headers
+
+2008-11-20 08:59 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: only one header per package, not one
+ per service -- fixes #4260
+
+2008-11-20 04:52 ivan
+
+ * FS/FS/cust_main/Import.pm: better end-of-spreadsheet detection
+ for excel import, hopefully. should fix "Error: Can't use an
+ undefined value as an ARRAY reference" error on import. RT#4297
+
+2008-11-20 03:35 ivan
+
+ * bin/rate.delete: fill in the ratenum. doesn't actually delete
+ the rate itself, just all its data (the hard part)
+
+2008-11-19 16:42 ivan
+
+ * FS/FS/cust_bill.pm: don't use payname for CARD or DCRD either,
+ closes: RT#3982
+
+2008-11-19 06:55 jeff
+
+ * FS/FS/Misc.pm, FS/FS/Schema.pm, FS/FS/cust_tax_location.pm,
+ FS/FS/part_pkg_taxrate.pm, FS/FS/tax_class.pm, FS/FS/tax_rate.pm,
+ httemplate/misc/tax-import.cgi: support for cch fixed format
+
+2008-11-18 17:24 ivan
+
+ * FS/FS/Schema.pm: fix phone_avail.availnum to be a proper primary
+ key, fix agent.agent_custnum unique index causing it to get a
+ value filled in by Record.pm
+
+2008-11-17 18:56 rsiddall
+
+ * rpm/rpm2Bundle: Now handles hyphenated Perl requirements as well
+ as those in parentheses, and handles more version relation types.
+
+2008-11-12 18:22 ivan
+
+ * FS/FS/access_groupagent.pm, FS/FS/agent.pm,
+ httemplate/browse/agent.cgi, httemplate/edit/agent.cgi,
+ httemplate/edit/process/agent.cgi: add ability to view/edit
+ access groups of an agent
+
+2008-11-11 00:55 ivan
+
+ * FS/FS/cust_bill.pm: add fax to invoice data, RT#3290
+
+2008-11-11 00:45 ivan
+
+ * conf/: invoice_html, invoice_latex: agent_custid and ship_fax
+ don't belong with the ship address, that was an unrelated
+ tampabay/pbx-change request, RT#3290
+
+2008-11-10 23:51 ivan
+
+ * conf/invoice_html: make HTML invoice more consistent with current
+ typeset invoice: center invoice date instead of right-justify
+
+2008-11-09 03:43 ivan
+
+ * httemplate/browse/agent.cgi: realign things in light of
+ small_custview in this table for master customering, roundaboutly
+ part of #2933
+
+2008-11-09 03:31 ivan
+
+ * FS/FS/cust_main/Import.pm: move batch customer import to its own
+ file; add svc_external_svc_phone export format, RT#4103
+
+2008-11-09 01:14 ivan
+
+ * FS/FS/Conf.pm, httemplate/elements/file-upload.html,
+ httemplate/misc/phone_avail-import.html: add a global countrycode
+ to phone_avail import and a conf for the default (some other conf
+ values snuck in also, oh well)
+
+2008-11-09 00:51 ivan
+
+ * FS/FS/Mason.pm, FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ FS/FS/cust_main/Import.pm, httemplate/misc/cust_main-import.cgi,
+ Makefile, FS/FS.pm, FS/MANIFEST, FS/bin/freeside-queued,
+ httemplate/misc/process/cust_main-import.cgi: move batch customer
+ import to its own file; add svc_external_svc_phone export format,
+ RT#4103
+
+2008-11-06 22:04 ivan
+
+ * httemplate/view/svc_acct.cgi: fix viewing of unlinked services.
+ wow, it has been a while
+
+2008-11-06 14:53 ivan
+
+ * FS/FS/part_export/sqlradius.pm: should fix open session RADIUS
+ search, RT #4233
+
+2008-11-06 14:20 ivan
+
+ * FS/FS/part_export/sqlradius.pm: fix radius search, RT#4233
+
+2008-11-05 20:22 ivan
+
+ * FS/FS/svc_acct.pm: avoid harmless "Use of uninitialized value in
+ concatenation (.) or string at
+ /usr/local/share/perl/5.8.8/FS/svc_acct.pm line 1140" error
+
+2008-11-05 20:18 ivan
+
+ * FS/FS/svc_acct.pm: . is used in some implementations of classic
+ crypt
+
+2008-11-03 07:28 jeff
+
+ * FS/FS/cust_main.pm: REAL otherwise there are no taxes
+
+2008-11-03 07:26 jeff
+
+ * FS/FS/cust_main.pm: yikes! not yet
+
+2008-11-03 07:14 jeff
+
+ * FS/FS/cust_main.pm: otherwise there are no taxes
+
+2008-11-02 17:10 ivan
+
+ * httemplate/view/svc_acct.cgi: time remaining is more useful to
+ display as hours + minutes than days, hours, minutes from
+ Time::Duration
+
+2008-11-02 12:27 ivan
+
+ * httemplate/search/: cust_bill_pkg.cgi, report_tax.cgi: (and
+ REALLY fix the line-item links too, whew) fix overreporting of
+ tax invoiced when using & reporting with taxclasses, RT#4131
+
+2008-11-02 12:03 ivan
+
+ * httemplate/search/report_tax.cgi: (and fix the line-item links
+ too, whew) fix overreporting of tax invoiced when using &
+ reporting with taxclasses, RT#4131
+
+2008-11-02 11:40 ivan
+
+ * httemplate/search/report_tax.cgi: (and fix the total too) fix
+ overreporting of tax invoiced when using & reporting with
+ taxclasses, RT#4131
+
+2008-11-02 11:26 ivan
+
+ * httemplate/search/report_tax.cgi: fix overreporting of tax
+ invoiced when using & reporting with taxclasses, RT#4131
+
+2008-11-01 15:12 ivan
+
+ * init.d/freeside-init, FS/FS/Daemon.pm, FS/bin/freeside-cdrd: have
+ freeside-cdrd disable itself if there's no appropriate package
+ definition, RT#4184
+
+2008-10-29 15:24 ivan
+
+ * FS/FS/cust_main.pm: eek, fix agent_plandata from comping up with
+ spurious hits
+
+2008-10-29 13:23 ivan
+
+ * FS/FS/part_event/Action.pm: remove debugging accidentally left in
+
+2008-10-29 13:21 ivan
+
+ * FS/FS/part_event/Action.pm: huh. how did event editing ever
+ work? is this 5.10-specific?
+
+2008-10-29 01:03 ivan
+
+ * FS/FS/cust_main.pm, init.d/freeside-init,
+ FS/FS/part_pkg/voip_cdr.pm, FS/bin/freeside-cdrd: prepaid cdr
+ pickup & bill daemon, RT#4184
+
+2008-10-29 00:50 ivan
+
+ * FS/FS/part_export/internal_diddb.pm: fix to internal_diddb
+ provisioning
+
+2008-10-27 18:23 ivan
+
+ * FS/FS/svc_phone.pm: fix svc_phone non-numeric "phone numbers",
+ RT#4204
+
+2008-10-24 17:37 ivan
+
+ * FS/FS/: Conf.pm, svc_phone.pm: add a switch to allow letters in
+ phone numbers, RT#4195
+
+2008-10-24 16:21 ivan
+
+ * httemplate/view/svc_phone.cgi: correct links to non-US CDRs from
+ svc_phone view
+
+2008-10-24 15:53 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm: use
+ Reply-Message for the RADIUS error message, RT#4100
+
+2008-10-24 15:23 ivan
+
+ * FS/FS/ClientAPI/PrepaidPhone.pm: adding prepaid self-service
+ hooks, RT#4100
+
+2008-10-24 14:31 ivan
+
+ * FS/FS/: rate.pm, ClientAPI/PrepaidPhone.pm, part_pkg/voip_cdr.pm,
+ part_pkg/voip_sqlradacct.pm: adding prepaid self-service hooks,
+ RT#4100
+
+2008-10-24 14:25 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService/: FreeRadiusVoip.pm:
+ rlm_perl hook for prepaid voip radius, RT#4100
+
+2008-10-24 14:22 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm:
+ rlm_perl hook for prepaid voip radius, RT#4100
+
+2008-10-24 12:58 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService/: FreeRadiusVoip.pm:
+ rlm_perl hook for prepaid voip radius, RT#4100
+
+2008-10-24 12:54 ivan
+
+ * fs_selfservice/FS-SelfService/: SelfService.pm,
+ SelfService/FreeRadiusVoip.pm: rlm_perl hook for prepaid voip
+ radius, RT#4100
+
+2008-10-24 12:45 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: rlm_perl hook for
+ prepaid voip radius, RT#4100
+
+2008-10-24 12:13 ivan
+
+ * fs_selfservice/FS-SelfService/: SelfService.pm,
+ SelfService/FreeRadiusVoip.pm: rlm_perl hook for prepaid voip
+ radius, RT#4100
+
+2008-10-23 19:54 ivan
+
+ * FS/: FS/part_export/phone_sqlradius.pm,
+ FS/part_export/sqlradius.pm, bin/freeside-sqlradius-radacctd:
+ untested code to suck in CDRs in from VoIP RADIUS exports,
+ RT#4100
+
+2008-10-23 19:08 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/xmlhttp-cust_main-search.cgi:
+ fixes to facilitate using agent_custid as custnum, RT#4190
+
+2008-10-23 18:45 ivan
+
+ * FS/: FS/svc_phone.pm, bin/freeside-sqlradius-reset: tiny nits for
+ phone RADIUS export: allow freeside-sqlradius-reset to reset a
+ phone_sqlradius export, but only if explicitly specified by
+ exportnum. also fix "Reference found where even-size list
+ expected" warning and junk winding up in radreply table". all
+ this phone_sqlradius stuff is RT#4100
+
+2008-10-23 18:19 ivan
+
+ * FS/FS/: Conf.pm, svc_phone.pm, part_export/phone_sqlradius.pm,
+ part_export/sqlradius.pm: add phone_sqlradius export
+
+2008-10-22 22:20 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: POD cleanup
+
+2008-10-22 11:50 ivan
+
+ * httemplate/view/svc_phone.cgi: fix CDR links
+
+2008-10-21 21:39 ivan
+
+ * FS/FS/part_export/sqlradius.pm, httemplate/search/sqlradius.cgi,
+ httemplate/search/sqlradius.html: fix error on open-ended RADIUS
+ search with Pg, add options for open session search and search on
+ start time, RT#4051
+
+2008-10-21 08:50 jeff
+
+ * fs_selfservice/java/: freeside_login_example.java,
+ freeside_signup_example.java, biz/freeside/SelfService.java:
+ biz.freeside.SelfService class and sample applications
+
+2008-10-18 18:57 ivan
+
+ * httemplate/config/config.cgi: correctly allow re-editing of
+ config options with " in them
+
+2008-10-18 17:38 ivan
+
+ * FS/FS/Schema.pm, FS/FS/agent.pm, httemplate/edit/agent.cgi,
+ httemplate/elements/search-cust_main.html,
+ httemplate/browse/agent.cgi: add a master custnum field to
+ agents, RT#2933 (roundabout)
+
+2008-10-17 18:22 jeff
+
+ * FS/FS/cust_main.pm: sheesh
+
+2008-10-17 18:19 jeff
+
+ * FS/FS/cust_main.pm: doh
+
+2008-10-17 18:08 jeff
+
+ * FS/FS/cust_main.pm: cope with overlapping (but with distinct
+ endpoints) tax areas
+
+2008-10-17 13:01 jeff
+
+ * conf/: invoice_latex, invoice_latexcoupon: address tweaks,
+ assumes a window at least 2.75in or 7cm wide
+
+2008-10-17 11:57 jeff
+
+ * FS/FS/cust_bill.pm: correct erroneous line dupplication on
+ invoices
+
+2008-10-16 15:45 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add an option to use duration instead
+ of billsec to calculate billable time, RT#4147
+
+2008-10-15 22:29 ivan
+
+ * FS/FS/Conf_compat17.pm: sync Conf_compat17.pm
+
+2008-10-15 22:29 ivan
+
+ * FS/FS/Conf.pm, httemplate/misc/payment.cgi,
+ httemplate/search/cust_pay_batch.cgi,
+ httemplate/view/cust_main/payment_history.html: add
+ batch-enable_payby and realtime_disable_payby for better control
+ over hybrid realtime/batch installs; deprecate never-used
+ paymentforcedtobatch, RT#4052
+
+2008-10-15 22:04 ivan
+
+ * httemplate/elements/menu.html: add batch-enable_payby and
+ realtime_disable_payby for better control over hybrid
+ realtime/batch installs; deprecate never-used
+ paymentforcedtobatch, RT#4052
+
+2008-10-14 14:27 ivan
+
+ * FS/FS/Tron.pm: not interested in payment gateway survey just now
+
+2008-10-13 17:50 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/cust_main-import.cgi: add an
+ import format for external services, including next bill date
+ (cust_pkg.bill), RT#4108
+
+2008-10-13 14:58 ivan
+
+ * FS/: bin/freeside-fetch, FS/Conf.pm: Change subject for
+ freeside-fetch emailed reports from "subject" to "Freeside
+ report", and add email_report-subject config to change it.
+ RT#4093
+
+2008-10-12 16:56 jeff
+
+ * conf/invoice_latex: better column widths and easier maintenance
+
+2008-10-12 14:22 jeff
+
+ * conf/invoice_latex: better value for non-broken tetex
+
+2008-10-12 12:43 jeff
+
+ * conf/longtable.sty.patch: check not just for fit, but move the
+ goalposts as well
+
+2008-10-11 17:58 ivan
+
+ * httemplate/browse/cust_main_county.cgi: fix link
+
+2008-10-11 17:54 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/bulk-cust_main_county.html,
+ edit/process/bulk-cust_main_county.html: add a quick bulk tax add
+ tool (eating my own dogfood instead of running a one-off SQL
+ query), RT#4117
+
+2008-10-10 17:32 ivan
+
+ * FS/FS/: Conf.pm, cust_pkg.pm: enable suspension notices to an
+ administrator, RT#4083
+
+2008-10-10 16:30 ivan
+
+ * FS/FS/cust_pkg.pm: quick kludge to eliminate exact duplicates in
+ h_labels_short in an effort to reduce the number of "XXX service
+ listing twice on invoice" incidents, RT#3944. still should be
+ possible to fundamentally do better with the function in the
+ first place
+
+2008-10-10 14:30 jeff
+
+ * conf/: invoice_latex, longtable.sty.patch: avoid overprinting
+ remittance coupons
+
+2008-10-10 12:25 ivan
+
+ * FS/FS/cust_bill.pm: add options to auto-generate agent_custid and
+ display it as the customer number, RT#4099
+
+2008-10-09 18:15 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm,
+ FS/FS/UI/Web/small_custview.pm, httemplate/index.html,
+ httemplate/view/cust_main/misc.html, FS/FS/UI/Web.pm,
+ httemplate/edit/cust_main.cgi, httemplate/search/cust_main.cgi:
+ add options to auto-generate agent_custid and display it as the
+ customer number, RT#4099
+
+2008-10-09 13:06 ivan
+
+ * FS/FS/part_export/sqlradius.pm: use Freeradius := attribute for
+ ALL attributes except Password. Crypt-Password, User-Password,
+ Password-With-Header should now use := instead of ==. RT#4051
+
+2008-10-07 16:57 ivan
+
+ * httemplate/misc/: cdr-import.html, process/cdr-import.html: put
+ each CDR web import into a batch
+
+2008-10-07 16:23 ivan
+
+ * FS/FS/cdr/: genband.pm, nextone.pm: also set billsec for nextone
+ CDR format
+
+2008-10-06 17:10 ivan
+
+ * FS/FS/Upgrade.pm: oops, brainfart
+
+2008-10-06 17:09 ivan
+
+ * FS/FS/Upgrade.pm: when setting last_login/last_logout, ensure
+ only accounts actually attached to the export are updated
+
+2008-10-06 15:48 ivan
+
+ * FS/FS/svc_acct.pm: make RADIUS password exports
+ _password_encoding-aware so we export Password-With-Header when
+ necessary
+
+2008-10-06 15:19 ivan
+
+ * FS/FS/svc_acct.pm: make RADIUS password exports
+ _password_encoding-aware so we export Password-With-Header when
+ necessary
+
+2008-10-06 08:28 ivan
+
+ * FS/FS/: cdr.pm, cdr/netcentrex.pm: add initial netcentrex CDR
+ format
+
+2008-10-05 14:36 ivan
+
+ * httemplate/search/pay_batch.cgi: fix links to closed batches,
+ RT#4052
+
+2008-10-05 03:17 ivan
+
+ * httemplate/search/phone_avail.html: adding the start of available
+ phone# search. still needs a menu entry, search options page...
+ RT#3925
+
+2008-10-04 23:07 ivan
+
+ * httemplate/: edit/elements/ApplicationCommon.html,
+ view/cust_main/payment_history/credit.html,
+ view/cust_main/payment_history/payment.html: finish UI
+ improvements wrt refunds: now you have to post a check or cash
+ refund explicitly, no more implicit creation by 'applying'
+ credits. don't show useless application links. don't enable
+ apply button until you pick an invoice/refund. RT#3812
+
+2008-10-04 15:35 ivan
+
+ * FS/FS/: Misc.pm, cust_bill_ApplicationCommon.pm,
+ payinfo_transaction_Mixin.pm, Misc/prune.pm, rate_detail.pm,
+ usage_class.pm, part_event/Action.pm: POD cleanups
+
+2008-10-04 13:55 ivan
+
+ * httemplate/edit/rate_region.cgi: fix inappropriate rounding when
+ editing rates for a whole region
+
+2008-10-04 13:43 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add disable_tollfree option
+
+2008-10-03 17:30 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix recurring box graying out on
+ package customize
+
+2008-10-03 12:41 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add debugging
+
+2008-09-30 14:05 jeff
+
+ * httemplate/: search/report_newtax.cgi, search/cust_bill_pkg.cgi,
+ search/report_newtax.html, elements/menu.html: simple reporting
+ for new tax system
+
+2008-09-30 13:22 jeff
+
+ * FS/FS/: Conf.pm, cust_main.pm: option for no postal fee on
+ one-time charges
+
+2008-09-30 13:17 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/: bill.html, selfservice.cgi:
+ turn on and off postal billing from self-service
+
+2008-09-28 20:41 ivan
+
+ * httemplate/misc/delay_susp_pkg.html: use init_calendar.html
+
+2008-09-26 20:01 jeff
+
+ * httemplate/edit/process/addr_block/manual_flag.cgi,
+ FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/addr_block.pm,
+ FS/FS/svc_broadband.pm, httemplate/browse/addr_block.cgi,
+ httemplate/edit/svc_broadband.cgi: per address block ip auto
+ assignment and auto router selection
+
+2008-09-25 20:54 jeff
+
+ * FS/FS/part_event/Condition/dundate.pm,
+ httemplate/misc/delay_susp_pkg.html, FS/FS/AccessRight.pm,
+ FS/FS/Schema.pm, FS/FS/cust_main.pm, FS/FS/part_bill_event.pm,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/misc/process/delay_susp_pkg.html,
+ httemplate/view/cust_main/packages.html: push out event triggered
+ suspensions
+
+2008-09-25 16:44 jeff
+
+ * FS/FS/cust_main.pm: lost bits of reason
+
+2008-09-24 19:27 jeff
+
+ * FS/FS/part_export/prizm.pm: prizm export improvement for package
+ changes
+
+2008-09-18 16:17 jeff
+
+ * FS/FS/Schema.pm: trade space for time
+
+2008-09-16 08:58 jeff
+
+ * httemplate/search/report_tax.cgi: minor initialization issue
+
+2008-09-15 18:22 jeff
+
+ * httemplate/: edit/part_pkg.cgi, edit/elements/edit.html,
+ elements/tr-select-taxoverride.html,
+ elements/tr-select-taxproduct.html: correct package editor when
+ taxproducts off
+
+2008-09-15 00:18 ivan
+
+ * FS/FS/Schema.pm, FS/FS/Record.pm, FS/FS/phone_avail.pm,
+ FS/FS/part_export/internal_diddb.pm,
+ httemplate/elements/menu.html,
+ httemplate/misc/phone_avail-import.html,
+ httemplate/misc/process/phone_avail-import.html: add internal did
+ database & ability to query for availability, plus upload tool
+
+2008-09-14 17:40 ivan
+
+ * FS/FS/part_export/globalpops_voip.pm: add dry_run option to
+ globalpops_voip export
+
+2008-09-14 13:24 ivan
+
+ * FS/FS/cust_main_invoice.pm: silently strip out leading and
+ trailing spaces from invoicing email addresses instead of
+ throwing an error
+
+2008-09-14 13:20 ivan
+
+ * httemplate/config/: config-process.cgi, config-view.cgi: don't
+ reload the whole page every time a config option is changed,
+ RT#3989
+
+2008-09-14 12:13 ivan
+
+ * httemplate/elements/header.html: default the menu to top in 1.9,
+ still a pref
+
+2008-09-12 15:53 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: just give up and try again tommorow,
+ "1011" came from us not the CDRs anyway, RT#3985
+
+2008-09-12 15:48 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: not enough sleep to support multiple
+ internal_prefixen, RT#3985
+
+2008-09-12 15:38 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: not enough sleep to support multiple
+ internal_prefixen, RT#3985
+
+2008-09-12 15:18 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: grr, TRY to support multiple
+ internal_prefixen, RT#3985
+
+2008-09-12 14:56 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: support multiple internal_prefixen,
+ RT#3985
+
+2008-09-12 14:55 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: support multiple internal_prefixen
+
+2008-09-12 00:58 ivan
+
+ * FS/FS/: Conf.pm, cust_pkg.pm: make the max # of indivudal
+ services printed on invoices configurable. RT#3904
+
+2008-09-12 00:07 ivan
+
+ * FS/FS/: part_pkg/flat.pm, part_pkg/voip_cdr.pm, cust_main.pm:
+ don't throw noisy warnings about missing new recur_temporality,
+ RT#3851
+
+2008-09-11 19:28 jeff
+
+ * FS/: FS/Schema.pm, FS/cust_bill.pm, FS/cust_bill_pkg.pm,
+ FS/cust_bill_pkg_display.pm, MANIFEST, FS/cust_main.pm,
+ t/cust_bill_pkg_display.t: re-repurpose cust_bill_pkg
+
+2008-09-11 19:01 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/Conf.pm,
+ httemplate/misc/spool_invoices.cgi,
+ httemplate/search/cust_bill.html: add billco respooling, not
+ re-FTPing, RT#3971
+
+2008-09-11 17:53 ivan
+
+ * FS/FS/part_pkg/: flat.pm, voip_cdr.pm: add recur_temporality to
+ flat.pm, RT#3851
+
+2008-09-11 17:41 ivan
+
+ * FS/FS/cust_main.pm: correct a (fortunately harmless) typo
+
+2008-09-10 01:33 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/Conf.pm,
+ httemplate/misc/ftp_invoices.cgi,
+ httemplate/search/cust_bill.html: add re-FTP reprint,
+ RT#create-me-tommorow-for-enet
+
+2008-09-10 00:55 ivan
+
+ * FS/FS/Schema.pm: better (?) place to put display and taxation
+ data than overloading real line items
+
+2008-09-10 00:32 ivan
+
+ * FS/FS/part_pkg.pm: well, allow things to work for now so work can
+ get done
+
+2008-09-10 00:30 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add upcoming/preceding option,
+ RT#3851
+
+2008-09-10 00:24 ivan
+
+ * FS/FS/cust_main.pm: add upcoming/preceding option, RT#3851
+
+2008-09-09 15:35 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: allow implied primary services to
+ log into selfservice when selfservice_server-primary_only is on
+
+2008-09-09 14:29 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: this should allow implied primary
+ services to log into selfservice when
+ selfservice_server-primary_only is on
+
+2008-09-09 14:04 ivan
+
+ * FS/FS/Upgrade.pm: show which _upgrade_data sub is being run
+
+2008-09-09 01:19 ivan
+
+ * FS/FS/Schema.pm: wtf, cust_pkg_reason has no indices?!
+ _upgrade_data is hosing cpu badly
+
+2008-09-08 19:35 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: doh, forgot to display new options,
+ RT#3838
+
+2008-09-08 19:24 ivan
+
+ * FS/FS/: cdr.pm, cdr/taqua.pm, part_pkg/voip_cdr.pm: additional
+ QIS/Taqua-specific CDR handling details, RT#3838
+
+2008-09-08 14:46 ivan
+
+ * FS/FS/cust_main.pm: oops, debugging got left on by accident
+
+2008-09-08 14:23 ivan
+
+ * httemplate/view/elements/svc_Common.html: also hide fixed+blank
+ fields on service view, RT#3829
+
+2008-09-08 14:02 ivan
+
+ * httemplate/edit/elements/svc_Common.html: completely hide
+ fixed+blank fields, RT#3829
+
+2008-09-07 19:49 ivan
+
+ * httemplate/edit/quick-charge.html: extraneous code cleanup
+
+2008-09-07 19:48 ivan
+
+ * FS/FS/cust_bill_pkg.pm: removing unacceptable display fields from
+ cust_bill_pkg
+
+2008-09-07 19:47 ivan
+
+ * FS/FS/: AccessRight.pm, cust_main.pm: add package invoice details
+ & comments, RT#3810
+
+2008-09-07 19:42 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_pkg_detail.pm, FS/MANIFEST,
+ FS/t/cust_pkg_detail.t, httemplate/pref/pref-process.html,
+ httemplate/pref/pref.html,
+ httemplate/view/cust_main/packages.html, FS/FS.pm,
+ httemplate/edit/cust_pkg_detail.html,
+ httemplate/edit/process/cust_pkg_detail.html, FS/FS/cust_pkg.pm:
+ add package invoice details & comments, RT#3810
+
+2008-09-06 13:54 ivan
+
+ * FS/FS/UI/Web.pm: don't link to customer service view unless the
+ user has the ACL to view the resulting page
+
+2008-09-04 06:29 jeff
+
+ * FS/FS/Upgrade.pm: three lost lines
+
+2008-09-03 20:10 ivan
+
+ * httemplate/edit/invoice_logo.html: ask for an EPS for EPS upload,
+ not incorrectly a PNG
+
+2008-09-03 19:44 ivan
+
+ * httemplate/edit/process/invoice_logo.html: fix invoice uplaoding
+ in light of database config where you absolutely need
+ ->set_binary for swtuf retreived with ->config_binary, RT#3936
+
+2008-09-03 12:08 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/access_right.pm, FS/FS/addr_block.pm,
+ FS/FS/router.pm, httemplate/browse/addr_block.cgi,
+ httemplate/browse/router.cgi, httemplate/browse/svc_acct_pop.cgi,
+ httemplate/edit/allocate.html, httemplate/edit/router.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/process/router.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/addr_block/add.cgi,
+ httemplate/edit/process/addr_block/allocate.cgi,
+ httemplate/edit/process/addr_block/deallocate.cgi,
+ httemplate/edit/process/addr_block/split.cgi,
+ httemplate/elements/menu.html: new access right names
+
+2008-09-03 11:59 jeff
+
+ * FS/FS/: Upgrade.pm, cust_pkg_reason.pm: system only reason update
+ routine
+
+2008-09-02 18:52 ivan
+
+ * httemplate/view/cust_main/payment_history.html: add back ability
+ to post a check/cash refund. be more explicit about it instead of
+ just being a checkbox when posting a credit. RT#3812
+
+2008-09-02 18:46 ivan
+
+ * FS/FS/payby.pm, httemplate/edit/cust_pay.cgi,
+ httemplate/edit/cust_refund.cgi,
+ httemplate/edit/process/cust_refund.cgi,
+ httemplate/elements/init_calendar.html,
+ httemplate/view/cust_refund.html,
+ httemplate/view/cust_main/payment_history/refund.html,
+ FS/FS/AccessRight.pm: add back ability to post a check/cash
+ refund. be more explicit about it instead of just being a
+ checkbox when posting a credit. RT#3812
+
+2008-09-02 08:37 jeff
+
+ * FS/FS/: cust_bill.pm, cust_bill_pkg.pm, ClientAPI/MyAccount.pm:
+ call details in self-service
+
+2008-08-30 14:34 jeff
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_main.pm, FS/FS/Report/Table/Monthly.pm,
+ FS/FS/part_pkg/voip_cdr.pm, httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_prepaid_income.cgi,
+ httemplate/search/report_tax.cgi: remove duplicate cust_bill_pkg
+ creation RT#3919
+
+2008-08-29 19:10 jeff
+
+ * FS/FS/cust_bill_pkg.pm, FS/FS/cust_main.pm, FS/FS/tax_rate.pm,
+ httemplate/edit/process/part_pkg.cgi: bug squashing for multiple
+ usage classes
+
+2008-08-29 16:13 ivan
+
+ * FS/FS/part_export/acct_freeside.pm: adding fs-to-fs provisioning
+ of simple accounts for cheepnet, RT#3805
+
+2008-08-29 13:10 ivan
+
+ * httemplate/elements/tr-pkg_svc.html: increase maxlength and size
+ of quantity fields on package edit, for RT#3805
+
+2008-08-28 18:09 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cdr.pm, bin/cdr.sftp_and_import,
+ httemplate/elements/select-cdrbatch.html,
+ httemplate/elements/tr-select-cdrbatch.html,
+ httemplate/search/cdr.html, httemplate/search/report_cdr.html:
+ add CDR batch TFTP feature, RT#3113
+
+2008-08-28 17:45 jeff
+
+ * FS/FS/part_pkg.pm: noise reduction
+
+2008-08-28 17:23 ivan
+
+ * httemplate/elements/: tr-select-taxclass.html,
+ select-taxclass.html: correct nits in tax class selection
+
+2008-08-28 15:00 jeff
+
+ * FS/FS/tax_rate.pm: updates can be completely empty
+
+2008-08-28 14:32 jeff
+
+ * FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ httemplate/browse/part_pkg_taxproduct.cgi,
+ httemplate/edit/part_pkg_taxoverride.html,
+ httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/elements/select-taxoverride.html,
+ httemplate/elements/select-taxproduct.html,
+ httemplate/view/cust_main/packages.html: taxproduct selection for
+ one time charges
+
+2008-08-28 12:09 ivan
+
+ * FS/FS/: Tron.pm, Yori.pm: payment gateway survey
+
+2008-08-28 00:38 jeff
+
+ * httemplate/elements/select-taxoverride.html,
+ httemplate/elements/select-taxproduct.html,
+ httemplate/elements/tr-select-taxoverride.html,
+ httemplate/elements/tr-select-taxproduct.html, FS/FS/Schema.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_pkg/voip_cdr.pm,
+ httemplate/browse/part_pkg_taxproduct.cgi,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_pkg_taxoverride.html,
+ httemplate/edit/process/part_pkg.cgi: multiple usage classes
+ checkpoint
+
+2008-08-26 17:15 ivan
+
+ * FS/FS/cust_main.pm: don't override countrydefault or whatever
+ with a blank value in bulk customer import
+
+2008-08-26 17:05 ivan
+
+ * httemplate/elements/mcp_lint.html: add unchecked vs. ok
+ distinction to lint
+
+2008-08-26 17:00 ivan
+
+ * httemplate/elements/mcp_lint.html: add unchecked vs. ok
+ distinction to lint
+
+2008-08-26 16:53 ivan
+
+ * FS/FS/Tron.pm, httemplate/elements/mcp_lint.html: add unchecked
+ vs. ok distinction to lint
+
+2008-08-26 06:59 rsiddall
+
+ * rpm/freeside.spec: More changes to the self-service RPMs, mostly
+ fixing up paths so the RPM-installed self-service files are not
+ under /usr/local on the remote machine. Also fixed an
+ initialization problem where the system configuration files for
+ Freeside were assumed to be under /etc/default, not
+ /etc/sysconfig
+
+2008-08-25 14:23 ivan
+
+ * httemplate/edit/elements/edit.html: fix package editor showing
+ "all" for pkg class selection
+
+2008-08-25 13:33 ivan
+
+ * FS/FS/part_event/Condition/cust_bill_has_service.pm: fix
+ comparison from svcnum to svcpart
+
+2008-08-24 22:53 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/Report/Table/Monthly.pm,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_prepaid_income.cgi,
+ httemplate/search/report_tax.cgi: correct fallout from duplicate
+ line items
+
+2008-08-24 22:18 jeff
+
+ * httemplate/search/cust_tax_exempt_pkg.cgi: correct fallout from
+ agent virtualizing packages
+
+2008-08-24 15:35 ivan
+
+ * httemplate/elements/checkboxes-table-name.html: add controls to
+ select/unselect/toggle all checkboxes
+
+2008-08-24 14:52 ivan
+
+ * bin/customer-faker: add -k option for pkgpart
+
+2008-08-24 14:49 ivan
+
+ * bin/customer-faker: add -a option for agentnum
+
+2008-08-23 20:41 rsiddall
+
+ * rpm/freeside.spec: Create discrete RPMs for different parts of
+ the self-service interface. Put the default configuration folder
+ in the main freeside RPM.
+
+2008-08-23 14:59 jeff
+
+ * FS/FS/Mason.pm, FS/FS/Schema.pm, FS/FS/usage_class.pm,
+ FS/FS/Setup.pm, FS/FS/Upgrade.pm, FS/FS/rate_detail.pm,
+ FS/t/usage_class.t, httemplate/browse/usage_class.html, FS/FS.pm,
+ FS/MANIFEST, httemplate/browse/rate_detail.html,
+ httemplate/edit/rate_detail.html,
+ httemplate/edit/rate_region.cgi,
+ httemplate/edit/usage_class.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/rate_region.cgi,
+ httemplate/edit/process/usage_class.html,
+ httemplate/elements/menu.html: add usage classes to rate details
+
+2008-08-22 20:29 jeff
+
+ * FS/FS/: Record.pm, cust_main.pm, part_pkg_taxrate.pm,
+ tax_rate.pm: tax data update bug fixes and error message
+ improvements
+
+2008-08-21 20:01 ivan
+
+ * FS/FS/Mason.pm, FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/Tron.pm,
+ FS/FS/cust_svc.pm, FS/FS/cust_svc_option.pm, bin/tron-scan,
+ FS/MANIFEST, FS/t/cust_svc_option.t,
+ httemplate/elements/dashboard-toplist.html,
+ httemplate/elements/mcp_lint.html: the master control program has
+ chosen YOU to serve your system on the game grid
+
+2008-08-21 16:21 ivan
+
+ * FS/: FS/Yori.pm, bin/freeside-yori, MANIFEST: add the client-side
+ reporting for MCP mode
+
+2008-08-21 11:21 jeff
+
+ * bin/import-optigold.pl: use options with proper names
+
+2008-08-19 11:42 ivan
+
+ * FS/FS/svc_acct.pm: beter error messages for duplicate accounts
+
+2008-08-19 04:35 ivan
+
+ * FS/FS/cdr.pm: fix duration on simple/simple2 CDR formats
+
+2008-08-19 03:09 ivan
+
+ * httemplate/edit/process/rate_region.cgi: also don't neglext nxx
+ here
+
+2008-08-19 03:06 ivan
+
+ * FS/FS/rate_region.pm, httemplate/browse/rate_region.html,
+ httemplate/edit/rate_region.cgi: more consistent prefix display,
+ and don't forget nxx'
+
+2008-08-15 12:42 ivan
+
+ * Makefile: install default conf with make create-config too, so it
+ doesn't go missing
+
+2008-08-15 12:26 ivan
+
+ * FS/bin/freeside-setup: allow a full pathname to be specified to
+ freeside-setup for initial configdir
+
+2008-08-14 18:09 jeff
+
+ * FS/FS/tax_class.pm: correct field ordering - invonsequential
+
+2008-08-14 17:41 ivan
+
+ * httemplate/elements/form-file_upload.html: can have a message
+ then a URL too
+
+2008-08-14 04:53 ivan
+
+ * FS/FS/Schema.pm, FS/FS/UID.pm, FS/FS/cust_main.pm,
+ httemplate/elements/progress-init.html,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import.cgi,
+ httemplate/elements/progress-popup.html,
+ httemplate/search/cust_main.html,
+ httemplate/elements/form-file_upload.html,
+ httemplate/misc/file-upload.html,
+ httemplate/elements/file-upload.html: customer import: add
+ progress bar & redirect to a search of the imported customers,
+ #3475
+
+2008-08-14 04:44 ivan
+
+ * FS/FS/tax_rate.pm, httemplate/misc/tax-import.cgi: customer
+ import: add progress bar & redirect to a search of the imported
+ customers, #3475
+
+2008-08-13 18:58 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Record.pm, FS/FS/cust_main.pm,
+ httemplate/elements/menu.html,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import.cgi: import customer
+ from Excel file too
+
+2008-08-13 18:52 ivan
+
+ * FS/FS/svc_Common.pm: tyop
+
+2008-08-13 18:38 ivan
+
+ * httemplate/view/svc_forward.cgi: tyop
+
+2008-08-08 13:29 jeff
+
+ * bin/import-optigold.pl: better opti table relationship following
+
+2008-08-08 11:13 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_main.pm, FS/FS/part_pkg/voip_cdr.pm,
+ conf/invoice_latex: cdrs can be in separate invoice section,
+ after total, summarized inline, with hints for page breaks
+
+2008-08-07 15:30 ivan
+
+ * Makefile: don't generate a new key on install-selfservice if
+ there's already an RSA one either
+
+2008-08-05 23:39 jeff
+
+ * FS/FS/part_pkg/voip_cdr.pm: prevent adding 0 value line items
+
+2008-08-05 21:05 jeff
+
+ * FS/FS/cust_main.pm: fix bug(s) introduced with billing loop
+ refactor
+
+2008-08-02 19:15 ivan
+
+ * FS/FS/Schema.pm, FS/FS/svc_phone.pm,
+ httemplate/edit/svc_phone.cgi, httemplate/view/svc_phone.cgi: add
+ a name field to svc_phone
+
+2008-08-02 17:54 ivan
+
+ * FS/FS/cdr/simple2.pm: doh, fix regex
+
+2008-08-02 17:26 ivan
+
+ * FS/FS/: Record.pm: attempt to eliminate 'Can't call method
+ "exists" on an undefined value at
+ /usr/local/share/perl/5.8.8/FS/Record.pm line 812.' error on
+ upgrade
+
+2008-08-02 17:20 ivan
+
+ * FS/FS/Record.pm: attempt to eliminate 'Can't call method "exists"
+ on an undefined value at /usr/local/share/perl/5.8.8/FS/Record.pm
+ line 812.' error on upgrade
+
+2008-08-02 16:51 ivan
+
+ * FS/FS/: cdr.pm, cdr/asterisk.pm, cdr/genband.pm,
+ cdr/genband_meetme.pm, cdr/nextone.pm, cdr/openser.pm,
+ cdr/simple.pm, cdr/taqua.pm, cdr/unitel.pm, cdr/simple2.pm: fix
+ 'Can't call method "parse" on an undefined value' error from CDR
+ format refactor
+
+2008-08-01 21:20 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_main.pm,
+ FS/FS/part_pkg/voip_cdr.pm, conf/invoice_html,
+ conf/invoice_latex, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/view/cust_main/billing.html: bundled package
+ presentation improvements
+
+2008-08-01 21:09 jeff
+
+ * FS/FS/: Schema.pm, Upgrade.pm, cust_bill.pm, cust_bill_pkg.pm,
+ cust_bill_pkg_detail.pm, cust_main.pm, part_pkg.pm,
+ part_pkg/voip_cdr.pm: improve CDR usage presentation
+
+2008-08-01 14:41 ivan
+
+ * FS/FS/cust_main.pm: fix receivables report: credits/etc. should
+ be limited by date like before, closes: Bug#3801
+
+2008-08-01 13:21 ivan
+
+ * httemplate/edit/pkg_class.html: categories deserve labels too
+
+2008-07-31 16:32 ivan
+
+ * httemplate/search/report_receivables.cgi: this should fix columns
+ not showing up in receivables report... not surea bout #3801
+ (credits/etc show up in all time periods)
+
+2008-07-31 13:17 ivan
+
+ * httemplate/search/report_receivables.cgi, FS/FS/cust_main.pm: fix
+ receivables report: credits/etc. should be limited by date like
+ before, closes: Bug#3801
+
+2008-07-30 19:35 ivan
+
+ * httemplate/misc/delete-customer.cgi: fix error on customer
+ deletion
+
+2008-07-30 15:10 ivan
+
+ * FS/FS/cdr/: nextone.pm, nt.pm: rename nt to nextone
+
+2008-07-29 13:00 jeff
+
+ * FS/FS/cust_bill.pm: correct amount for new charges total on
+ sectioned invoices
+
+2008-07-29 10:29 rsiddall
+
+ * rpm/freeside.spec: Self-Service files were reorganized; changed
+ the way we copy them into the buildroot.
+
+2008-07-24 09:40 jeff
+
+ * FS/FS/cust_bill.pm: ensure invoice line items are delivered in
+ line number order
+
+2008-07-23 07:41 jeff
+
+ * httemplate/edit/tax_rate.html: add disabled column to new tax
+ rates, false laziness elimination, and bug fixes - closes #3566
+
+2008-07-23 07:36 jeff
+
+ * FS/FS/Schema.pm, FS/FS/tax_rate.pm,
+ httemplate/browse/tax_rate.cgi,
+ httemplate/misc/enable_or_disable_tax.html,
+ httemplate/misc/process/enable_or_disable_tax.html: add disabled
+ column to new tax rates, false laziness elimination, and bug
+ fixes - closes #3566
+
+2008-07-22 01:33 ivan
+
+ * FS/FS/part_export/phone_shellcommands.pm: freepbx modification
+ command
+
+2008-07-21 21:59 ivan
+
+ * httemplate/view/svc_phone.cgi: add "incoming CDRs" link to phone#
+ view also
+
+2008-07-21 15:34 ivan
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ fs_selfservice/FS-SelfService/cgi/success.html: svc_phone signup
+
+2008-07-21 14:23 ivan
+
+ * Makefile: oops, don't inadvertantly switch default db type
+
+2008-07-21 12:09 ivan
+
+ * FS/FS/Conf.pm, httemplate/elements/select-did.html,
+ FS/FS/ClientAPI/MasonComponent.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ fs_selfservice/FS-SelfService/cgi/misc/areacodes.cgi,
+ fs_selfservice/FS-SelfService/cgi/misc/exchanges.cgi,
+ fs_selfservice/FS-SelfService/cgi/images/cross.png,
+ fs_selfservice/FS-SelfService/cgi/images/wait-orange.gif,
+ fs_selfservice/FS-SelfService/cgi/misc/phonenums.cgi: signup
+ w/globalpops DID selection via mason components pass-through
+
+2008-07-21 11:58 ivan
+
+ * FS/MANIFEST, htetc/handler.pl, FS/FS/CGI.pm, FS/FS/Mason.pm,
+ FS/FS/Mason/Request.pm, Makefile: add framework for running Mason
+ components standalone
+
+2008-07-21 03:42 ivan
+
+ * FS/FS/svc_phone.pm: generate a SIP password if it is blank
+
+2008-07-18 15:31 ivan
+
+ * httemplate/search/report_rt_transaction.html: missing closing
+ FORM tag
+
+2008-07-18 15:30 ivan
+
+ * httemplate/elements/popup_link.html: add target param, i thought
+ this was needed for something...
+
+2008-07-18 15:29 ivan
+
+ * bin/bind.import: add -e option to bind.import (now to actually
+ implement it)
+
+2008-07-18 15:28 ivan
+
+ * FS/FS/rate_region.pm: show NXX is US if applicable
+
+2008-07-18 15:28 ivan
+
+ * FS/FS/: h_cust_svc.pm, part_export.pm, part_pkg.pm, svc_acct.pm,
+ UI/Web.pm: some random cleanups
+
+2008-07-18 15:27 ivan
+
+ * FS/FS/Record.pm: add no_check_foreign kludge for gigantic rate
+ imports
+
+2008-07-18 15:26 ivan
+
+ * FS/MANIFEST: add part_pkg_link to MANIFEST
+
+2008-07-17 16:55 ivan
+
+ * FS/FS/: cdr.pm, cdr/asterisk.pm, cdr/genband.pm,
+ cdr/genband_meetme.pm, cdr/nt.pm, cdr/openser.pm, cdr/simple.pm,
+ cdr/taqua.pm, cdr/unitel.pm: CDR updates; modularize CDR import
+ formats; add formats for OpenSER, Genband/Tekelec, and "NT"
+
+2008-07-16 16:55 ivan
+
+ * httemplate/search/svc_acct.cgi: fix account search by time
+ remaining to deal with situations w/o a recurring amount
+
+2008-07-15 16:25 ivan
+
+ * FS/FS/Upgrade.pm: where in the world is $DBI::errstr
+
+2008-07-15 16:18 ivan
+
+ * FS/FS/Upgrade.pm: parens help alot
+
+2008-07-15 16:17 ivan
+
+ * FS/FS/Upgrade.pm: report errors connecting to sqlradius dbs on
+ upgrade
+
+2008-07-15 13:56 ivan
+
+ * FS/FS/cust_main.pm: prevent inactive customers from showing up in
+ reports of cancelled customers
+
+2008-07-14 18:19 ivan
+
+ * FS/FS/part_export/phone_shellcommands.pm: add warning about
+ concurrency in FreePBX
+
+2008-07-14 16:59 ivan
+
+ * httemplate/view/cust_main/notes.html: fuck embedded iframes and
+ their stupid display problems with scrolling. also make the
+ gridding more consistent
+
+2008-07-14 16:08 ivan
+
+ * httemplate/: edit/process/cust_main_note.cgi, view/cust_main.cgi,
+ view/cust_main/notes.html: fuck embedded iframes and their stupid
+ display problems with scrolling. also make the gridding more
+ consistent
+
+2008-07-10 11:48 ivan
+
+ * httemplate/view/cust_main/packages.html: fix variable scoping
+ issues preventing customer view page from coing up
+
+2008-07-09 20:16 jeff
+
+ * FS/FS/cust_bill.pm: restore line item date ranges
+
+2008-07-09 13:37 ivan
+
+ * FS/FS/part_pkg.pm: should avoid spurious uninitialized value
+ warnings on upgrade
+
+2008-07-09 13:33 ivan
+
+ * FS/FS/svc_Common.pm: perl vs SQL brainfart
+
+2008-07-09 12:45 ivan
+
+ * httemplate/docs/license.html: fix famfamfam link
+
+2008-07-09 12:35 ivan
+
+ * FS/FS/svc_Common.pm: service searching should be case-insensitive
+ now
+
+2008-07-08 20:40 ivan
+
+ * httemplate/search/: cust_tax_exempt.cgi: helpful to see when
+ exemptions were inserted?
+
+2008-07-08 20:27 ivan
+
+ * httemplate/search/cust_tax_exempt.cgi: need the exemptnum...
+
+2008-07-08 20:18 ivan
+
+ * httemplate/search/: cust_tax_exempt.cgi, cust_tax_exempt.html:
+ search legacy tax exemptions by customer status
+
+2008-07-08 19:30 ivan
+
+ * httemplate/edit/process/part_pkg.cgi: don't require an agent type
+ to be specified when editing a disabled package
+
+2008-07-07 19:19 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: fix line-item reports on
+ taxclass-less regions
+
+2008-07-07 19:01 ivan
+
+ * FS/FS/cust_main_county.pm, httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/report_tax.cgi: fix line-item reports on
+ taxclass-less regions
+
+2008-07-07 17:35 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: order by number for line
+ items with the same datestamp
+
+2008-07-07 17:20 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: order line item reports by
+ date
+
+2008-07-07 16:47 ivan
+
+ * httemplate/search/report_tax.cgi: should be a proper fix for edge
+ cases where you have taxclass and empty-taxclass rates for a
+ region, whew
+
+2008-07-07 14:38 ivan
+
+ * FS/FS/Record.pm: SQL_FLOAT is probably unnecessary and causes
+ probelms on old (v1.x?) DBD::Pg
+
+2008-07-07 14:18 ivan
+
+ * FS/FS/Record.pm: eek, hopefully fix problems caused by adding
+ debugging of bind_param statements
+
+2008-07-07 14:07 ivan
+
+ * FS/FS/Record.pm: add debugging of bind_param statements
+
+2008-07-07 12:50 ivan
+
+ * FS/FS/Record.pm: add debugging of bind_param statements
+
+2008-07-03 16:23 ivan
+
+ * httemplate/view/cust_main/packages.html: fix bad sub names in
+ forward-port
+
+2008-07-02 21:19 ivan
+
+ * FS/FS/Record.pm: should FINALLY get binding correctly in light of
+ regression caused by get_real_fields refactor
+
+2008-07-02 21:12 ivan
+
+ * FS/FS/Record.pm: this should non-"=" searches on fields that
+ require SQL type binding...
+
+2008-07-02 21:00 ivan
+
+ * FS/FS/cust_pkg.pm: correct hash vs hashref brainfart on
+ "forward-port", i guess
+
+2008-07-02 20:57 ivan
+
+ * FS/FS/Record.pm: real should be bound to SQL_FLOAT Like float4...
+ 1.7? not touching it unless it breaks :)
+
+2008-07-01 19:55 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix errors paying with an on-file
+ card through self-service
+
+2008-07-01 00:02 jeff
+
+ * FS/FS/cust_pkg.pm: you shouldn't keep 'em separated
+
+2008-06-30 22:01 jeff
+
+ * httemplate/misc/unadjourn_pkg.cgi,
+ httemplate/misc/unexpire_pkg.cgi, FS/FS/Schema.pm,
+ FS/FS/cust_pkg.pm, FS/FS/cust_pkg_reason.pm,
+ FS/FS/part_export/shellcommands.pm,
+ FS/FS/part_export/sqlradius.pm,
+ httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/misc/process/cancel_pkg.html,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/view/cust_main/packages.html: correct internal reason
+ searching, prevent interleaved suspend/cancel/expire/adjourn,
+ backporting and refactoring
+
+2008-06-30 17:11 ivan
+
+ * FS/FS/svc_phone.pm: that should fix new sip_password field, whew
+
+2008-06-30 17:07 ivan
+
+ * FS/FS/svc_phone.pm: that should fix the new sip_password field, i
+ hope
+
+2008-06-30 17:00 ivan
+
+ * httemplate/view/svc_phone.cgi: add sip pw display
+
+2008-06-30 16:56 ivan
+
+ * FS/FS/Schema.pm, FS/FS/svc_phone.pm,
+ FS/FS/part_export/phone_shellcommands.pm,
+ httemplate/edit/svc_phone.cgi: add sip pw field
+
+2008-06-30 01:01 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/: signup.cgi, signup.html:
+ checkpoint signup work
+
+2008-06-30 01:00 ivan
+
+ * FS/FS/part_export/phone_shellcommands.pm: reload after adding
+ extensions
+
+2008-06-29 13:53 ivan
+
+ * FS/FS/svc_phone.pm, FS/FS/part_export/globalpops_voip.pm,
+ httemplate/elements/select-phonenum.html,
+ httemplate/elements/tr-select-did.html: globalPOPs provisioning
+
+2008-06-28 21:33 jeff
+
+ * httemplate/view/cust_main/packages.html: spurious 'suspended'
+
+2008-06-28 17:41 ivan
+
+ * FS/: MANIFEST, FS.pm, t/phone_avail.t, FS/Schema.pm,
+ FS/phone_avail.pm, FS/part_export/globalpops_voip.pm:
+ state->areacode caching,
+
+2008-06-28 16:03 ivan
+
+ * httemplate/images/wait-orange.gif, FS/FS/part_svc.pm,
+ httemplate/edit/elements/svc_Common.html,
+ httemplate/elements/input-text.html,
+ httemplate/elements/select-areacode.html,
+ httemplate/elements/select-did.html,
+ httemplate/elements/select-exchange.html,
+ httemplate/elements/select-phonenum.html,
+ httemplate/elements/select-state.html,
+ httemplate/elements/tr-input-text.html,
+ httemplate/elements/tr-select-did.html,
+ httemplate/misc/areacodes.cgi, httemplate/misc/exchanges.cgi,
+ httemplate/misc/phonenums.cgi, FS/FS/Record.pm,
+ FS/FS/part_export/globalpops_voip.pm,
+ httemplate/edit/svc_phone.cgi,
+ httemplate/edit/cust_main/select-state.html: get DIDs from
+ globalpops
+
+2008-06-28 12:25 jeff
+
+ * httemplate/elements/tr-checkboxes-table.html,
+ httemplate/elements/checkboxes-table.html,
+ httemplate/elements/menu.html,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-table.html, FS/FS/AccessRight.pm,
+ FS/FS/addr_block.pm, FS/FS/router.pm, FS/FS/svc_broadband.pm,
+ httemplate/browse/addr_block.cgi, httemplate/browse/router.cgi,
+ httemplate/browse/svc_acct_pop.cgi,
+ httemplate/edit/allocate.html, httemplate/edit/router.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_broadband.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/elements/svc_Common.html,
+ httemplate/edit/process/router.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/svc_broadband.cgi,
+ httemplate/edit/process/addr_block/add.cgi,
+ httemplate/edit/process/addr_block/allocate.cgi,
+ httemplate/edit/process/addr_block/deallocate.cgi,
+ httemplate/edit/process/addr_block/split.cgi,
+ httemplate/edit/process/elements/process.html: agent virtualize
+ address blocks and routers
+
+2008-06-27 01:53 ivan
+
+ * FS/FS/Conf.pm, FS/FS/ClientAPI/Signup.pm, fs_selfservice/DEPLOY,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.html: adding
+ signup_server-service config
+
+2008-06-27 00:18 ivan
+
+ * FS/FS/part_export/globalpops_voip.pm: globalpops_voip export
+ compilation fixes
+
+2008-06-26 17:27 ivan
+
+ * FS/FS/part_export/globalpops_voip.pm: commiting globalpops export
+ start. stupid power failure.
+
+2008-06-26 14:55 ivan
+
+ * FS/FS/part_export/phone_shellcommands.pm: adding
+ phone_shellcommands with preliminary FreePBX integration commands
+
+2008-06-25 13:14 ivan
+
+ * httemplate/search/report_receivables.cgi: optimize total query in
+ receivables report. very significant speedup for large DBs
+
+2008-06-25 13:11 ivan
+
+ * FS/FS/: cust_main.pm, cust_bill.pm: POD updates
+
+2008-06-25 11:14 ivan
+
+ * FS/FS/Upgrade.pm: don't show error messages about FreesideStatus
+ index already existing either
+
+2008-06-24 17:29 ivan
+
+ * htetc/handler.pl, FS/FS/Record.pm: finish adding
+ str2time_sql_closing
+
+2008-06-24 11:50 ivan
+
+ * conf/invoice_html: i think we need a $ there???
+
+2008-06-24 09:39 jeff
+
+ * FS/FS/: Conf.pm, Conf_compat17.pm, cust_main.pm: postal invoice
+ fees
+
+2008-06-23 19:09 ivan
+
+ * FS/FS/part_export/sqlradius.pm: prevent decrementing
+ time/bandwidth for old RADIUS records
+
+2008-06-23 15:59 ivan
+
+ * bin/cdr.import: hahahd doh, we're in perl
+
+2008-06-23 15:11 ivan
+
+ * bin/cdr.import: add quick command line too for CDR imports
+
+2008-06-23 09:46 jeff
+
+ * conf/invoice_html: this is what it was for
+
+2008-06-23 08:36 jeff
+
+ * FS/FS/cust_bill.pm, conf/invoice_html, conf/invoice_latex:
+ invoice service address modifications
+
+2008-06-22 19:50 ivan
+
+ * conf/invoice_html: wtf was this for in the first place then
+
+2008-06-22 19:48 ivan
+
+ * conf/invoice_html: this seems to match the latex templates more
+ accurately, rather than push the sub-totals out into their own
+ column
+
+2008-06-22 19:35 ivan
+
+ * conf/invoice_html: fix leaking colspan in totals on sectioned
+ invoices
+
+2008-06-22 17:41 ivan
+
+ * FS/FS/cust_tax_exempt.pm: adding report on legacy tax exemptions
+ to assist in enet migraiton
+
+2008-06-22 17:37 ivan
+
+ * httemplate/search/cust_tax_exempt.cgi: legacy tax exemption
+ report fix, no _date
+
+2008-06-22 17:34 ivan
+
+ * httemplate/search/cust_tax_exempt.cgi: adding report on legacy
+ tax exemptions to assist in enet migraiton
+
+2008-06-19 22:47 jeff
+
+ * FS/FS/cust_bill.pm: extra values for invoices
+
+2008-06-19 20:36 ivan
+
+ * FS/FS/: cdr.pm, part_pkg/voip_cdr.pm: VoxLineSystems are lying
+ scum who charged back their customization work and then used the
+ software anyway
+
+2008-06-18 20:18 jeff
+
+ * FS/FS/pkg_category.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/part_pkg.pm, FS/FS/pkg_class.pm, FS/t/pkg_category.t,
+ FS/FS.pm, httemplate/browse/pkg_category.html,
+ httemplate/browse/pkg_class.html,
+ httemplate/edit/pkg_category.html,
+ httemplate/edit/pkg_class.html,
+ httemplate/edit/process/pkg_category.html, FS/MANIFEST,
+ htetc/handler.pl, httemplate/edit/elements/edit.html,
+ httemplate/elements/menu.html: package categories (meta package
+ classes) and grouping invoices by them
+
+2008-06-18 14:18 ivan
+
+ * FS/FS/Misc.pm: fix regression caused by use of IPC::Run to run
+ pslatex: send STDOUT and STDERR from pslatex to /dev/null, we
+ don't want them
+
+2008-06-18 12:24 ivan
+
+ * httemplate/edit/part_pkg.cgi: s helps alot
+
+2008-06-18 12:09 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix setup/recur fees on cloning
+ (customizing) package definitions w/new editor
+
+2008-06-18 11:50 jeff
+
+ * httemplate/: browse/tax_rate.cgi,
+ misc/enable_or_disable_tax.html,
+ misc/process/enable_or_disable_tax.html: allow enabling and
+ disabling if tax_rate rows in groups (RT 3566)
+
+2008-06-17 22:22 ivan
+
+ * FS/FS/cust_main.pm: %statuscolor is either a global or a my var,
+ make up your mind
+
+2008-06-17 17:49 ivan
+
+ * FS/FS/part_virtual_field.pm: this module, also, has no need to
+ import qsearch/qsearchs, and is causing dependency loop problems
+ (Record->part_virtual_field->Record)
+
+2008-06-17 17:46 ivan
+
+ * FS/FS/Record.pm: hopefully finally fix the dependency loops bs...
+ as simple as Record->Conf->Record here
+
+2008-06-17 17:42 ivan
+
+ * FS/FS/Msgcat.pm: REALLY, don't use FS::Conf from Msgcat until
+ runtime... should hopefully FINALLY eliminate the
+ Record->Msgcat->Conf->Record loop
+
+2008-06-17 17:36 ivan
+
+ * FS/FS/msgcat.pm: msgcat.pm doesn't actually need
+ qsearch/qsearchs... hopefully this is the last of the weird
+ dependency loops (this one is Record->Msgcat->msgcat->Record)
+
+2008-06-17 17:27 ivan
+
+ * FS/FS/Msgcat.pm: fix dependency loop problem with database
+ config, hopefully? (Record->Msgcat->Conf->Record)
+
+2008-06-17 17:10 ivan
+
+ * FS/FS/conf.pm: conf.pm doesn't actually need qsearch/qsearchs -
+ hopefully this will solve the weird circular dependency issue
+ (Record->Msgcat->Conf->conf->Record)
+
+2008-06-17 17:05 ivan
+
+ * httemplate/misc/xmlhttp-cust_main-address_standardize.html: turn
+ off debugging for address standardization
+
+2008-06-17 16:57 ivan
+
+ * httemplate/edit/part_pkg.cgi: don't lose the pricing on package
+ cloning w/new package editor
+
+2008-06-17 12:29 jeff
+
+ * conf/invoice_latex: fixup damage from quantity addition
+
+2008-06-16 20:35 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/edit/invoice_template.html,
+ FS/FS/ConfDefaults.pm, FS/FS/Misc.pm, FS/FS/cust_main.pm,
+ htetc/handler.pl, httemplate/elements/htmlarea.html,
+ httemplate/misc/email-customers.html,
+ httemplate/misc/process/email-customers.html,
+ httemplate/search/cust_main.html: finish adding a feature to
+ easily list all email addresses for an agent & send them email
+
+2008-06-16 20:13 jeff
+
+ * conf/invoice_latex: not forgetting to add fax and old customer id
+
+2008-06-16 18:43 ivan
+
+ * httemplate/edit/process/cust_main.cgi: have agent_custid editing
+ now
+
+2008-06-16 06:36 jeff
+
+ * bin/import-optigold.pl: catch one more customer
+
+2008-06-15 23:53 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi: add (with config)
+ ability to edit agent_custid
+
+2008-06-15 18:32 jeff
+
+ * bin/import-optigold.pl: ugh; cast about for svc/pkg linkages
+
+2008-06-12 16:15 ivan
+
+ * httemplate/edit/REAL_cust_pkg.cgi: fix visual regression not
+ displaying package and comment on date editing
+
+2008-06-12 14:53 ivan
+
+ * httemplate/: edit/process/elements/process.html,
+ view/cust_main/packages.html, edit/part_pkg.cgi,
+ edit/elements/edit.html, edit/process/part_pkg.cgi: fix cloning
+ w/new package editor
+
+2008-06-12 09:56 jeff
+
+ * bin/import-optigold.pl: date fixups
+
+2008-06-12 08:55 jeff
+
+ * bin/import-optigold.pl: import services from service providing
+ servers
+
+2008-06-10 16:24 ivan
+
+ * FS/FS/: Upgrade.pm: start of better error reporting for RADIUS
+ upgrade errors
+
+2008-06-10 10:39 ivan
+
+ * FS/FS/Misc.pm: turn off debugging that got left on by accident
+
+2008-06-09 19:12 ivan
+
+ * httemplate/edit/process/: cust_credit_refund.cgi,
+ cust_pay_refund.cgi: fix up application of things to refunds,
+ RT#3606/RT#3545
+
+2008-06-09 11:32 ivan
+
+ * FS/FS/cdr.pm: remove name from voxlinesystems2, really
+
+2008-06-05 15:44 ivan
+
+ * FS/FS/cdr.pm: add am/pm to voxlinesystems2 display format, remove
+ name, revsere src/dst
+
+2008-06-05 13:09 ivan
+
+ * FS/FS/: cust_main.pm, part_pkg/flat.pm: fix one-time charge
+ quantities &
+
+2008-06-05 12:44 ivan
+
+ * FS/FS/: cust_svc.pm, part_pkg/voip_cdr.pm: disable_src fixes
+
+2008-06-05 12:29 ivan
+
+ * FS/FS/Schema.pm: unit pricing didn't exist before, so it can be
+ NULL
+
+2008-06-05 12:25 ivan
+
+ * FS/FS/part_pkg/flat.pm: implement quantity charging for setup
+ fees
+
+2008-06-05 12:24 ivan
+
+ * FS/FS/cdr.pm, FS/FS/cust_main.pm, httemplate/search/cdr.html,
+ httemplate/view/svc_phone.cgi, httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi: voxlinesystems CDRs and
+ quantity bs
+
+2008-06-05 12:06 jeff
+
+ * conf/invoice_html: dash removal
+
+2008-06-05 10:05 jeff
+
+ * conf/invoice_html: fix unitprice/posttotal nit
+
+2008-06-05 09:56 jeff
+
+ * conf/invoice_html: fix unitprice/section nit
+
+2008-06-05 09:51 jeff
+
+ * conf/invoice_html: correct bogus porting
+
+2008-06-05 05:42 jeff
+
+ * conf/invoice_latex: replace lost braces
+
+2008-06-05 03:36 ivan
+
+ * FS/FS/cust_main.pm, httemplate/search/cust_main.html,
+ httemplate/search/report_cust_main.html: add customer status to
+ adv. customer report, template customer search for future use in
+ emailing notices, RT#2731
+
+2008-06-05 03:34 ivan
+
+ * FS/FS/: cust_pkg.pm: docs for search_sql
+
+2008-06-05 01:54 ivan
+
+ * httemplate/search/report_cust_bill.html: minor invoice report UI
+
+2008-06-04 22:06 ivan
+
+ * FS/FS/cust_pay.pm, httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_pay_refund.cgi,
+ httemplate/view/cust_main/payment_history/credit.html,
+ httemplate/view/cust_main/payment_history/payment.html,
+ httemplate/edit/cust_credit_refund.cgi,
+ httemplate/edit/elements/ApplicationCommon.html,
+ httemplate/edit/process/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/edit/process/cust_credit_refund.cgi,
+ httemplate/edit/process/cust_pay_refund.cgi,
+ httemplate/edit/process/elements/ApplicationCommon.html: payment
+ and credit applications have separate "apply to refund" choices
+ now, and no auto-refund choice in the invoice dropdown. RT#3545
+
+2008-06-04 15:44 jeff
+
+ * FS/FS/cust_bill.pm: moar tyop
+
+2008-06-04 15:42 jeff
+
+ * FS/FS/cust_bill.pm: tyop
+
+2008-06-04 11:50 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/misc/fax-invoice.cgi: this should
+ fix the random "HylaFax support has not been configured" error,
+ caused by cust_bill->fax getting called instead of cust_main->fax
+ field
+
+2008-06-04 11:40 jeff
+
+ * conf/invoice_html: more voxline invoice formatting
+
+2008-06-04 11:05 jeff
+
+ * FS/FS/cust_bill.pm: voxline invoice formatting
+
+2008-06-04 10:57 jeff
+
+ * FS/FS/cdr.pm, FS/FS/cust_bill_pkg.pm, FS/FS/part_pkg/voip_cdr.pm,
+ conf/invoice_html, conf/invoice_latex, FS/FS/Conf.pm,
+ FS/FS/Conf_compat17.pm: voxline invoice formatting
+
+2008-06-04 06:28 jeff
+
+ * FS/FS/: Record.pm, cust_main.pm, tax_rate.pm: tax on tax
+
+2008-06-04 06:26 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Conf_compat17.pm, FS/FS/cust_bill.pm,
+ conf/invoice_latex: service address on invoice
+
+2008-06-03 14:06 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/Schema.pm, FS/FS/cust_bill_pkg.pm,
+ FS/FS/cust_pkg.pm, httemplate/search/cust_pkg.cgi,
+ httemplate/view/cust_main/packages.html: very basic start at
+ adding quantities
+
+2008-06-02 11:59 ivan
+
+ * FS/FS/payinfo_transaction_Mixin.pm: fix payinfo_transaction
+
+2008-06-02 11:31 ivan
+
+ * FS/FS/UI/Web/small_custview.pm: fix ntable calls
+
+2008-06-02 10:58 ivan
+
+ * httemplate/misc/process/timeworked.html: fix error apply
+ fractional seconds
+
+2008-06-02 10:14 ivan
+
+ * FS/FS/UI/Web/small_custview.pm: doh!
+
+2008-06-02 10:06 ivan
+
+ * FS/FS/CGI.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/UI/Web/small_custview.pm, htetc/handler.pl,
+ rt/lib/RT/URI/freeside/Internal.pm,
+ rt/lib/RT/URI/freeside/XMLRPC.pm: badly placed small_custview all
+ of a sudden causing fatal errors?! wtf
+
+2008-06-02 04:16 jeff
+
+ * conf/invoice_latex, conf/invoice_latexcoupon, FS/FS/Conf.pm,
+ FS/FS/Conf_compat17.pm, FS/FS/cust_bill.pm: typeset tear-off
+ remittance coupon
+
+2008-06-01 19:47 ivan
+
+ * FS/FS/Misc.pm: and batchmode was probably right
+
+2008-06-01 19:45 ivan
+
+ * FS/FS/Misc.pm: yow, don't want everything to waitt until the
+ timeout
+
+2008-06-01 19:16 ivan
+
+ * FS/FS/: cust_bill.pm, Misc.pm: use IPC::Run to run pslatex & add
+ a timeout, this should prevent hanging on template errors
+
+2008-06-01 15:48 ivan
+
+ * FS/FS/cust_pay.pm, FS/FS/cust_refund.pm, FS/FS/payinfo_Mixin.pm,
+ FS/FS/payinfo_transaction_Mixin.pm,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/search/elements/cust_pay_or_refund.html,
+ httemplate/view/cust_refund.html,
+ httemplate/view/cust_main/payment_history/credit.html,
+ httemplate/view/cust_main/payment_history/invoice.html,
+ httemplate/view/cust_main/payment_history/payment.html,
+ httemplate/view/cust_main/payment_history/refund.html,
+ httemplate/view/cust_main/payment_history/voided_payment.html:
+ refactor payment history slightly, add refund receipts, have
+ "unapplied" refunds show like other unapplied/open things,
+ RT#3545
+
+2008-06-01 00:08 ivan
+
+ * FS/FS/cust_pay.pm: show "Check #" on payment receipts instead of
+ "Billing #"
+
+2008-05-31 22:43 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_bill_ApplicationCommon.pm,
+ httemplate/view/cust_main/payment_history.html: add date to
+ "applied to Invoice#" messages in history
+
+2008-05-31 20:19 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: fix line item report for
+ agent-virtualized packages, clean up sloppy $where
+ stringification, hard agent virtualization
+
+2008-05-31 19:19 jeff
+
+ * bin/import-optigold.pl: umm.. right.. really do some on-demand
+ stuff
+
+2008-05-31 18:23 ivan
+
+ * htetc/handler.pl: depend on CGI.pm 3.29 to fix RT attachment
+ problems
+
+2008-05-31 17:11 ivan
+
+ * FS/FS/cust_bill.pm: fix problems when service definition names
+ contain chars that need to be latex escaped
+
+2008-05-31 16:50 jeff
+
+ * bin/import-optigold.pl: guess at on demand billing, link
+ pre-existing services
+
+2008-05-31 10:54 ivan
+
+ * htetc/handler.pl: add an explicit use for RT's not-well-declared
+ dependency on CSS::Squish 0.06
+
+2008-05-31 07:49 jeff
+
+ * FS/FS/cust_bill.pm, conf/invoice_html, conf/invoice_latex:
+ invoice cosmetic improvements
+
+2008-05-29 21:04 ivan
+
+ * httemplate/edit/part_bill_event.cgi: 1.7 sucks. but people are
+ still going to be editing old-style invoice events for a little
+ while more yet, so space them out better (so options don't run
+ together)
+
+2008-05-29 20:55 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/edit/part_bill_event.cgi: 1.7
+ sucks. add a "balance over" option to the 1.7 style
+ agent-specific invoice send event
+
+2008-05-29 18:38 ivan
+
+ * FS/FS/Misc/prune.pm: fix a missing semicolon bug only triggered
+ when running prune_applications not in debug mode...
+
+2008-05-29 18:34 ivan
+
+ * FS/FS/Upgrade.pm: don't print out warnings about SQL RADIUS
+ FreesideStatus every time either. really?
+
+2008-05-29 18:33 ivan
+
+ * FS/bin/freeside-upgrade: don't print out the cust_credit_refund
+ pruning every time
+
+2008-05-29 18:28 ivan
+
+ * FS/bin/freeside-upgrade: don't print out the cust_credit_refund
+ pruning every time
+
+2008-05-29 18:02 ivan
+
+ * FS/FS/cust_pay_pending.pm: clean up any stray/old
+ cust_pay_pending records causing problems
+
+2008-05-29 17:53 ivan
+
+ * FS/FS/: Upgrade.pm, cust_pay_pending.pm: clean up any stray/old
+ cust_pay_pending records causing problems
+
+2008-05-28 17:11 ivan
+
+ * httemplate/graph/money_time.cgi: line things up better on the
+ 12mo report (prevent labels from taking up most of the graph
+
+2008-05-28 03:45 ivan
+
+ * htetc/handler.pl: mailgate realiability fix: don't bomb out when
+ FS dbdef hasn't been initialized yet (& need to import
+ adminsuidsetup)
+
+2008-05-28 03:41 ivan
+
+ * htetc/: handler.pl: mailgate realiability fix: don't bomb out
+ when FS dbdef hasn't been initialized yet
+
+2008-05-28 03:14 ivan
+
+ * htetc/handler.pl: mailgate realiability fix: don't bomb out when
+ FS dbdef hasn't been initialized yet
+
+2008-05-19 20:52 ivan
+
+ * FS/FS/Upgrade.pm: automatically create an index on the new
+ radacct.FreesideStatus column
+
+2008-05-19 15:31 jeff
+
+ * conf/invoice_latex, FS/FS/cust_bill_pkg.pm: fix broken pagenation
+
+2008-05-19 11:50 ivan
+
+ * FS/FS/Conf.pm: a better link to the T:T docs
+
+2008-05-18 21:29 ivan
+
+ * FS/FS/Schema.pm: add a key on ( history_action, $primary_key ) to
+ the h_ tables. this should speed up the cust_pay upgrade??
+
+2008-05-18 21:07 ivan
+
+ * FS/FS/cust_bill_pay.pm, FS/FS/payinfo_Mixin.pm,
+ FS/FS/cust_credit_refund.pm, FS/FS/cust_refund.pm,
+ FS/FS/payby.pm, FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/money_time.cgi,
+ httemplate/search/cust_bill_pay.html,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_credit_refund.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/cust_refund.html,
+ httemplate/search/elements/cust_pay_or_refund.html: make net
+ receipts clickable... and netreceipts != cashflow, really, so
+ separate those concepts, and cashflow gets gross & net variants.
+ also add gross/net refunds. #3012
+
+2008-05-18 20:51 jeff
+
+ * conf/invoice_latex: fix latex template bogosity
+
+2008-05-18 15:57 ivan
+
+ * FS/FS/Upgrade.pm: fix auto sqlradius upgrade: module
+ include/import
+
+2008-05-18 15:54 ivan
+
+ * FS/FS/part_export/sqlradius.pm: oops, fix minor refactoring of
+ auto sqlradius upgrade
+
+2008-05-18 15:53 ivan
+
+ * FS/bin/freeside-upgrade: fix the auto sqlradiusupgrade
+
+2008-05-18 15:42 ivan
+
+ * FS/FS/Upgrade.pm, FS/bin/freeside-sqlradius-radacctd,
+ FS/bin/freeside-upgrade, FS/FS/part_export/sqlradius.pm,
+ init.d/freeside-init: on upgrade, automatically seed from
+ sqlradius databases, and start freeside-sqlradius-radacctd by
+ default
+
+2008-05-17 23:50 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/process/access_group.html: add a
+ config value for disabling the ACLs... this should be good for a
+ demo in 1.7, 1.9 will need some way to disable ACL changes from
+ OUTSIDE the db
+
+2008-05-17 20:04 ivan
+
+ * httemplate/: elements/customer-table.html,
+ misc/batch-cust_pay.html: quick payment entry running total,
+ closes: #3470
+
+2008-05-16 12:26 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cdr.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_bill_pkg_detail.pm,
+ FS/FS/part_pkg/voip_cdr.pm, conf/invoice_html,
+ conf/invoice_latex: typeset CDRs into 5 columns on invoices
+
+2008-05-15 15:48 ivan
+
+ * FS/FS/CGI.pm: fix minor problem with ship_zip not showing up in
+ small_custview
+
+2008-05-14 14:21 jeff
+
+ * FS/FS/: Conf.pm, Conf_compat17.pm, cust_bill.pm: config option to
+ omit statement type items from invoices
+
+2008-05-14 11:19 jeff
+
+ * bin/import-optigold.pl: do NOT delete the existing data
+
+2008-05-14 11:07 jeff
+
+ * FS/FS/: cust_bill_pkg.pm, part_pkg.pm, tax_rate.pm,
+ part_pkg/voip_cdr.pm: correct tax selection and *actually* handle
+ fee based taxes
+
+2008-05-14 09:52 ivan
+
+ * bin/import-optigold.pl: [no log message]
+
+2008-05-13 16:36 ivan
+
+ * FS/bin/freeside-adduser: tyop
+
+2008-05-13 14:20 ivan
+
+ * FS/FS/part_pkg.pm: eliminate warnings on upgrade: "(Odd number of
+ elements in anonymous hash | Use of unintialized value in
+ anonymous hash ) at
+ /usr/local/share/perl/5.8.8/FS/option_Common.pm line 176.
+
+2008-05-13 12:13 ivan
+
+ * Makefile: ensure new self-service libs are installed
+
+2008-05-12 20:49 ivan
+
+ * debian/rules: tyop
+
+2008-05-12 20:49 ivan
+
+ * Makefile, FS/bin/freeside-setup, debian/rules: better place for
+ initial configuration to be stored and retreived from than the
+ initial tarball...
+
+2008-05-08 23:34 ivan
+
+ * httemplate/misc/: xmlhttp-cust_main-address_standardize.html,
+ xmlhttp-cust_main-search.cgi: JSON 1.0 (on deb 4.0) doesn't have
+ to_json yet
+
+2008-05-08 22:59 ivan
+
+ * httemplate/: docs/credits.html, docs/license.html,
+ edit/cust_main.cgi, images/cross.png, images/error.png,
+ images/tick.png: finish usps address standardization
+
+2008-05-08 22:54 ivan
+
+ * httemplate/view/cust_main/packages.html: perl 5.10-ism? new
+ mason?
+
+2008-05-08 05:45 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi,
+ httemplate/elements/xmlhttp.html,
+ httemplate/misc/xmlhttp-cust_main-address_standardize.html,
+ httemplate/misc/xmlhttp-cust_main-search.cgi, htetc/handler.pl:
+ address standardization part one, finally checked in from here
+
+2008-05-07 14:36 ivan
+
+ * httemplate/: view/cust_main.cgi, misc/cancel_cust.html: fix
+ customer cancellation, sort of a side effect of #2872, fixes
+ #3480, #3481
+
+2008-05-05 18:15 ivan
+
+ * httemplate/elements/customer-table.html: put the documentation in
+ a proper <%doc> section
+
+2008-05-05 18:14 ivan
+
+ * httemplate/misc/xmlhttp-cust_main-search.cgi: agent-virtualize
+ customer # portion of quick payment entry
+
+2008-05-05 18:14 ivan
+
+ * httemplate/: misc/batch-cust_pay.html,
+ elements/customer-table.html, misc/elements/customer-table.html:
+ agent-virtualize quick payment entry
+
+2008-05-04 19:11 ivan
+
+ * FS/FS/payinfo_Mixin.pm: hopefully really a better fix for using
+ new payment duplicate stuff with cc encryption :/
+
+2008-05-04 18:52 ivan
+
+ * FS/FS/payinfo_Mixin.pm: better fix for using new payment
+ duplicate stuff with cc encryption :)
+
+2008-05-04 18:18 ivan
+
+ * FS/FS/payinfo_Mixin.pm: fix for using new payment duplicate stuff
+ with cc encryption
+
+2008-05-02 13:30 ivan
+
+ * FS/bin/freeside-upgrade: add -s switch to freeside-upgrade for
+ schema-only changes (for slony slaves)
+
+2008-05-01 18:58 ivan
+
+ * FS/FS/Upgrade.pm: upgrade part_pkg before cust_credit
+
+2008-04-30 16:42 ivan
+
+ * Makefile: not here
+
+2008-04-30 16:36 ivan
+
+ * Makefile: that explains the bs with ChangeLog
+
+2008-04-30 16:29 ivan
+
+ * Makefile: last last-minute fix for last-minute change
+
+2008-04-30 16:26 ivan
+
+ * Makefile: last minute fix for last minute change
+
+2008-04-30 16:19 ivan
+
+ * Makefile: last minute release target update. not particularly
+ dangerous, nobody uses it but me
+
+2008-04-28 12:17 ivan
+
+ * FS/FS/: cust_main.pm, Cron/bill.pm: fix 1.9 queued billing from
+ doing weird things with expirations and adjournments because
+ freeside-queued $^T != freeside-daily $^T
+
+2008-04-27 09:28 jeff
+
+ * httemplate/elements/select-taxproduct.html: sticky, too
+
+2008-04-27 08:19 jeff
+
+ * httemplate/elements/select-taxproduct.html: fixup taxproduct
+ selection
+
+2008-04-24 15:51 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: add use_amaflags and use_disposition
+ flags to voip_cdr price plan
+
+2008-04-22 19:59 jeff
+
+ * FS/FS/cust_bill.pm: fixup return address fallback
+
+2008-04-22 12:46 ivan
+
+ * FS/FS/cust_bill.pm: no comma there
+
+2008-04-22 03:56 ivan
+
+ * FS/FS/: cdr.pm, part_pkg/voip_cdr.pm: voxline cdrs
+
+2008-04-18 14:27 ivan
+
+ * rt/lib/RT/Ticket_Overlay.pm: blah. last silly typo hopefully.
+ wish this was easier to test.
+
+2008-04-18 14:25 ivan
+
+ * rt/lib/RT/Ticket_Overlay.pm: silly semicolon
+
+2008-04-18 14:19 ivan
+
+ * rt/lib/RT/: Ticket_Overlay.pm, URI/freeside.pm: hopefully,
+ finally fix ticket auto-association not getting along with RT
+ ACLs
+
+2008-04-17 20:29 jeff
+
+ * FS/t/addr_block.t, FS/t/router.t, httemplate/edit/allocate.html,
+ httemplate/browse/addr_block.cgi, httemplate/browse/router.cgi,
+ httemplate/edit/process/addr_block/add.cgi,
+ httemplate/edit/process/addr_block/allocate.cgi,
+ httemplate/edit/process/addr_block/deallocate.cgi,
+ httemplate/edit/process/addr_block/split.cgi: drag address and
+ router even farther into the century
+
+2008-04-16 18:39 ivan
+
+ * FS/FS/: Schema.pm, cust_bill.pm, cust_bill_pkg.pm, cust_main.pm,
+ cust_main_county.pm, cust_pkg.pm, part_pkg/flat.pm: implement
+ line item bundling
+
+2008-04-16 18:28 ivan
+
+ * httemplate/elements/menu.html: this is more accurate
+
+2008-04-16 14:52 ivan
+
+ * FS/FS/: part_pkg.pm, cust_main.pm: start implementing billing
+ add-ons
+
+2008-04-16 14:12 ivan
+
+ * FS/FS/part_pkg.pm, httemplate/browse/part_pkg.cgi: implement
+ service add-ons
+
+2008-04-16 14:10 ivan
+
+ * FS/FS/Record.pm: be more forgiving about numeric things padded
+ with leading/trailing space
+
+2008-04-16 13:34 ivan
+
+ * httemplate/: edit/part_bill_event.cgi, edit/part_pkg.cgi,
+ edit/quick-charge.html, elements/select-taxclass.html,
+ elements/tr-select-taxclass.html: fix tax class on package def
+ edit
+
+2008-04-16 13:00 ivan
+
+ * httemplate/: browse/part_pkg.cgi, edit/part_pkg.cgi: show package
+ add-on links in browse
+
+2008-04-16 11:32 jeff
+
+ * FS/FS/cust_pkg.pm, FS/FS/cust_pkg_reason.pm,
+ httemplate/view/cust_main/packages.html: show user who created
+ (cancel/suspend) reason and possibly fix a lingering spurious
+ usergroup bug
+
+2008-04-16 04:54 jeff
+
+ * httemplate/edit/part_pkg_taxproduct.html: this no longer belongs
+
+2008-04-15 21:42 ivan
+
+ * httemplate/: edit/part_pkg.cgi, browse/part_pkg.cgi: add plan &
+ pricing to package browse...
+
+2008-04-15 18:03 ivan
+
+ * FS/FS/m2m_Common.pm, FS/FS/part_pkg.pm,
+ httemplate/edit/process/part_pkg.cgi: fix new link editing in new
+ package editor
+
+2008-04-15 17:29 ivan
+
+ * FS/FS/part_pkg.pm: new package def editor
+
+2008-04-15 17:19 ivan
+
+ * httemplate/edit/: part_pkg.cgi, elements/edit.html,
+ process/part_pkg.cgi: new package def editor
+
+2008-04-15 17:16 ivan
+
+ * FS/: FS.pm, FS/m2m_Common.pm, FS/part_pkg_link.pm,
+ t/part_pkg_link.t: new package def editor
+
+2008-04-15 13:47 jeff
+
+ * httemplate/elements/file-upload.html,
+ httemplate/elements/header-minimal.html,
+ httemplate/misc/file-upload.html, httemplate/misc/tax-import.cgi,
+ httemplate/misc/process/tax-import.cgi,
+ httemplate/misc/process/tax-upgrade.cgi, FS/FS/cust_main.pm,
+ FS/FS/cust_tax_location.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_pkg_taxproduct.pm, FS/FS/part_pkg_taxrate.pm,
+ FS/FS/tax_class.pm, FS/FS/tax_rate.pm: (finally) wrap up new tax
+ rate engine (for now)
+
+2008-04-15 12:43 ivan
+
+ * FS/FS/: part_pkg_option.pm, part_pkg/sesmon_hour.pm,
+ part_pkg/sesmon_minute.pm, part_pkg/sql_external.pm,
+ part_pkg/sql_generic.pm, part_pkg/sqlradacct_hour.pm,
+ part_pkg/voip_cdr.pm, part_pkg/voip_sqlradacct.pm:
+ s/recur_flat/recur_fee/
+
+2008-04-15 06:41 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_event.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/option_Common.pm,
+ FS/FS/part_event_option.pm, FS/FS/part_pkg.pm,
+ FS/FS/svc_Common.pm, FS/FS/svc_acct.pm, FS/FS/svc_domain.pm,
+ httemplate/edit/part_event.html, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/elements/process.html,
+ httemplate/elements/select-agent_types.html,
+ httemplate/elements/select-taxproduct.html,
+ httemplate/elements/selectlayers.html,
+ httemplate/elements/tr-input-text.html,
+ httemplate/elements/tr-part_pkg_freq.html,
+ httemplate/elements/tr-pkg_svc.html,
+ httemplate/elements/tr-select-agent_types.html,
+ httemplate/elements/tr-title.html: new package editor
+
+2008-04-15 03:50 ivan
+
+ * httemplate/docs/about.html: it's april 15th, and i sure do.
+
+2008-04-14 06:42 jeff
+
+ * FS/FS/Record.pm: Improve record searching
+
+2008-04-13 14:37 ivan
+
+ * FS/FS/part_pkg/: base_delayed.pm, flat_delayed.pm,
+ prorate_delayed.pm: fix recur_notify label for *_delayed price
+ plans
+
+2008-04-13 13:35 ivan
+
+ * httemplate/elements/: select-cust-part_pkg.html,
+ select-part_pkg.html, tr-select-part_pkg.html, select-table.html:
+ select-table and select-part_pkg updates so we can use
+ select-part_pkg as an edit/elements/edit.html m2 type
+
+2008-04-13 03:21 ivan
+
+ * httemplate/elements/tr-justtitle.html: adding just a title with
+ no blank space above
+
+2008-04-13 03:19 ivan
+
+ * httemplate/elements/: tr-selectlayers-select.html,
+ selectlayers.html: add a tr- for just the select bit of a
+ selectlayers...
+
+2008-04-13 01:21 ivan
+
+ * httemplate/elements/tr-input-text.html: add disabled option to
+ text elements
+
+2008-04-13 00:41 ivan
+
+ * FS/FS/part_pkg/: base_delayed.pm, base_rate.pm, bulk.pm, flat.pm,
+ flat_comission.pm, flat_comission_cust.pm, flat_comission_pkg.pm,
+ flat_delayed.pm, flat_introrate.pm, prepaid.pm, prorate.pm,
+ prorate_delayed.pm, sesmon_hour.pm, sesmon_minute.pm,
+ sql_external.pm, sql_generic.pm, sqlradacct_hour.pm,
+ subscription.pm, voip_cdr.pm, voip_sqlradacct.pm: shorter names
+ and rearranged weights for a brighter tommorow^W^Wbetter price
+ plan <SELECT>
+
+2008-04-12 20:03 ivan
+
+ * httemplate/elements/tr-select-table.html: more stuff to allow
+ select-table to be used as as edit/elements/edit.html m2*
+ element: add tr-select-table.html
+
+2008-04-12 20:03 ivan
+
+ * httemplate/elements/select-table.html: some stuff to allow
+ select-table to be used as as edit/elements/edit.html m2*
+ element: add js_only and html_only options, add id option to
+ specify element id, add a kludge to onchange option
+
+2008-04-12 19:58 ivan
+
+ * httemplate/elements/tablebreak-tr-title.html: allow table id to
+ be specified for tablebreak elements (so edit/elements/edit.html
+ m2* stuff can be used after a tablebreak)
+
+2008-04-12 19:56 ivan
+
+ * httemplate/elements/: select-taxproduct.html,
+ tr-select-taxproduct.html: add elements for selecting taxproduct
+
+2008-04-12 19:55 ivan
+
+ * httemplate/elements/tr-part_pkg_freq.html: add an element for
+ selecting part_pkg frequencies
+
+2008-04-12 16:31 ivan
+
+ * httemplate/elements/: columnnext.html, columnstart.html: space
+ columns out
+
+2008-04-12 16:18 ivan
+
+ * httemplate/elements/: columnend.html, columnnext.html,
+ columnstart.html: add some column elements so we can replicate
+ multi-column edit forms with edit.html
+
+2008-04-11 02:20 ivan
+
+ * FS/FS/cdr.pm, httemplate/misc/cdr-import.html: taqua cdrs!
+
+2008-04-10 18:50 ivan
+
+ * FS/FS/cdr.pm, httemplate/misc/cdr-import.html: checkpoint taqua
+
+2008-04-10 15:00 ivan
+
+ * rt/lib/RT/Ticket_Overlay.pm: use non-ACL'ed _AddLink instead of
+ AddLink so that the auto-association stuff works when creating a
+ ticket
+
+2008-04-09 18:35 jeff
+
+ * FS/FS/Conf.pm: sync terminology
+
+2008-04-09 16:51 ivan
+
+ * httemplate/elements/menu.html: add a menu entry for the new tax
+ stuff
+
+2008-04-09 14:54 ivan
+
+ * httemplate/misc/tax-import.cgi: clean up irrelevant stuff on
+ batch tax import
+
+2008-04-09 14:44 ivan
+
+ * httemplate/docs/AGPL.html: oops, adding explicit AGPL.html
+
+2008-04-09 14:27 ivan
+
+ * FS/FS/UID.pm: please mr. bootstrapping tree, give us some bootsap
+
+2008-04-09 14:17 ivan
+
+ * FS/FS/UID.pm: 1.9 bootstrapping: apparantly, we have a dbdef at
+ this point, but its not in the database yet, so checking
+ dbdef->table doesn't DWWW
+
+2008-04-09 14:07 ivan
+
+ * debian/control: adding 1.9 dependencies
+
+2008-04-08 20:33 ivan
+
+ * FS/FS/part_pkg/sqlradacct_hour.pm: fix hourly cap for SQL overage
+ charges
+
+2008-04-07 22:49 ivan
+
+ * debian/: README.Debian, TODO, changelog, compat, conffiles.ex,
+ config, control, copyright, cron.d, cron.d.ex,
+ dbconfig-common.install, dbconfig-common.upgrade, dirs, docs,
+ ex.doc-base.package, freeside-doc.docs, freeside-doc.files,
+ freeside-webui.links, freeside.apache-alias.conf,
+ freeside.default, freeside.docs, init.d.ex, init.d.lsb.ex,
+ manpage.1.ex, manpage.sgml.ex, menu.ex, postinst, postinst.ex,
+ postrm, postrm.ex, preinst, preinst.ex, prerm, prerm.ex, rules,
+ templates, watch.ex: debian packages!
+
+2008-04-06 09:12 jeff
+
+ * httemplate/browse/part_pkg_taxproduct.cgi,
+ httemplate/browse/tax_rate.cgi, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_county.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_pkg_taxrate.pm, FS/FS/tax_rate.pm,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/tax_rate.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/tax_rate.html,
+ httemplate/edit/process/elements/process.html: new tax rating
+ engine
+
+2008-04-05 00:00 ivan
+
+ * FS/bin/freeside-prepaidd: configurable logfile location for
+ freeside-prepaidd
+
+2008-04-04 12:47 ivan
+
+ * httemplate/elements/header.html: sync with 1_7_BRANCH
+
+2008-04-04 10:47 ivan
+
+ * httemplate/search/elements/search.html: this worked fine. don't
+ understand why it was changed in the first place.
+
+2008-04-04 10:42 ivan
+
+ * httemplate/search/elements/search.html: fix range selection on
+ searches, huh
+
+2008-04-02 13:42 jeff
+
+ * httemplate/browse/tax_class.html, FS/FS/Schema.pm,
+ FS/FS/part_pkg_taxoverride.pm, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_pkg_taxoverride.html,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/search/elements/search.html: checkpoint tax editors
+ and correct a blunder
+
+2008-04-02 10:28 ivan
+
+ * Makefile: substitute FREESIDE_CONF in apache conf files
+
+2008-04-02 10:26 ivan
+
+ * htetc/: freeside-base1.99.conf, freeside-base1.conf,
+ freeside-base2.conf: template AuthUserFile htpasswd to be in
+ FREESIDE_CONF dir instead of hardcoded location
+
+2008-04-02 10:00 rsiddall
+
+ * Makefile: Quick fix to update the release version number in the
+ RPM specfile. This leaves the specfile unusable for CVS builds.
+
+2008-04-02 08:38 ivan
+
+ * init.d/freeside-init: tiny init file nit that helps with deb
+ packaging (and probably rpm too) - source /etc/default/freeside
+ if it exists
+
+2008-04-01 21:32 ivan
+
+ * httemplate/docs/credits.html: slight browser adjustments and DONE
+
+2008-04-01 21:20 ivan
+
+ * httemplate/elements/header.html: new header about: box
+
+2008-04-01 21:19 ivan
+
+ * httemplate/docs/about.html: slightly taller
+
+2008-04-01 21:07 ivan
+
+ * httemplate/docs/: credits.html, license.html: updated credits and
+ license
+
+2008-04-01 21:05 ivan
+
+ * httemplate/docs/about.html: adding about.html splash
+
+2008-04-01 20:48 ivan
+
+ * httemplate/elements/popup_link_onclick.html: remove excessive
+ iframe borders, add "scrolling" and "nofalse" options
+
+2008-04-01 17:22 ivan
+
+ * FS/FS/cust_pay.pm: don't do (as much) useless work on upgrade
+
+2008-04-01 16:56 ivan
+
+ * httemplate/elements/iframecontentmws.js: fix hasty safari iframe
+ fix
+
+2008-04-01 16:30 ivan
+
+ * httemplate/docs/: credits.html, license.html: adding license and
+ credits in app itself
+
+2008-04-01 16:26 ivan
+
+ * fs_sesmon/: fs_session_server, FS-SessionClient/Changes,
+ FS-SessionClient/MANIFEST, FS-SessionClient/MANIFEST.SKIP,
+ FS-SessionClient/Makefile.PL, FS-SessionClient/SessionClient.pm,
+ FS-SessionClient/fs_sessiond, FS-SessionClient/test.pl,
+ FS-SessionClient/bin/freeside-login,
+ FS-SessionClient/bin/freeside-logout,
+ FS-SessionClient/cgi/login.cgi, FS-SessionClient/cgi/logout.cgi:
+ remove fs_sesmon
+
+2008-04-01 16:24 ivan
+
+ * TODO: remove TODO
+
+2008-04-01 16:24 ivan
+
+ * SCHEMA_CHANGE: remove SCHEMA_CHANGE
+
+2008-04-01 16:23 ivan
+
+ * fs_selfadmin/: README, fs_mailadmin_server,
+ FS-MailAdminServer/MailAdminClient.pm,
+ FS-MailAdminServer/fs_mailadmind,
+ FS-MailAdminServer/cgi/mailadmin.cgi: remove fs_selfadmin
+
+2008-04-01 16:20 ivan
+
+ * README: welcome to the new world
+
+2008-04-01 16:15 ivan
+
+ * INSTALL: clean up top level files
+
+2008-04-01 16:08 ivan
+
+ * CREDITS, INSTALL: clean up some of the top-level files
+
+2008-04-01 02:40 ivan
+
+ * Makefile: sync with 1.7.3
+
+2008-04-01 02:19 ivan
+
+ * FS/FS/cust_bill.pm: don't show services on invoices that are
+ newer than the invoice, closes: #3032
+
+2008-04-01 01:43 ivan
+
+ * rt/lib/RT/Ticket_Overlay.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_invoice.pm, rt/lib/RT/URI/freeside/Internal.pm:
+ last bit of magic for RT ticket customer auto-association: look
+ for requestor email addresses in cust_main_invoice and svc_acct,
+ closes; RT#1160
+
+2008-03-31 23:37 ivan
+
+ * httemplate/edit/cust_main_county.html: probably doesn't matter
+ now, but better error reporting anyway
+
+2008-03-31 23:34 ivan
+
+ * httemplate/: misc/cancel_cust.html, misc/cancel_pkg.html,
+ edit/cust_credit.cgi: popup iframes don't have predictable names
+ anymore, so locate submit buttons by id instead
+
+2008-03-31 23:26 ivan
+
+ * httemplate/elements/: popup_link.html, popup_link_onclick.html:
+ doc height param
+
+2008-03-31 23:16 ivan
+
+ * httemplate/elements/iframecontentmws.js: append a random number
+ to the iframe name on-the-fly to keep safari from caching it
+ under all circumstances
+
+2008-03-31 22:49 ivan
+
+ * httemplate/view/cust_main/payment_history.html: finish
+ component-izing overlib links
+
+2008-03-31 21:37 ivan
+
+ * httemplate/search/cust_pkg.cgi: use popup_link...
+
+2008-03-31 21:19 ivan
+
+ * httemplate/browse/rate_detail.html: can't run include() sub at
+ <%once> time
+
+2008-03-31 20:56 ivan
+
+ * httemplate/browse/rate_detail.html: component-ize overlib init
+ and popup link
+
+2008-03-31 20:51 ivan
+
+ * httemplate/edit/bulk-cust_svc.html: component-ize overlib init
+
+2008-03-31 20:49 ivan
+
+ * httemplate/elements/phonenumber.html: use popup_link element for
+ phonenumber.html silly vonage popup
+
+2008-03-31 17:54 jeff
+
+ * FS/FS/cust_tax_location.pm, FS/FS/part_pkg_taxoverride.pm,
+ FS/FS/part_pkg_taxproduct.pm, FS/FS/part_pkg_taxrate.pm,
+ FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/tax_class.pm,
+ FS/FS/tax_rate.pm, FS/FS/part_pkg.pm, FS/t/cust_tax_location.t,
+ FS/t/part_pkg_taxoverride.t, FS/t/part_pkg_taxproduct.t,
+ FS/t/part_pkg_taxrate.t, FS/t/tax_class.t, FS/t/tax_rate.t,
+ httemplate/browse/tax_rate.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_pkg_taxoverride.html,
+ httemplate/edit/part_pkg_taxproduct.html,
+ httemplate/edit/tax_class.html, httemplate/edit/tax_rate.html,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/tax_class.html,
+ httemplate/edit/process/tax_rate.html,
+ httemplate/misc/tax-import.cgi, FS/MANIFEST, htetc/handler.pl,
+ httemplate/elements/menu.html,
+ httemplate/misc/process/recharge_svc.new,
+ httemplate/misc/process/tax-import.cgi: checkpoint of new tax
+ rating system
+
+2008-03-31 16:19 ivan
+
+ * httemplate/elements/progress-init.html: overlib include
+
+2008-03-31 16:14 ivan
+
+ * httemplate/elements/: popup_link-cust_main.html,
+ popup_link-cust_pkg.html, popup_link-cust_svc.html,
+ popup_link.html, popup_link_onclick.html: fix examples to use
+ elements/init_overlib.html
+
+2008-03-31 16:09 ivan
+
+ * httemplate/: browse/cust_main_county.cgi, config/config-view.cgi:
+ overlib include
+
+2008-03-31 16:07 ivan
+
+ * httemplate/: view/cust_main.cgi,
+ elements/popup_link_onclick.html, view/cust_main/notes.html:
+ clean up overlib usage for customer notes
+
+2008-03-31 15:52 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.cgi: signup.cgi fix for
+ hidden agentnum tags with trailling "/ >"
+
+2008-03-31 15:27 ivan
+
+ * httemplate/: edit/cust_main/billing.html,
+ elements/init_overlib.html, misc/payment.cgi: overlib cleanup:
+ easy static CVV2/echeck popups
+
+2008-03-31 14:52 ivan
+
+ * httemplate/elements/iframecontentmws.js: update overlibmws to
+ current code
+
+2008-03-31 14:45 ivan
+
+ * httemplate/: config/config-view.cgi, elements/popup_link.html:
+ move config edit popup to elements/popup_link.html
+
+2008-03-31 14:43 ivan
+
+ * httemplate/config/config.cgi: more approprietly sized textareas
+ prevent scrollbars from being necessary in config popups
+
+2008-03-31 14:11 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ elements/popup_link.html, elements/popup_link_onclick.html: fix
+ safari weirdness with caching iframes and auto-submitting them
+ (in tax editor at least)
+
+2008-03-31 13:40 ivan
+
+ * httemplate/elements/: popup_link-cust_main.html,
+ popup_link-cust_pkg.html, popup_link-cust_svc.html,
+ popup_link.html: clean up popup link elements a bit, have the
+ iframe name autogenerate to work around safari fuckery
+
+2008-03-31 11:50 ivan
+
+ * httemplate/elements/: overlibmws.js, overlibmws_crossframe.js,
+ overlibmws_draggable.js, overlibmws_iframe.js: update overlibmws
+ to current code before delving into safari problem... hopefully
+ no disasterous side effects :)
+
+2008-03-29 19:42 ivan
+
+ * httemplate/: search/cust_bill.html, view/cust_bill.cgi: don't
+ show invoice resend and payment posting links if you can't do
+ that anyway
+
+2008-03-29 19:32 ivan
+
+ * FS/FS/cust_bill.pm: okay, REALLY fix substitution problems with
+ ancient-style invoice template includes
+
+2008-03-29 18:26 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm: fix missing backslash preventing
+ ancient invoice template includes from working, whew! and
+ spiffied up the error reporting on template compile problems,
+ since they're bound to happen when folks edit
+
+2008-03-29 17:57 ivan
+
+ * FS/FS/Conf.pm: document config_orbase, add key_orbase for
+ debugging info
+
+2008-03-29 02:11 ivan
+
+ * httemplate/view/: svc_phone.cgi, elements/svc_Common.html: add
+ quick links for unprocessed and processed CDRs to svc_phone view
+
+2008-03-29 01:32 ivan
+
+ * httemplate/misc/order_pkg.html: in the unlikely error case, the
+ order button should stay enabled
+
+2008-03-29 01:15 ivan
+
+ * httemplate/: elements/popup_link-cust_main.html,
+ elements/tr-select-reason.html, misc/cancel_cust.html,
+ misc/order_pkg.html, view/cust_main/packages.html: okay. and
+ thank goodness its on 1.9. really fix error reporting on quick
+ package order this time. have to change cust cancel popup
+ slightly too, but its for the better (easier custnum parsing).
+ and lastly make it easier for reason selection to be reused
+ without stickiness-on-errors being a big pain in the ass
+
+2008-03-28 23:42 ivan
+
+ * httemplate/edit/process/quick-cust_pkg.cgi: fix quick pkg order
+ redirect
+
+2008-03-28 15:31 ivan
+
+ * FS/FS/cust_svc.pm: fix double charging for CDRs when number is in
+ both src and charged_party fields, and disable_src is not checked
+
+2008-03-27 15:04 ivan
+
+ * httemplate/edit/process/cust_main.cgi: fixes edit if routing code
+ only, closes: #3085
+
+2008-03-27 14:05 ivan
+
+ * httemplate/view/cust_main/: payment_history.html: fix for ACH
+ info masking
+
+2008-03-27 14:01 ivan
+
+ * httemplate/view/cust_main/: billing.html, payment_history.html:
+ mask ACH info in payment history
+
+2008-03-27 13:40 ivan
+
+ * httemplate/: elements/menu.html, search/report_sql.html: add back
+ raw SQL query (it had an appropriate ACL)
+
+2008-03-27 13:19 ivan
+
+ * httemplate/: search/cust_pay.cgi, view/cust_pay.html: resolve
+ minor ACL glitch linking to payments
+
+2008-03-26 11:18 ivan
+
+ * FS/FS/Report/Table/Monthly.pm: add a netcredits_12mo sub so that
+ 12mo checkbox works again... sure do need these to be
+ auto-generated or $AUTOLOADED or something :)
+
+2008-03-26 08:42 jeff
+
+ * FS/FS/rate_detail.pm, httemplate/browse/rate_detail.html,
+ httemplate/edit/rate_detail.html,
+ httemplate/edit/rate_region.cgi: fixup per call billing
+
+2008-03-25 20:04 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: don't granular-ize 0 billsec calls
+ into having a minimum charge
+
+2008-03-25 19:27 ivan
+
+ * httemplate/search/: cdr.html, report_cdr.html: add ability to
+ query ranges of duration & billable seconds to CDR report
+
+2008-03-25 19:19 ivan
+
+ * httemplate/search/: report_cust_main.html, report_svc_acct.html:
+ UI nit: separate search & display options
+
+2008-03-25 18:03 ivan
+
+ * httemplate/edit/: part_bill_event.cgi,
+ process/part_bill_event.cgi: quick shortcut for easier adding of
+ new 1.7-style invoice events
+
+2008-03-24 19:52 ivan
+
+ * rt/lib/RT/: Groups_Overlay.pm, Users_Overlay.pm: REALLY require
+ DBIx::SB 1.50, jeez
+
+2008-03-24 19:33 ivan
+
+ * rt/lib/RT/SearchBuilder.pm: bring declared SearchBuilder
+ dependency inline with reality
+
+2008-03-24 15:35 ivan
+
+ * httemplate/edit/part_bill_event.cgi: this probably never worked.
+ ->send isn't at all what is wanted, that sends the original
+ invoice, not the new one with the late charge
+
+2008-03-23 20:07 ivan
+
+ * rt/: html/Elements/EditCustomers,
+ html/Ticket/Elements/EditCustomers,
+ html/Ticket/Elements/ShowCustomers, lib/RT/Record.pm,
+ lib/RT/Ticket_Overlay.pm: woo! final part of #1160! yup,
+ auto-associating tickets with customers now. whew!
+
+2008-03-23 18:28 ivan
+
+ * rt/: html/Ticket/Elements/AddCustomers, lib/RT/Record.pm,
+ lib/RT/Interface/Web_Vendor.pm: part two of #1160: linking a
+ ticket to its first customer will auto-link any customerless
+ requestors
+
+2008-03-23 16:38 ivan
+
+ * rt/: html/Admin/Users/Modify.html, lib/RT/User_Overlay.pm,
+ lib/RT/Interface/Web_Vendor.pm: part 1 of #1160: associate users
+ w/customers, manual editing
+
+2008-03-23 16:32 ivan
+
+ * rt/html/Elements/: AddCustomers, EditCustomers: part 1 of #1160:
+ associate users w/customers, manual editing
+
+2008-03-19 12:48 jeff
+
+ * httemplate/edit/part_bill_event.cgi: quick fix for deep recursion
+ (RT#3267)
+
+2008-03-17 23:43 ivan
+
+ * fs_selfservice/fri/modules/: billing.module, dashboard.module,
+ myaccount.module: pre-show checkpoint. duct tape!
+
+2008-03-17 09:24 ivan
+
+ * fs_selfservice/fri/modules/: billing.module, dashboard.module,
+ myaccount.module: checkpoint
+
+2008-03-16 19:49 ivan
+
+ * fs_selfservice/fri/: includes/freeside.class.php,
+ modules.template/blank.module: missed bits
+
+2008-03-16 19:48 ivan
+
+ * fs_selfservice/fri/: includes/login.php, includes/main.conf.php,
+ locale/ari.po, modules/billing.module,
+ modules/callmonitor.module, modules/dashboard.module,
+ modules/myaccount.module, modules/settings.module,
+ theme/page.tpl.php: first bits of working FRI! woop!
+
+2008-03-16 19:37 ivan
+
+ * httemplate/view/cust_main/packages.html: fix oops in new popup
+ components
+
+2008-03-16 16:36 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: hopefully allow phone login to work
+
+2008-03-16 16:25 ivan
+
+ * httemplate/view/svc_phone.cgi: view PINs too
+
+2008-03-16 16:05 jeff
+
+ * httemplate/: elements/popup_link-cust_main.html,
+ elements/popup_link-cust_pkg.html,
+ elements/popup_link-cust_svc.html, elements/popup_link.html,
+ view/cust_main.cgi, view/cust_main/packages.html: componentize
+ conflicting %once subroutines (rt#3250)
+
+2008-03-16 15:48 ivan
+
+ * httemplate/edit/svc_phone.cgi: phone gets a pin
+
+2008-03-16 15:39 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: phonenum + pin login
+
+2008-03-16 15:24 ivan
+
+ * FS/FS/: Conf.pm, svc_phone.pm, ClientAPI/MyAccount.pm: phonenum +
+ pin login
+
+2008-03-16 14:07 ivan
+
+ * fs_selfservice/fri/includes/: common.php, login.php: first try at
+ single sign-on
+
+2008-03-16 12:58 ivan
+
+ * fs_selfservice/fri/: CHANGE.log, LICENSE.txt, README.txt,
+ index.php, version.php, theme/global.css, theme/header.css,
+ theme/iefixes.css, theme/layout.css, theme/logo.gif,
+ theme/main.css, theme/navigation.css, theme/page.tpl.php,
+ theme/spacer.gif, theme/text.css, theme/images/arrow-asc.gif,
+ theme/images/arrow-desc.gif, modules/callmonitor.module,
+ modules/phonefeatures.module, modules/settings.module,
+ modules/voicemail.module, modules/featurecodes.module,
+ modules/followme.module, includes/ajax.php, includes/crypt.php,
+ includes/main.conf.php, misc/audio.php, misc/popup.css,
+ misc/recording_popup.php, modules/VmX.module, includes/asi.php,
+ includes/bootstrap.php, includes/common.php,
+ includes/database.php, includes/display.php, includes/lang.php,
+ includes/login.php, locale/readme.txt, locale/ari.po,
+ locale/ari.utf-8.po, locale/locale.txt,
+ locale/de_DE/LC_MESSAGES/ari.mo, locale/hu_HU/LC_MESSAGES/ari.mo,
+ locale/hu_HU/LC_MESSAGES/ari.po, locale/pt_BR/LC_MESSAGES/ari.mo,
+ locale/pt_BR/LC_MESSAGES/ari.po, locale/de_DE/LC_MESSAGES/ari.po,
+ locale/el_GR/LC_MESSAGES/ari.mo, locale/el_GR/LC_MESSAGES/ari.po,
+ locale/es_ES/LC_MESSAGES/ari.mo, locale/es_ES/LC_MESSAGES/ari.po,
+ locale/sv_SE/LC_MESSAGES/ari.mo, locale/sv_SE/LC_MESSAGES/ari.po,
+ locale/it_IT/LC_MESSAGES/ari.mo, locale/fr_FR/LC_MESSAGES/ari.mo,
+ locale/fr_FR/LC_MESSAGES/ari.po, locale/he_IL/LC_MESSAGES/ari.mo,
+ locale/he_IL/LC_MESSAGES/ari.po, locale/it_IT/LC_MESSAGES/ari.po:
+ Initial revision
+
+2008-03-16 09:57 jeff
+
+ * httemplate/misc/recharge_svc.html: doh
+
+2008-03-16 01:04 ivan
+
+ * FS/FS/UID.pm: goodness, i hope this fixes the bootstrapping
+
+2008-03-16 00:25 ivan
+
+ * FS/FS/UID.pm: okay, really now, how about this
+
+2008-03-16 00:24 ivan
+
+ * FS/FS/UID.pm: okay, how about this
+
+2008-03-16 00:21 ivan
+
+ * FS/FS/UID.pm: fix 1.7->1.9 bootstrapping, i think
+
+2008-03-15 22:22 ivan
+
+ * httemplate/search/svc_broadband.cgi: clean up and
+ agent-virtualize svc_broadband searching
+
+2008-03-15 22:13 ivan
+
+ * httemplate/edit/part_svc.cgi: finish bringing sanity to
+ svc_broadband service definition blocknum edit
+
+2008-03-15 22:13 ivan
+
+ * FS/FS/: addr_block.pm, svc_broadband.pm: bring some sanity to
+ address block selection in svc_broadband service definition edit
+
+2008-03-15 21:54 ivan
+
+ * httemplate/browse/: addr_block.cgi, router.cgi: drag address &
+ router browse into this centiry
+
+2008-03-15 21:00 ivan
+
+ * httemplate/elements/header.html, httemplate/elements/menu.html,
+ rt/html/Elements/FreesideSearch: hide customer search if user
+ does not have "List customers" ACL, closes: RT#3105
+
+2008-03-15 15:18 ivan
+
+ * httemplate/edit/part_pkg.cgi, FS/FS/part_pkg/voip_cdr.pm:
+ slightly better voip_cdr package edit: use radio buttons for
+ selecting long things
+
+2008-03-15 14:39 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: be asssertive
+
+2008-03-15 14:14 ivan
+
+ * FS/FS/: cust_svc.pm, part_pkg/voip_cdr.pm: configurable
+ disable_src, domestic_prefix and international_prefix options for
+ voip price plan
+
+2008-03-15 12:52 ivan
+
+ * httemplate/search/cust_bill.html, FS/FS/cust_bill.pm: check on
+ invoice re-printing newest percust... can't reproduce any
+ problem, prints newest per cust fine, closes: #3161
+
+2008-03-14 17:30 ivan
+
+ * httemplate/: view/svc_domain.cgi, misc/catchall.cgi: fix harmless
+ code leaking out onto the page, hehe, closes: Bug#3253, also
+ remove silly formatting on catchall edit
+
+2008-03-14 13:11 ivan
+
+ * FS/FS/cust_main.pm: eliminate some harmless uninitialized value
+ warnings
+
+2008-03-14 10:30 jeff
+
+ * FS/FS/part_export/prizm.pm: insist on Net::Prizm 0.04
+
+2008-03-14 01:13 ivan
+
+ * httemplate/edit/process/cust_pkg.cgi: whew, glad that change
+ package bugfix was easy to find, closes: Bug#3241
+
+2008-03-14 00:48 ivan
+
+ * FS/FS/cust_credit_bill.pm, FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/money_time.cgi,
+ httemplate/search/cust_credit_bill.html,
+ httemplate/search/cust_credit.html: add net credits to
+ sales/credits/receipts report
+
+2008-03-13 19:10 ivan
+
+ * FS/FS/Conf.pm: add Net20 invoice terms, closes: #3219
+
+2008-03-13 19:09 ivan
+
+ * FS/FS/Conf.pm: show where the warning about no conf comes from
+
+2008-03-13 02:28 ivan
+
+ * FS/FS/cust_pay.pm: yow. very sleep deprived. remove the
+ infinite loop rather than add one.
+
+2008-03-13 02:14 ivan
+
+ * FS/FS/cust_pay.pm: infinite loop protection
+
+2008-03-13 01:57 ivan
+
+ * FS/FS/cust_pay.pm: allow cust_pay.otaker upgrade to proceed even
+ if there are some old crufty records around attached to
+ now-deleted customers
+
+2008-03-12 09:22 jeff
+
+ * FS/FS/cust_svc.pm, FS/FS/part_export.pm, FS/FS/svc_Common.pm,
+ FS/FS/UI/Web.pm, FS/FS/part_export/prizm.pm,
+ eg/export_template.pm, httemplate/view/cust_main/packages.html:
+ allow exports to add links to customer view (#1407)
+
+2008-03-04 13:07 ivan
+
+ * FS/FS/cust_refund.pm: fix otaker population for cust_refund like
+ cust_credit and cust_pay
+
+2008-03-04 13:06 ivan
+
+ * FS/FS/cust_pay.pm: fix cust_pay.otaker population
+
+2008-03-04 11:15 ivan
+
+ * httemplate/: edit/cust_pkg.cgi, edit/process/cust_pkg.cgi,
+ misc/change_pkg.cgi: fix edit/process/cust_pkg getting confused
+ about the two different places that would be calling it... i.e.
+ with an empty new_pkgnum it would redirect the popup back the
+ customer view, hehe
+
+2008-03-03 19:38 ivan
+
+ * FS/FS/cust_bill.pm: AND fix latex->html notes substituion for ~s
+
+2008-03-03 19:37 ivan
+
+ * FS/FS/cust_bill.pm: and fix latex->html notes substituion for
+ escaped #s
+
+2008-03-03 19:34 ivan
+
+ * FS/FS/cust_bill.pm: fix latex->html notes substituion for
+ newlines
+
+2008-03-03 18:27 ivan
+
+ * httemplate/browse/rate_region.html: should improve compatibility
+ with older Pg. i hope
+
+2008-03-03 17:49 ivan
+
+ * FS/FS/UID.pm: argh, don't load up a user until the other
+ initialization is done
+
+2008-03-03 15:12 ivan
+
+ * rt/: etc/RT_Config.pm.in, html/Elements/Header,
+ html/Elements/PageLayout, html/Elements/Tabs,
+ html/Elements/CollectionAsTable/Row,
+ html/Ticket/Elements/ShowTransactionAttachments,
+ html/Widgets/TitleBoxStart, sbin/rt-setup-database.in: merge in
+ rt 3.6.6. *gulp*!
+
+2008-03-01 20:11 ivan
+
+ * rt/html/: Elements/EmailInput, NoAuth/css/dhandler,
+ NoAuth/images/css/fieldbg-autocomplete.gif,
+ NoAuth/js/scriptaculous/controls.js,
+ NoAuth/js/scriptaculous/effects.js,
+ NoAuth/js/scriptaculous/prototype.js,
+ NoAuth/js/scriptaculous/scriptaculous.js,
+ Helpers/EmailAutocomplete, Ticket/Elements/ShowQueue: Initial
+ revision
+
+2008-03-01 19:07 ivan
+
+ * httemplate/elements/header.html,
+ rt/html/Elements/FreesideNewCust: fix annoying resize of "New
+ customer" button; closes: RT#1642
+
+2008-03-01 18:50 ivan
+
+ * htetc/handler.pl: better indication of why these things are the
+ way they are
+
+2008-03-01 17:31 ivan
+
+ * FS/FS/payment_gateway.pm, httemplate/browse/payment_gateway.html,
+ httemplate/misc/disable-payment_gateway.cgi,
+ httemplate/search/elements/search.html: add payment gateway
+ disabling (and move payment gateway browse over to new template)
+
+2008-03-01 15:30 ivan
+
+ * FS/FS/: Conf.pm, payinfo_Mixin.pm: added a config value to
+ control the extent of credit card masking, but since
+ cust_main.paymask is in the db, need something to update it for
+ all existing customers too
+
+2008-03-01 14:39 ivan
+
+ * httemplate/search/cust_main.html: ah, that's better, prettyfy and
+ link adv. customer search
+
+2008-03-01 14:23 ivan
+
+ * httemplate/: elements/select-payby.html,
+ elements/tr-select-payby.html, search/cust_main.html,
+ search/report_cust_main.html: add payby selection to adv.
+ customer search
+
+2008-02-29 09:57 jeff
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, conf/invoice_html,
+ conf/invoice_latex: refactor print_*; invoice sections by package
+ class; could still stand some more refactoring
+
+2008-02-28 20:31 ivan
+
+ * FS/FS/cdr.pm, httemplate/misc/cdr-import.html: working asterisk
+ CDR CSV import (not just direct DB)
+
+2008-02-28 18:29 ivan
+
+ * FS/FS/: Record.pm, access_user.pm: disallow uppercase usernames
+ in the first place. also Record::str2time_sql_closing snuck in.
+
+2008-02-21 17:32 ivan
+
+ * httemplate/search/svc_acct.cgi: on accounts overview: show time
+ applied after multipliers, not actual time worked
+
+2008-02-21 17:09 ivan
+
+ * FS/FS/cust_pay.pm: want to upgrade legacy payments even if they
+ are deprecated COMP payby...
+
+2008-02-21 16:57 ivan
+
+ * FS/FS/cust_pay.pm: don't bomb out on this transition on old
+ databases without history records for everything...
+
+2008-02-21 16:54 ivan
+
+ * httemplate/search/svc_acct.cgi: on accounts overview: show time
+ applied after multipliers, not actual time worked
+
+2008-02-20 14:45 ivan
+
+ * httemplate/misc/inventory_item-import.html: doh. ivan is so in
+ the doghouse for this one
+
+2008-02-19 18:07 ivan
+
+ * FS/FS/prepay_credit.pm,
+ httemplate/edit/process/prepay_credit.cgi: retry collisions a
+ bit, acme is getting duplicate errors... guess they're using lots
+ and lots of prepaid cards. closes: RT#3104
+
+2008-02-19 17:21 ivan
+
+ * FS/FS/Schema.pm: update the tax class editor to enable taxclass
+ adding, RT#2929
+
+2008-02-19 17:16 ivan
+
+ * httemplate/edit/part_pkg_taxclass.html,
+ httemplate/edit/process/part_pkg_taxclass.html,
+ httemplate/browse/cust_main_county.cgi, FS/FS/Upgrade.pm,
+ FS/FS/part_pkg_taxclass.pm, htetc/handler.pl,
+ httemplate/elements/tr-select-taxclass.html: update the tax class
+ editor to enable taxclass adding, RT#2929
+
+2008-02-19 17:10 ivan
+
+ * httemplate/edit/: cust_main_county-expand.cgi,
+ process/cust_main_county-expand.cgi, process/invoice_logo.html,
+ process/reg_code.cgi: process/part_pkg_taxclass.html
+
+2008-02-19 01:15 ivan
+
+ * FS/: FS/part_pkg_taxclass.pm, t/part_pkg_taxclass.t, FS.pm,
+ MANIFEST: adding taxclass table
+
+2008-02-19 01:10 ivan
+
+ * bin/generate-table-module: fix this to generate more
+ wiki-friendly column list
+
+2008-02-18 19:30 ivan
+
+ * FS/FS/svc_external.pm: add some descriptions for svc_external
+ fields, allowing id to fill in from inventory
+
+2008-02-18 19:17 ivan
+
+ * FS/FS/svc_external.pm: return svc_external id and title as label
+ instead of svcnum
+
+2008-02-18 18:57 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: fixup and expand
+ POD docs for self-service list_pkgs & list_svcs
+
+2008-02-18 18:38 ivan
+
+ * bin/pod2x: fix API upload
+
+2008-02-18 18:37 ivan
+
+ * FS/FS.pm: update base API docs contents
+
+2008-02-18 18:33 ivan
+
+ * FS/FS/cust_pay_pending.pm: clean up POD docs for better wiki
+ exportability
+
+2008-02-18 18:28 ivan
+
+ * FS/FS/cust_credit.pm: clean up POD docs for better wiki
+ exportability
+
+2008-02-18 18:25 ivan
+
+ * FS/FS/cust_bill_event.pm: clean up POD docs for better wiki
+ exportability
+
+2008-02-18 18:20 ivan
+
+ * FS/FS/cust_bill.pm: clean up POD docs for better wiki
+ exportability
+
+2008-02-18 18:15 ivan
+
+ * FS/FS/: access_user.pm, acct_rt_transaction.pm: clean up POD docs
+ for better wiki exportability
+
+2008-02-14 00:31 ivan
+
+ * httemplate/search/cust_pkg.cgi: brown-bag missing comma from last
+ update. time to go home
+
+2008-02-14 00:28 ivan
+
+ * httemplate/search/cust_pkg.cgi: re-align links and styling in
+ package report correctly
+
+2008-02-13 19:52 ivan
+
+ * FS/FS/Schema.pm, FS/FS/Upgrade.pm, FS/FS/cust_pay.pm,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/search/cust_pay.cgi: add cust_pay.otaker field;
+ populate it based on history on upgrades, and show the order
+ taker on all payments (on customer view and payment search)
+ closes: #2953
+
+2008-02-13 19:48 ivan
+
+ * FS/: FS/h_cust_pay.pm, t/h_cust_credit.t, t/h_cust_pay.t: add
+ FS::h_cust_pay class
+
+2008-02-13 17:48 ivan
+
+ * httemplate/view/cust_main/payment_history.html: this ACL has been
+ around for long enough (and almost nobody uses batched payments,
+ so showing them is probably bad)
+
+2008-02-13 15:49 jeff
+
+ * FS/FS/svc_broadband.pm, httemplate/elements/header.html:
+ svc_broadband MAC searches RT#2985
+
+2008-02-13 15:45 jeff
+
+ * FS/FS/cust_main.pm, httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi: package class selection
+ for one-time charges RT#1322
+
+2008-02-13 15:39 jeff
+
+ * FS/FS/rate_detail.pm, FS/FS/part_pkg/voip_cdr.pm,
+ httemplate/edit/rate_region.cgi: directory assistance (flat
+ per-call) billing RT#3114
+
+2008-02-13 13:50 ivan
+
+ * httemplate/misc/process/link.cgi: fix compile error from hasty
+ refactoring
+
+2008-02-12 22:02 ivan
+
+ * FS/FS/part_pkg/bulk.pm: yup, bulk price plan appears to be
+ working
+
+2008-02-12 22:00 ivan
+
+ * README: modernizing
+
+2008-02-12 21:15 ivan
+
+ * FS/FS/cust_bill.pm: fix missing fill-in values on invoices
+ resulting from skewed hash ($conf->config returning empty list in
+ list context)
+
+2008-02-12 11:24 ivan
+
+ * httemplate/search/: rt_transaction.html, timeworked.html: for our
+ internal time tracking: TimeWorked can happen on a Create
+ transaction as well as Correspond and Comment. is there anywhere
+ else this needs to be changed?
+
+2008-02-11 19:11 ivan
+
+ * FS/FS/Misc.pm: update for MailTools v2.00
+
+2008-02-10 18:37 ivan
+
+ * FS/FS/reason.pm: upgrading reason table not quite working with
+ mysql, hopefully no old installs need this, new ones should be
+ fine hopefully
+
+2008-02-10 18:36 ivan
+
+ * FS/FS/: Upgrade.pm, cust_svc.pm, h_cust_svc.pm: fix & cleanup
+ duplicate history records
+
+2008-02-10 18:03 ivan
+
+ * FS/FS/reason.pm: better debugging if things go awry
+
+2008-02-10 16:53 ivan
+
+ * FS/FS/Cron/notify.pm: third time's the charm: MySQL didn't like
+ casting to INTEGER, it wants SIGNED. whew.
+
+2008-02-10 16:02 ivan
+
+ * FS/FS/Cron/notify.pm: ah, no, its count (*) vs count(*), wow
+
+2008-02-10 15:58 ivan
+
+ * FS/FS/Cron/notify.pm: comment out unused db statements in a way
+ that doesn't get to the database, to avoid Pg vs mysql
+ comment-out differences
+
+2008-02-09 11:16 ivan
+
+ * httemplate/edit/process/agent_type.cgi: typo, fix from mtou,
+ thanks
+
+2008-02-08 13:59 rsiddall
+
+ * rpm/freeside.spec: Removed code that create a freeside user on
+ the build machine and added code to modify Makefile to remove
+ clauses that require such a user. This should allow the RPMs to
+ build under mock.
+
+2008-02-08 07:00 jeff
+
+ * FS/FS/TicketSystem/RT_External.pm: tyop
+
+2008-02-04 19:37 ivan
+
+ * httemplate/edit/process/part_pkg.cgi: fix package editing on
+ HEAD, whew. bad semicolon.
+
+2008-02-02 18:24 ivan
+
+ * FS/FS/cust_main.pm: should eliminate "Use of uninitialized value
+ in length at /usr/local/share/perl/5.8.8/FS/cust_main.pm line
+ 5194." warnings
+
+2008-02-02 17:43 ivan
+
+ * httemplate/edit/cust_main.cgi: oops, fix display of errors on
+ customer edit
+
+2008-01-30 08:14 jeff
+
+ * httemplate/misc/bulk_change_pkg.cgi: pointless false laziness
+ removal
+
+2008-01-28 20:15 jeff
+
+ * FS/FS/cust_pkg.pm: missed use
+
+2008-01-28 19:56 jeff
+
+ * FS/FS/cust_pkg.pm: 1394 regression fixup
+
+2008-01-28 19:34 jeff
+
+ * FS/FS/cust_pkg.pm, httemplate/misc/bulk_change_pkg.cgi,
+ httemplate/misc/process/bulk_change_pkg.cgi,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/search/elements/search.html: bulk package changing
+ (RT#1394)
+
+2008-01-25 10:26 jeff
+
+ * httemplate/misc/cust_pay-import.cgi,
+ httemplate/misc/process/cust_pay-import.cgi, FS/FS/cust_pay.pm,
+ httemplate/elements/menu.html: simple payment CSV import
+
+2008-01-24 18:55 jeff
+
+ * FS/FS/part_export/prizm.pm: add an always BAM option and be
+ explicit about transactions
+
+2008-01-24 13:16 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ httemplate/view/cust_main/tickets.html: slightly more sane names
+ for customer tickets hash, display ticket owners on customer view
+ page
+
+2008-01-24 13:10 ivan
+
+ * htetc/handler.pl: used in rt autohandler. i wonder why this
+ never bit before
+
+2008-01-23 11:18 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/bill.html,
+ fs_selfservice/FS-SelfService/cgi/card.html,
+ fs_selfservice/FS-SelfService/cgi/change_bill.html,
+ fs_selfservice/FS-SelfService/cgi/change_pay.html,
+ fs_selfservice/FS-SelfService/cgi/change_ship.html,
+ fs_selfservice/FS-SelfService/cgi/check.html,
+ fs_selfservice/FS-SelfService/cgi/contact.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_bill.html,
+ FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/make_ach_payment.html,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_pay.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_ship.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: change
+ service, billing, and payment info in selfservice
+
+2008-01-20 16:12 ivan
+
+ * bin/explain-ar-total.sql: [no log message]
+
+2008-01-20 15:24 ivan
+
+ * FS/FS/Schema.pm: add and fix some indices, this should marginally
+ (but not drastically) improve the time to pull up A/R report
+ totals
+
+2008-01-16 20:23 ivan
+
+ * httemplate/edit/: part_pkg.cgi, process/part_pkg.cgi: fix ACLs to
+ allow the limited "package editing" of customizing customer
+ packages
+
+2008-01-16 19:18 ivan
+
+ * httemplate/view/cust_main/billing.html: don't show 'Bill now'
+ link unless the current user can...
+
+2008-01-13 16:22 ivan
+
+ * httemplate/: edit/part_bill_event.cgi,
+ elements/select-taxclass.html: maintenance on old events, yay.
+ fix for late charges without a taxclass, closes: RT#2988
+
+2008-01-13 16:17 ivan
+
+ * httemplate/edit/: cust_main.cgi, svc_www.cgi: fix tyops
+
+2008-01-13 15:31 ivan
+
+ * httemplate/search/timeworked.html: almost could work under mysql?
+ need TO_NUMBER and TO_CHAR equivalents
+
+2008-01-13 15:30 ivan
+
+ * httemplate/misc/timeworked.html: missing semicolon, doh
+
+2008-01-13 13:46 ivan
+
+ * httemplate/view/cust_pay.html: remove 1.7 ACL cruft on HEAD
+
+2008-01-13 13:45 ivan
+
+ * httemplate/view/cust_main/payment_history.html: remove 1.7.3
+ cruft
+
+2008-01-13 13:41 ivan
+
+ * httemplate/edit/: cust_bill_pay.cgi, process/cust_bill_pay.cgi,
+ cust_credit_bill.cgi, process/cust_credit_bill.cgi: new ACL name
+ in 1.9 right away
+
+2008-01-13 13:39 ivan
+
+ * httemplate/edit/: part_pkg.cgi, process/part_pkg.cgi: remove 1.7
+ vs. 1.9 cruft
+
+2008-01-13 13:35 ivan
+
+ * httemplate/edit/: REAL_cust_pkg.cgi, access_user.html, agent.cgi,
+ agent_payment_gateway.html, agent_type.cgi, bulk-cust_svc.html,
+ cust_bill_pay.cgi, cust_credit.cgi, cust_credit_bill.cgi,
+ cust_main.cgi, cust_main_county-expand.cgi, cust_main_note.cgi,
+ cust_pay.cgi, cust_pkg.cgi, cust_refund.cgi,
+ inventory_class.html, part_bill_event.cgi, part_export.cgi,
+ part_pkg.cgi, part_referral.html, part_svc.cgi,
+ part_virtual_field.cgi, payment_gateway.html, pkg_class.html,
+ prepay_credit.cgi, quick-charge.html, rate.cgi, rate_region.cgi,
+ reason.html, reason_type.html, reg_code.cgi, router.cgi,
+ svc_Common.html, svc_acct.cgi, svc_acct_pop.cgi,
+ svc_broadband.cgi, svc_domain.cgi, svc_external.cgi,
+ svc_forward.cgi, svc_phone.cgi, svc_www.cgi,
+ process/REAL_cust_pkg.cgi, process/access_user.html,
+ process/agent.cgi, process/agent_payment_gateway.html,
+ process/agent_type.cgi, process/bulk-cust_svc.cgi,
+ process/cust_bill_pay.cgi, process/cust_credit.cgi,
+ process/cust_credit_bill.cgi, process/cust_main.cgi,
+ process/cust_main_county-collapse.cgi,
+ process/cust_main_county-expand.cgi,
+ process/cust_main_county.html, process/cust_main_note.cgi,
+ process/cust_pay.cgi, process/cust_pkg.cgi,
+ process/cust_refund.cgi, process/cust_svc.cgi,
+ process/domain_record.cgi, process/generic.cgi,
+ process/inventory_class.html, process/msgcat.cgi,
+ process/part_bill_event.cgi, process/part_export.cgi,
+ process/part_pkg.cgi, process/part_referral.html,
+ process/part_svc.cgi, process/payment_gateway.html,
+ process/pkg_class.html, process/prepay_credit.cgi,
+ process/quick-charge.cgi, process/quick-cust_pkg.cgi,
+ process/rate.cgi, process/reason.html, process/reason_type.html,
+ process/reg_code.cgi, process/router.cgi,
+ process/svc_Common.html, process/svc_acct.cgi,
+ process/svc_acct_pop.cgi, process/svc_broadband.cgi,
+ process/svc_domain.cgi, process/svc_external.cgi,
+ process/svc_forward.cgi, process/svc_phone.html,
+ process/svc_www.cgi: ACLs
+
+2008-01-13 13:14 ivan
+
+ * httemplate/misc/: batch-cust_pay.html, bill.cgi,
+ cancel-unaudited.cgi, cancel_cust.html, cancel_pkg.html,
+ catchall.cgi, cdr-import.html, cust_main-cancel.cgi,
+ cust_main-import.cgi, cust_main-import_charges.cgi,
+ delete-cust_credit.cgi, delete-cust_pay.cgi,
+ delete-cust_refund.cgi, delete-customer.cgi,
+ delete-domain_record.cgi, delete-part_export.cgi, dump.cgi,
+ email-invoice.cgi, email_invoice_events.cgi, email_invoices.cgi,
+ fax-invoice.cgi, fax_invoice_events.cgi, fax_invoices.cgi,
+ inventory_item-import.html, link.cgi, meta-import.cgi,
+ payment.cgi, print-invoice.cgi, print_invoice_events.cgi,
+ print_invoices.cgi, queue.cgi, recharge_svc.html,
+ svc_acct-domains.cgi, unapply-cust_credit.cgi,
+ unapply-cust_pay.cgi, unprovision.cgi, unsusp_pkg.cgi,
+ unvoid-cust_pay_void.cgi, upload-batch.cgi, void-cust_pay.cgi,
+ whois.cgi, process/batch-cust_pay.cgi, process/cancel_pkg.html,
+ process/catchall.cgi, process/cdr-import.html,
+ process/cust_main-import.cgi,
+ process/cust_main-import_charges.cgi,
+ process/delete-customer.cgi, process/inventory_item-import.html,
+ process/link.cgi, process/meta-import.cgi, process/payment.cgi,
+ process/recharge_svc.html: ACLs
+
+2008-01-13 13:08 ivan
+
+ * httemplate/misc/: email_events.cgi, fax_events.cgi,
+ print_events.cgi, order_pkg.html: ACLs
+
+2008-01-13 12:55 ivan
+
+ * httemplate/: browse/part_bill_event.cgi, search/cust_event.html,
+ search/timeworked.html, search/cust_bill.html,
+ search/cust_bill_event.cgi, search/cust_pay_batch.cgi,
+ search/prepay_credit.html, search/queue.html,
+ search/report_prepaid_income.cgi, search/report_tax.cgi,
+ search/sqlradius.cgi: ACLs
+
+2008-01-13 12:50 ivan
+
+ * httemplate/elements/: errorpage.html, tr-select-reason.html:
+ stale leftovers from XSSmas
+
+2008-01-13 12:46 ivan
+
+ * httemplate/view/: cust_bill.cgi, svc_acct.cgi, svc_broadband.cgi,
+ svc_domain.cgi, svc_external.cgi, svc_forward.cgi, svc_www.cgi,
+ cust_main/payment_history.html, elements/svc_Common.html: ACLs
+
+2008-01-13 12:38 ivan
+
+ * httemplate/browse/: access_group.html, access_user.html,
+ addr_block.cgi, agent.cgi, agent_type.cgi, nas.cgi, part_pkg.cgi,
+ part_svc.cgi, part_virtual_field.cgi, payment_gateway.html,
+ reason.html, router.cgi: ACLs
+
+2008-01-13 12:30 ivan
+
+ * FS/FS/AccessRight.pm: new ACLs
+
+2008-01-12 16:35 ivan
+
+ * htetc/handler.pl: use this in handler.pl, not in mason files
+
+2008-01-11 15:10 ivan
+
+ * FS/FS/cust_main.pm: add option to enable searching of
+ cust_main.agent_custid with one or two letter prefix before the
+ numeric part
+
+2008-01-11 14:53 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: add option to enable searching of
+ cust_main.agent_custid with one or two letter prefix before the
+ numeric part
+
+2008-01-11 09:30 ivan
+
+ * httemplate/edit/elements/svc_Common.html: turn off debugging
+
+2008-01-10 14:13 ivan
+
+ * httemplate/search/elements/search.html: doc
+
+2008-01-10 14:06 ivan
+
+ * httemplate/elements/menu.html: new rate editor
+
+2008-01-10 13:53 ivan
+
+ * FS/FS/rate_detail.pm, httemplate/browse/rate.cgi,
+ httemplate/edit/rate.cgi, httemplate/edit/rate_region.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/rate_region.cgi: new rate editor
+
+2008-01-10 13:52 ivan
+
+ * httemplate/: browse/rate_detail.html, browse/rate_region.html,
+ edit/rate_detail.html, edit/process/rate_detail.html: new call
+ rate editor (VoIP/telephony)
+
+2008-01-10 13:17 ivan
+
+ * FS/FS/reason_type.pm: third person is better
+
+2008-01-10 13:14 ivan
+
+ * httemplate/browse/reason.html: eliminate harmless typo
+
+2008-01-08 13:33 jeff
+
+ * FS/FS/svc_acct.pm: transactiony cruft removal
+
+2008-01-08 03:23 ivan
+
+ * FS/FS/cust_credit.pm, FS/FS/cust_main.pm,
+ httemplate/search/report_receivables.cgi: show negative balances
+ on A/R report, closes: RT#2983
+
+2008-01-07 18:22 ivan
+
+ * httemplate/edit/process/cust_main.cgi: add some debugging control
+
+2008-01-03 18:42 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/cust_main_county-expand.cgi, edit/cust_main_county.html,
+ edit/process/cust_main_county-expand.cgi,
+ edit/process/cust_main_county.html,
+ edit/process/elements/process.html, search/elements/search.html:
+ new tax rate editor
+
+2008-01-03 18:35 ivan
+
+ * httemplate/: edit/cust_main_county.cgi,
+ edit/process/cust_main_county.cgi, browse/elements/browse.html:
+ new tax rate editor
+
+2008-01-03 18:27 ivan
+
+ * httemplate/edit/: prepay_credit.cgi, rate_region.cgi: leftovers
+ from XSSmas
+
+2008-01-03 18:20 ivan
+
+ * httemplate/elements/hidden.html: escape value
+
+2008-01-03 18:19 ivan
+
+ * httemplate/elements/: tablebreak-tr-title.html,
+ tr-fixed-country.html, tr-fixed-state.html,
+ tr-input-percentage.html: adding new elements: percentage input,
+ fixed country and state display, tablebreak+title
+
+2008-01-03 18:18 ivan
+
+ * httemplate/elements/tr-fixed.html: add a formatted_value option
+
+2008-01-03 18:18 ivan
+
+ * httemplate/elements/tr-input-text.html: add maxlength, text-align
+ and postfix options, escape value
+
+2008-01-03 18:13 ivan
+
+ * httemplate/edit/elements/edit.html: there's no such thing as
+ fixedhidden... hidden will do
+
+2008-01-03 18:02 ivan
+
+ * httemplate/edit/elements/edit.html: doc
+
+2008-01-03 17:43 ivan
+
+ * httemplate/edit/elements/edit.html: add popup option, add
+ percentage and tablebreak-tr-title field types, pass object to
+ included elements, documentation updates
+
+2007-12-28 11:02 jeff
+
+ * httemplate/: elements/menu.html, search/report_svc_acct.html,
+ search/svc_acct.cgi: advanced account reports (RT#2954)
+
+2007-12-28 07:19 jeff
+
+ * httemplate/elements/menu.html: whoops
+
+2007-12-28 07:10 jeff
+
+ * httemplate/: elements/menu.html, search/svc_acct.cgi: add never
+ logged in report
+
+2007-12-28 06:39 jeff
+
+ * FS/bin/freeside-sqlradius-set-lastlog: tool to seed
+ svc_acct.last_login and .last_logout
+
+2007-12-28 04:10 ivan
+
+ * htetc/handler.pl: remove just a tiny bit more cruft
+
+2007-12-28 04:01 ivan
+
+ * htetc/handler.pl: restore in-browser error reporting
+
+2007-12-27 23:45 ivan
+
+ * htetc/handler.pl: a little late help from kwanzabot for XSSmas...
+ clean up handler.pl so we can have separate default_escape_flags
+ for FS and RT and don't have to make FS's |h flag useless
+
+2007-12-27 17:41 jeff
+
+ * FS/FS/Schema.pm, FS/FS/svc_acct.pm,
+ FS/FS/part_export/sqlradius.pm, httemplate/search/svc_acct.cgi,
+ httemplate/view/svc_acct.cgi: last login reporting (#2952)
+
+2007-12-27 15:49 ivan
+
+ * httemplate/search/report_tax.cgi: fix reporting bug for invisimax
+ in edge case where you have taxclass and empty-taxclass rates for
+ a country/state(/county) and also have a different set of
+ taxclasses for some other country/state
+
+2007-12-26 14:52 jeff
+
+ * FS/FS/part_export/prizm.pm: conifgurable siteName and docs
+
+2007-12-26 00:23 ivan
+
+ * httemplate/misc/timeworked.html: leftovers from XSSmas
+
+2007-12-25 23:51 ivan
+
+ * httemplate/edit/quick-charge.html: alas, XSSmas draws to a close
+
+2007-12-25 15:49 ivan
+
+ * httemplate/: browse/addr_block.cgi,
+ browse/part_virtual_field.cgi, browse/router.cgi,
+ config/config.cgi, edit/agent.cgi,
+ edit/agent_payment_gateway.html, edit/agent_type.cgi,
+ edit/cust_bill_pay.cgi, edit/cust_credit.cgi,
+ edit/cust_credit_bill.cgi, edit/cust_main_note.cgi,
+ edit/cust_pay.cgi, edit/cust_pkg.cgi, edit/cust_refund.cgi,
+ edit/msgcat.cgi, edit/part_bill_event.cgi, edit/part_export.cgi,
+ edit/part_pkg.cgi, edit/part_virtual_field.cgi,
+ edit/payment_gateway.html, edit/reg_code.cgi, edit/router.cgi,
+ edit/svc_acct.cgi, edit/svc_broadband.cgi, edit/svc_domain.cgi,
+ edit/svc_forward.cgi, edit/elements/edit.html,
+ elements/error.html, misc/batch-cust_pay.html,
+ misc/cancel_cust.html, misc/cancel_pkg.html, misc/change_pkg.cgi,
+ misc/recharge_svc.html, misc/process/meta-import.cgi,
+ search/cust_bill_event.html, search/report_cust_event.html: ho ho
+ ho, merry XSSmas
+
+2007-12-23 14:05 jeff
+
+ * FS/FS/part_pkg/flat.pm, FS/FS/part_pkg/prorate.pm,
+ FS/FS/part_pkg/subscription.pm,
+ httemplate/misc/process/recharge_svc.html: add a reset feature to
+ manual recharges (#1858)
+
+2007-12-20 11:23 jeff
+
+ * FS/FS/part_export/prizm.pm: increase siteName allowed length
+
+2007-12-19 14:25 jeff
+
+ * httemplate/misc/cust_main-cancel.cgi: redirect redirect
+
+2007-12-19 13:05 jeff
+
+ * FS/FS/ConfDefaults.pm, FS/FS/UI/Web.pm,
+ httemplate/search/cust_main.html,
+ httemplate/search/report_cust_main.html: add options for balance
+ over/under to advanced customer report
+
+2007-12-18 17:55 jeff
+
+ * FS/FS/cust_credit.pm: underscoring the important
+
+2007-12-18 14:41 jeff
+
+ * httemplate/: edit/cust_credit.cgi,
+ elements/tr-select-reason.html: correct bad credit reason
+ conflict resolution
+
+2007-12-18 12:58 ivan
+
+ * FS/FS/cust_main.pm: legacy agent_custid field should be as
+ searchable as actual custnum, right? at least if it is a
+ number...
+
+2007-12-18 12:42 ivan
+
+ * httemplate/edit/quick-charge.html: IE is case-sensitive when
+ setting maxLength (and other attributes?). hopefully that's all
+ it is.
+
+2007-12-17 15:57 jeff
+
+ * httemplate/view/cust_main/quick-charge.html: cruft removal
+
+2007-12-17 14:57 jeff
+
+ * FS/FS/cust_credit.pm: stricter otaker rules
+
+2007-12-17 11:59 ivan
+
+ * FS/FS/TicketSystem/RT_Internal.pm: no, *that's* where it couldn't
+ hurt anything.
+
+2007-12-17 11:52 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: i don't think it can hurt
+ anything... (famous last words)
+
+2007-12-16 17:17 ivan
+
+ * httemplate/view/cust_main/contacts.html: fix the case where the
+ customer doesn't actually have a ship address
+
+2007-12-16 16:59 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/elements/header.html,
+ httemplate/view/cust_main/contacts.html,
+ httemplate/search/cust_main.cgi: add cust_main-require_address2
+ config, reimplement address2-search config ("Unit #" search in
+ searchbar), visual indication of require_invoicing_list_email,
+ closes: RT#2926
+
+2007-12-16 14:40 ivan
+
+ * httemplate/elements/errorpage.html: less is better
+
+2007-12-16 13:02 ivan
+
+ * httemplate/elements/header.html: more consistent naming:
+ cust_main_ADV.cgi becomes cust_main.html
+
+2007-12-16 13:01 ivan
+
+ * httemplate/search/report_cust_main.html:
+ httemplate/elements/header.html
+
+2007-12-16 12:48 ivan
+
+ * httemplate/search/: cust_main.html, cust_main_ADV.cgi: more
+ consistent naming: cust_main_ADV.cgi becomes cust_main.html
+
+2007-12-15 14:47 rsiddall
+
+ * rpm/: INSTALL, freeside.spec, freeside.sysconfig, rpm2Bundle:
+ Files to build Freeside as Redhat-ish RPMs
+
+2007-12-14 17:45 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/search/cust_bill.html: fix earlier
+ drain bramage
+
+2007-12-14 17:37 ivan
+
+ * httemplate/search/cust_bill.html: where helps alot
+
+2007-12-14 17:23 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/search/cust_bill.html: hopefully
+ put reprinting issues to rest for ejourney, yow
+
+2007-12-14 15:41 jeff
+
+ * FS/bin/freeside-upgrade: yikes
+
+2007-12-14 13:51 jeff
+
+ * FS/FS/Schema.pm: binary not required and breaks
+ FS::Record::_quote
+
+2007-12-14 13:32 jeff
+
+ * FS/bin/freeside-upgrade: correct order of operations
+
+2007-12-14 08:47 jeff
+
+ * FS/FS/cust_credit.pm: 1.9 Conf::set returns false on success
+
+2007-12-13 19:56 jeff
+
+ * FS/bin/freeside-upgrade: even more deliberate reset
+
+2007-12-13 19:55 ivan
+
+ * httemplate/search/svc_acct.cgi: quick hack to show time worked in
+ last 1-3 months...
+
+2007-12-12 16:17 jeff
+
+ * bin/reset-cust_credit-otaker: cust_credit reason/otaker tool
+
+2007-12-12 13:18 jeff
+
+ * FS/FS/part_export/www_shellcommands.pm: add suspend/unsuspend to
+ www_shellcommands export (#1227)
+
+2007-12-12 01:03 ivan
+
+ * FS/bin/freeside-history-requeue: adding this quick script
+
+2007-12-11 21:58 jeff
+
+ * FS/FS/Setup.pm, FS/FS/svc_acct.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/svc_acct.html,
+ httemplate/edit/svc_acct.cgi: self-service can select domain on
+ provision (#2801)
+
+2007-12-11 21:42 jeff
+
+ * FS/: FS/cust_credit.pm, FS/h_cust_credit.pm,
+ bin/freeside-disable-reasons, bin/freeside-upgrade: cust_credit
+ reason improvement, bugfix, and tool
+
+2007-12-06 17:08 ivan
+
+ * FS/FS/cust_credit.pm: doh! is not an object. let's call it ,
+ mmkay
+
+2007-12-06 17:04 ivan
+
+ * FS/FS/cust_credit.pm: some old databases may have 'hanging'
+ cust_credit records; we don't want to abort the upgrade because
+ of that, just warn
+
+2007-12-06 12:49 jeff
+
+ * httemplate/edit/part_pkg.cgi: agent setting during package edit
+ cleanup
+
+2007-12-06 08:51 jeff
+
+ * httemplate/view/svc_acct.cgi: support display of negative time
+
+2007-12-05 14:05 ivan
+
+ * Makefile: when installing selfservice, create freeside homedir if
+ it doesn't exist
+
+2007-12-05 12:50 ivan
+
+ * httemplate/elements/tr-select-reason.html: doh, order_by does
+ have to include ORDER BY!
+
+2007-12-05 12:47 ivan
+
+ * httemplate/elements/tr-select-reason.html: show types in reason
+ selection, order by type and reason
+
+2007-12-05 07:10 jeff
+
+ * FS/FS/ConfDefaults.pm: add in status and company fields
+
+2007-12-05 06:50 jeff
+
+ * FS/FS/cust_main.pm: ensure a valid date is onhand (fixes #2800)
+
+2007-12-04 20:57 jeff
+
+ * httemplate/edit/process/part_pkg.cgi: wtf?
+
+2007-12-04 16:45 ivan
+
+ * httemplate/search/elements/search.html: i hope this allows IE to
+ download excel over https?
+
+2007-12-04 13:28 ivan
+
+ * sql-ledger/: VERSION, am.pl, favicon.ico, index.html, login.pl,
+ menu.ini, setup.pl, sql-ledger.conf.default, sql-ledger.gif,
+ sql-ledger.png, SL/AM.pm, SL/AP.pm, SL/AR.pm, SL/BP.pm, SL/CA.pm,
+ SL/CP.pm, SL/CT.pm, SL/Form.pm, SL/GL.pm, SL/HR.pm, SL/IC.pm,
+ SL/IR.pm, SL/IS.pm, SL/Inifile.pm, SL/Mailer.pm, SL/Menu.pm,
+ SL/Num2text.pm, SL/OE.pm, SL/OP.pm, SL/PE.pm, SL/RC.pm, SL/RP.pm,
+ SL/User.pm, bin/js/menu.pl, bin/lynx/menu.pl,
+ bin/mozilla/admin.pl, bin/mozilla/am.pl, bin/mozilla/ap.pl,
+ bin/mozilla/ar.pl, bin/mozilla/arap.pl, bin/mozilla/arapprn.pl,
+ bin/mozilla/bp.pl, bin/mozilla/ca.pl, bin/mozilla/cp.pl,
+ bin/mozilla/ct.pl, bin/mozilla/gl.pl, bin/mozilla/hr.pl,
+ bin/mozilla/ic.pl, bin/mozilla/io.pl, bin/mozilla/ir.pl,
+ bin/mozilla/is.pl, bin/mozilla/login.pl, bin/mozilla/menu.pl,
+ bin/mozilla/oe.pl, bin/mozilla/pe.pl, bin/mozilla/pos.pl,
+ bin/mozilla/ps.pl, bin/mozilla/pw.pl, bin/mozilla/rc.pl,
+ bin/mozilla/rp.pl, css/sql-ledger.css, doc/COPYING,
+ doc/COPYRIGHT, doc/README, doc/README.DB2, doc/UPGRADE-1.6-1.8,
+ doc/UPGRADE-1.8-1.8.3, doc/UPGRADE-1.8.3-1.8.4,
+ doc/UPGRADE-1.8.4-1.8.5, doc/UPGRADE-1.8.5-1.8.7,
+ doc/UPGRADE-1.8.7-2.0.0, doc/UPGRADE-2.0-2.0.8,
+ doc/UPGRADE-2.0.8-2.0.9, doc/UPGRADE-2.0.9-2.2.0,
+ doc/UPGRADE-2.2.0-2.2.7, doc/UPGRADE-2.2.7-2.4.0,
+ doc/UPGRADE-2.4.0-2.4.1, doc/UPGRADE-2.4.1-2.4.2,
+ doc/UPGRADE-2.4.2-2.4.3, doc/UPGRADE-2.4.3-2.4.4, doc/faq.html,
+ locale/be_nl/COPYING, locale/be_nl/LANGUAGE,
+ locale/be_nl/Num2text, locale/be_nl/admin, locale/be_nl/all,
+ locale/be_nl/am, locale/be_nl/ap, locale/be_nl/ar,
+ locale/be_nl/arap, locale/be_nl/arapprn, locale/be_nl/bp,
+ locale/be_nl/ca, locale/be_nl/cp, locale/be_nl/ct,
+ locale/be_nl/gl, locale/be_nl/hr, locale/be_nl/ic,
+ locale/be_nl/io, locale/be_nl/ir, locale/be_nl/is,
+ locale/be_nl/login, locale/be_nl/menu, locale/be_nl/oe,
+ locale/be_nl/pe, locale/be_nl/pos, locale/be_nl/ps,
+ locale/be_nl/pw, locale/be_nl/rc, locale/be_nl/rp,
+ locale/br/COPYING, locale/br/LANGUAGE, locale/br/admin,
+ locale/br/all, locale/br/am, locale/br/ap, locale/br/ar,
+ locale/br/arap, locale/br/arapprn, locale/br/bp, locale/br/ca,
+ locale/br/cp, locale/br/ct, locale/br/gl, locale/br/hr,
+ locale/br/ic, locale/br/io, locale/br/ir, locale/br/is,
+ locale/br/login, locale/br/menu, locale/br/oe, locale/br/pe,
+ locale/br/pos, locale/br/ps, locale/br/pw, locale/br/rc,
+ locale/br/rp, locale/cn_utf/COPYING, locale/cn_utf/LANGUAGE,
+ locale/cn_utf/admin, locale/cn_utf/all, locale/cn_utf/am,
+ locale/cn_utf/ap, locale/cn_utf/ar, locale/cn_utf/arap,
+ locale/cn_utf/arapprn, locale/cn_utf/bp, locale/cn_utf/ca,
+ locale/cn_utf/cp, locale/cn_utf/ct, locale/cn_utf/gl,
+ locale/cn_utf/hr, locale/cn_utf/ic, locale/cn_utf/io,
+ locale/cn_utf/ir, locale/cn_utf/is, locale/cn_utf/login,
+ locale/cn_utf/menu, locale/cn_utf/oe, locale/cn_utf/pe,
+ locale/cn_utf/pos, locale/cn_utf/ps, locale/cn_utf/pw,
+ locale/cn_utf/rc, locale/cn_utf/rp, locale/co/COPYING,
+ locale/co/LANGUAGE, locale/co/Num2text, locale/co/admin,
+ locale/co/all, locale/co/am, locale/co/ap, locale/co/ar,
+ locale/co/arap, locale/co/arapprn, locale/co/bp, locale/co/ca,
+ locale/co/cp, locale/co/ct, locale/co/gl, locale/co/hr,
+ locale/co/ic, locale/co/io, locale/co/ir, locale/co/is,
+ locale/co/login, locale/co/menu, locale/co/oe, locale/co/pe,
+ locale/co/pos, locale/co/ps, locale/co/pw, locale/co/rc,
+ locale/co/rp, locale/ct/COPYING, locale/ct/LANGUAGE,
+ locale/ct/admin, locale/ct/all, locale/ct/am, locale/ct/ap,
+ locale/ct/ar, locale/ct/arap, locale/ct/arapprn, locale/ct/bp,
+ locale/ct/ca, locale/ct/cp, locale/ct/ct, locale/ct/gl,
+ locale/ct/hr, locale/ct/ic, locale/ct/io, locale/ct/ir,
+ locale/ct/is, locale/ct/login, locale/ct/menu, locale/ct/oe,
+ locale/ct/pe, locale/ct/pos, locale/ct/ps, locale/ct/pw,
+ locale/ct/rc, locale/ct/rp, locale/cz/COPYING,
+ locale/cz/LANGUAGE, locale/cz/admin, locale/cz/all, locale/cz/am,
+ locale/cz/ap, locale/cz/ar, locale/cz/arap, locale/cz/arapprn,
+ locale/cz/bp, locale/cz/ca, locale/cz/cp, locale/cz/ct,
+ locale/cz/gl, locale/cz/hr, locale/cz/ic, locale/cz/io,
+ locale/cz/ir, locale/cz/is, locale/cz/login, locale/cz/menu,
+ locale/cz/oe, locale/cz/pe, locale/cz/pos, locale/cz/ps,
+ locale/cz/pw, locale/cz/rc, locale/cz/rp, locale/de/COPYING,
+ locale/de/LANGUAGE, locale/de/Num2text, locale/de/admin,
+ locale/de/am, locale/de/ap, locale/de/ar, locale/de/arap,
+ locale/de/arapprn, locale/de/bp, locale/de/ca, locale/de/cp,
+ locale/de/ct, locale/de/gl, locale/de/hr, locale/de/ic,
+ locale/de/io, locale/de/ir, locale/de/is, locale/de/locales.pl,
+ locale/de/login, locale/de/menu, locale/de/oe, locale/de/pe,
+ locale/de/pos, locale/de/ps, locale/de/pw, locale/de/rc,
+ locale/de/rp, locale/dk/COPYING, locale/dk/LANGUAGE,
+ locale/dk/admin, locale/dk/all, locale/dk/am, locale/dk/ap,
+ locale/dk/ar, locale/dk/arap, locale/dk/arapprn, locale/dk/bp,
+ locale/dk/ca, locale/dk/cp, locale/dk/ct, locale/dk/gl,
+ locale/dk/hr, locale/dk/ic, locale/dk/io, locale/dk/ir,
+ locale/dk/is, locale/dk/login, locale/dk/menu, locale/dk/oe,
+ locale/dk/pe, locale/dk/pos, locale/dk/ps, locale/dk/pw,
+ locale/dk/rc, locale/dk/rp, locale/ec/COPYING,
+ locale/ec/LANGUAGE, locale/ec/Num2text, locale/ec/admin,
+ locale/ec/all, locale/ec/am, locale/ec/ap, locale/ec/ar,
+ locale/ec/arap, locale/ec/arapprn, locale/ec/bp, locale/ec/ca,
+ locale/ec/cp, locale/ec/ct, locale/ec/gl, locale/ec/hr,
+ locale/ec/ic, locale/ec/io, locale/ec/ir, locale/ec/is,
+ locale/ec/login, locale/ec/menu, locale/ec/oe, locale/ec/pe,
+ locale/ec/pos, locale/ec/ps, locale/ec/pw, locale/ec/rc,
+ locale/ec/rp, locale/ee/COPYING, locale/ee/LANGUAGE,
+ locale/ee/Num2text, locale/ee/admin, locale/ee/all, locale/ee/am,
+ locale/ee/ap, locale/ee/ar, locale/ee/arap, locale/ee/arapprn,
+ locale/ee/bp, locale/ee/ca, locale/ee/cp, locale/ee/ct,
+ locale/ee/gl, locale/ee/hr, locale/ee/ic, locale/ee/io,
+ locale/ee/ir, locale/ee/is, locale/ee/login, locale/ee/menu,
+ locale/ee/oe, locale/ee/pe, locale/ee/pos, locale/ee/ps,
+ locale/ee/pw, locale/ee/rc, locale/ee/rp, locale/eg/COPYING,
+ locale/eg/LANGUAGE, locale/eg/admin, locale/eg/all, locale/eg/am,
+ locale/eg/ap, locale/eg/ar, locale/eg/arap, locale/eg/arapprn,
+ locale/eg/bp, locale/eg/ca, locale/eg/cp, locale/eg/ct,
+ locale/eg/gl, locale/eg/hr, locale/eg/ic, locale/eg/io,
+ locale/eg/ir, locale/eg/is, locale/eg/login, locale/eg/menu,
+ locale/eg/oe, locale/eg/pe, locale/eg/pos, locale/eg/ps,
+ locale/eg/pw, locale/eg/rc, locale/eg/rp, locale/en_GB/COPYING,
+ locale/en_GB/LANGUAGE, locale/en_GB/admin, locale/en_GB/all,
+ locale/en_GB/am, locale/en_GB/ap, locale/en_GB/ar,
+ locale/en_GB/arap, locale/en_GB/arapprn, locale/en_GB/bp,
+ locale/en_GB/ca, locale/en_GB/cp, locale/en_GB/ct,
+ locale/en_GB/gl, locale/en_GB/hr, locale/en_GB/ic,
+ locale/en_GB/io, locale/en_GB/ir, locale/en_GB/is,
+ locale/en_GB/login, locale/en_GB/menu, locale/en_GB/oe,
+ locale/en_GB/pe, locale/en_GB/pos, locale/en_GB/ps,
+ locale/en_GB/pw, locale/en_GB/rc, locale/en_GB/rp,
+ locale/es_iso/COPYING, locale/es_iso/LANGUAGE,
+ locale/es_iso/Num2text, locale/es_iso/admin, locale/es_iso/all,
+ locale/es_iso/am, locale/es_iso/ap, locale/es_iso/ar,
+ locale/es_iso/arap, locale/es_iso/arapprn, locale/es_iso/bp,
+ locale/es_iso/ca, locale/es_iso/cp, locale/es_iso/ct,
+ locale/es_iso/gl, locale/es_iso/hr, locale/es_iso/ic,
+ locale/es_iso/io, locale/es_iso/ir, locale/es_iso/is,
+ locale/es_iso/login, locale/es_iso/menu, locale/es_iso/oe,
+ locale/es_iso/pe, locale/es_iso/pos, locale/es_iso/ps,
+ locale/es_iso/pw, locale/es_iso/rc, locale/es_iso/rp,
+ locale/es_utf/COPYING, locale/es_utf/LANGUAGE,
+ locale/es_utf/Num2text, locale/es_utf/admin, locale/es_utf/all,
+ locale/es_utf/am, locale/es_utf/ap, locale/es_utf/ar,
+ locale/es_utf/arap, locale/es_utf/arapprn, locale/es_utf/bp,
+ locale/es_utf/ca, locale/es_utf/cp, locale/es_utf/ct,
+ locale/es_utf/gl, locale/es_utf/hr, locale/es_utf/ic,
+ locale/es_utf/io, locale/es_utf/ir, locale/es_utf/is,
+ locale/es_utf/login, locale/es_utf/menu, locale/es_utf/oe,
+ locale/es_utf/pe, locale/es_utf/pos, locale/es_utf/ps,
+ locale/es_utf/pw, locale/es_utf/rc, locale/es_utf/rp,
+ locale/fi/COPYING, locale/fi/LANGUAGE, locale/fi/admin,
+ locale/fi/all, locale/fi/am, locale/fi/ap, locale/fi/ar,
+ locale/fi/arap, locale/fi/arapprn, locale/fi/bp, locale/fi/ca,
+ locale/fi/cp, locale/fi/ct, locale/fi/gl, locale/fi/hr,
+ locale/fi/ic, locale/fi/io, locale/fi/ir, locale/fi/is,
+ locale/fi/login, locale/fi/menu, locale/fi/oe, locale/fi/pe,
+ locale/fi/pos, locale/fi/ps, locale/fi/pw, locale/fi/rc,
+ locale/fi/rp, locale/fr/COPYING, locale/fr/LANGUAGE,
+ locale/fr/Num2text, locale/fr/admin, locale/fr/all, locale/fr/am,
+ locale/fr/ap, locale/fr/ar, locale/fr/arap, locale/fr/arapprn,
+ locale/fr/bp, locale/fr/ca, locale/fr/cp, locale/fr/ct,
+ locale/fr/gl, locale/fr/hr, locale/fr/ic, locale/fr/io,
+ locale/fr/ir, locale/fr/is, locale/fr/login, locale/fr/menu,
+ locale/fr/oe, locale/fr/pe, locale/fr/pos, locale/fr/ps,
+ locale/fr/pw, locale/fr/rc, locale/fr/rp, locale/gr/COPYING,
+ locale/gr/LANGUAGE, locale/gr/admin, locale/gr/all, locale/gr/am,
+ locale/gr/ap, locale/gr/ar, locale/gr/arap, locale/gr/arapprn,
+ locale/gr/bp, locale/gr/ca, locale/gr/cp, locale/gr/ct,
+ locale/gr/gl, locale/gr/hr, locale/gr/ic, locale/gr/io,
+ locale/gr/ir, locale/gr/is, locale/gr/login, locale/gr/menu,
+ locale/gr/oe, locale/gr/pe, locale/gr/pos, locale/gr/ps,
+ locale/gr/pw, locale/gr/rc, locale/gr/rp, locale/hu/COPYING,
+ locale/hu/LANGUAGE, locale/hu/Num2text, locale/hu/admin,
+ locale/hu/all, locale/hu/am, locale/hu/ap, locale/hu/ar,
+ locale/hu/arap, locale/hu/arapprn, locale/hu/bp, locale/hu/ca,
+ locale/hu/cp, locale/hu/ct, locale/hu/gl, locale/hu/hr,
+ locale/hu/ic, locale/hu/io, locale/hu/ir, locale/hu/is,
+ locale/hu/login, locale/hu/menu, locale/hu/oe, locale/hu/pe,
+ locale/hu/pos, locale/hu/ps, locale/hu/pw, locale/hu/rc,
+ locale/hu/rp, locale/is/COPYING, locale/is/LANGUAGE,
+ locale/is/admin, locale/is/all, locale/is/am, locale/is/ap,
+ locale/is/ar, locale/is/arap, locale/is/arapprn, locale/is/bp,
+ locale/is/ca, locale/is/cp, locale/is/ct, locale/is/gl,
+ locale/is/hr, locale/is/ic, locale/is/io, locale/is/ir,
+ locale/is/is, locale/is/login, locale/is/menu, locale/is/oe,
+ locale/is/pe, locale/is/pos, locale/is/ps, locale/is/pw,
+ locale/is/rc, locale/is/rp, locale/it/COPYING,
+ locale/it/LANGUAGE, locale/it/Num2text, locale/it/admin,
+ locale/it/all, locale/it/am, locale/it/ap, locale/it/ar,
+ locale/it/arap, locale/it/arapprn, locale/it/bp, locale/it/ca,
+ locale/it/cp, locale/it/ct, locale/it/gl, locale/it/hr,
+ locale/it/ic, locale/it/io, locale/it/ir, locale/it/is,
+ locale/it/login, locale/it/menu, locale/it/oe, locale/it/pe,
+ locale/it/pos, locale/it/ps, locale/it/pw, locale/it/qe,
+ locale/it/rc, locale/it/rp, locale/lt/COPYING,
+ locale/lt/LANGUAGE, locale/lt/admin, locale/lt/all, locale/lt/am,
+ locale/lt/ap, locale/lt/ar, locale/lt/arap, locale/lt/arapprn,
+ locale/lt/bp, locale/lt/ca, locale/lt/cp, locale/lt/ct,
+ locale/lt/gl, locale/lt/hr, locale/lt/ic, locale/lt/io,
+ locale/lt/ir, locale/lt/is, locale/lt/login, locale/lt/menu,
+ locale/lt/oe, locale/lt/pe, locale/lt/pos, locale/lt/ps,
+ locale/lt/pw, locale/lt/rc, locale/lt/rp, locale/lv/COPYING,
+ locale/lv/LANGUAGE, locale/lv/admin, locale/lv/all, locale/lv/am,
+ locale/lv/ap, locale/lv/ar, locale/lv/arap, locale/lv/arapprn,
+ locale/lv/bp, locale/lv/ca, locale/lv/cp, locale/lv/ct,
+ locale/lv/gl, locale/lv/hr, locale/lv/ic, locale/lv/io,
+ locale/lv/ir, locale/lv/is, locale/lv/login, locale/lv/menu,
+ locale/lv/oe, locale/lv/pe, locale/lv/pos, locale/lv/ps,
+ locale/lv/pw, locale/lv/rc, locale/lv/rp, locale/mx/COPYING,
+ locale/mx/LANGUAGE, locale/mx/admin, locale/mx/all, locale/mx/am,
+ locale/mx/ap, locale/mx/ar, locale/mx/arap, locale/mx/arapprn,
+ locale/mx/bp, locale/mx/ca, locale/mx/cp, locale/mx/ct,
+ locale/mx/gl, locale/mx/hr, locale/mx/ic, locale/mx/io,
+ locale/mx/ir, locale/mx/is, locale/mx/login, locale/mx/menu,
+ locale/mx/oe, locale/mx/pe, locale/mx/pos, locale/mx/ps,
+ locale/mx/pw, locale/mx/rc, locale/mx/rp, locale/nb/COPYING,
+ locale/nb/LANGUAGE, locale/nb/admin, locale/nb/all, locale/nb/am,
+ locale/nb/ap, locale/nb/ar, locale/nb/arap, locale/nb/arapprn,
+ locale/nb/bp, locale/nb/ca, locale/nb/cp, locale/nb/ct,
+ locale/nb/gl, locale/nb/hr, locale/nb/ic, locale/nb/io,
+ locale/nb/ir, locale/nb/is, locale/nb/login, locale/nb/menu,
+ locale/nb/oe, locale/nb/pe, locale/nb/pos, locale/nb/ps,
+ locale/nb/pw, locale/nb/rc, locale/nb/rp, locale/nl/COPYING,
+ locale/nl/LANGUAGE, locale/nl/Num2text, locale/nl/admin,
+ locale/nl/all, locale/nl/am, locale/nl/ap, locale/nl/ar,
+ locale/nl/arap, locale/nl/arapprn, locale/nl/bp, locale/nl/ca,
+ locale/nl/cp, locale/nl/ct, locale/nl/gl, locale/nl/hr,
+ locale/nl/ic, locale/nl/io, locale/nl/ir, locale/nl/is,
+ locale/nl/login, locale/nl/menu, locale/nl/oe, locale/nl/pe,
+ locale/nl/pos, locale/nl/ps, locale/nl/pw, locale/nl/rc,
+ locale/nl/rp, locale/pa/COPYING, locale/pa/LANGUAGE,
+ locale/pa/admin, locale/pa/all, locale/pa/am, locale/pa/ap,
+ locale/pa/ar, locale/pa/arap, locale/pa/arapprn, locale/pa/bp,
+ locale/pa/ca, locale/pa/cp, locale/pa/ct, locale/pa/gl,
+ locale/pa/hr, locale/pa/ic, locale/pa/io, locale/pa/ir,
+ locale/pa/is, locale/pa/login, locale/pa/menu, locale/pa/oe,
+ locale/pa/pe, locale/pa/pos, locale/pa/ps, locale/pa/pw,
+ locale/pa/rc, locale/pa/rp, locale/pl/COPYING,
+ locale/pl/LANGUAGE, locale/pl/admin, locale/pl/all, locale/pl/am,
+ locale/pl/ap, locale/pl/ar, locale/pl/arap, locale/pl/arapprn,
+ locale/pl/bp, locale/pl/ca, locale/pl/cp, locale/pl/ct,
+ locale/pl/gl, locale/pl/hr, locale/pl/ic, locale/pl/io,
+ locale/pl/ir, locale/pl/is, locale/pl/login, locale/pl/menu,
+ locale/pl/oe, locale/pl/pe, locale/pl/pos, locale/pl/ps,
+ locale/pl/pw, locale/pl/rc, locale/pl/rp, locale/pt/COPYING,
+ locale/pt/LANGUAGE, locale/pt/admin, locale/pt/all, locale/pt/am,
+ locale/pt/ap, locale/pt/ar, locale/pt/arap, locale/pt/arapprn,
+ locale/pt/bp, locale/pt/ca, locale/pt/cp, locale/pt/ct,
+ locale/pt/gl, locale/pt/hr, locale/pt/ic, locale/pt/io,
+ locale/pt/ir, locale/pt/is, locale/pt/login, locale/pt/menu,
+ locale/pt/oe, locale/pt/pe, locale/pt/pos, locale/pt/ps,
+ locale/pt/pw, locale/pt/rc, locale/pt/rp, locale/ru/COPYING,
+ locale/ru/LANGUAGE, locale/ru/admin, locale/ru/all, locale/ru/am,
+ locale/ru/ap, locale/ru/ar, locale/ru/arap, locale/ru/arapprn,
+ locale/ru/bp, locale/ru/ca, locale/ru/cp, locale/ru/ct,
+ locale/ru/gl, locale/ru/hr, locale/ru/ic, locale/ru/io,
+ locale/ru/ir, locale/ru/is, locale/ru/login, locale/ru/menu,
+ locale/ru/oe, locale/ru/pe, locale/ru/pos, locale/ru/ps,
+ locale/ru/pw, locale/ru/rc, locale/ru/rp, locale/se/COPYING,
+ locale/se/LANGUAGE, locale/se/admin, locale/se/all, locale/se/am,
+ locale/se/ap, locale/se/ar, locale/se/arap, locale/se/arapprn,
+ locale/se/bp, locale/se/ca, locale/se/cp, locale/se/ct,
+ locale/se/gl, locale/se/hr, locale/se/ic, locale/se/io,
+ locale/se/ir, locale/se/is, locale/se/login, locale/se/menu,
+ locale/se/oe, locale/se/pe, locale/se/pos, locale/se/ps,
+ locale/se/pw, locale/se/rc, locale/se/rp, locale/sv/COPYING,
+ locale/sv/LANGUAGE, locale/sv/admin, locale/sv/all, locale/sv/am,
+ locale/sv/ap, locale/sv/ar, locale/sv/arap, locale/sv/arapprn,
+ locale/sv/bp, locale/sv/ca, locale/sv/cp, locale/sv/ct,
+ locale/sv/gl, locale/sv/hr, locale/sv/ic, locale/sv/io,
+ locale/sv/ir, locale/sv/is, locale/sv/login, locale/sv/menu,
+ locale/sv/oe, locale/sv/pe, locale/sv/pos, locale/sv/ps,
+ locale/sv/pw, locale/sv/rc, locale/sv/rp, locale/tr/COPYING,
+ locale/tr/LANGUAGE, locale/tr/admin, locale/tr/all, locale/tr/am,
+ locale/tr/ap, locale/tr/ar, locale/tr/arap, locale/tr/arapprn,
+ locale/tr/bp, locale/tr/ca, locale/tr/cp, locale/tr/ct,
+ locale/tr/gl, locale/tr/hr, locale/tr/ic, locale/tr/io,
+ locale/tr/ir, locale/tr/is, locale/tr/login, locale/tr/menu,
+ locale/tr/oe, locale/tr/pe, locale/tr/pos, locale/tr/ps,
+ locale/tr/pw, locale/tr/rc, locale/tr/rp, locale/tw_big5/COPYING,
+ locale/tw_big5/LANGUAGE, locale/tw_big5/admin,
+ locale/tw_big5/all, locale/tw_big5/am, locale/tw_big5/ap,
+ locale/tw_big5/ar, locale/tw_big5/arap, locale/tw_big5/arapprn,
+ locale/tw_big5/bp, locale/tw_big5/ca, locale/tw_big5/cp,
+ locale/tw_big5/ct, locale/tw_big5/gl, locale/tw_big5/hr,
+ locale/tw_big5/ic, locale/tw_big5/io, locale/tw_big5/ir,
+ locale/tw_big5/is, locale/tw_big5/login, locale/tw_big5/menu,
+ locale/tw_big5/oe, locale/tw_big5/pe, locale/tw_big5/pos,
+ locale/tw_big5/ps, locale/tw_big5/pw, locale/tw_big5/rc,
+ locale/tw_big5/rp, locale/tw_big5/temp, locale/tw_utf/COPYING,
+ locale/tw_utf/LANGUAGE, locale/tw_utf/admin, locale/tw_utf/all,
+ locale/tw_utf/am, locale/tw_utf/ap, locale/tw_utf/ar,
+ locale/tw_utf/arap, locale/tw_utf/arapprn, locale/tw_utf/bp,
+ locale/tw_utf/ca, locale/tw_utf/cp, locale/tw_utf/ct,
+ locale/tw_utf/gl, locale/tw_utf/hr, locale/tw_utf/ic,
+ locale/tw_utf/io, locale/tw_utf/ir, locale/tw_utf/is,
+ locale/tw_utf/login, locale/tw_utf/menu, locale/tw_utf/oe,
+ locale/tw_utf/pe, locale/tw_utf/pos, locale/tw_utf/ps,
+ locale/tw_utf/pw, locale/tw_utf/rc, locale/tw_utf/rp,
+ locale/ua/COPYING, locale/ua/LANGUAGE, locale/ua/admin,
+ locale/ua/all, locale/ua/am, locale/ua/ap, locale/ua/ar,
+ locale/ua/arap, locale/ua/arapprn, locale/ua/bp, locale/ua/ca,
+ locale/ua/cp, locale/ua/ct, locale/ua/gl, locale/ua/hr,
+ locale/ua/ic, locale/ua/io, locale/ua/ir, locale/ua/is,
+ locale/ua/login, locale/ua/menu, locale/ua/oe, locale/ua/pe,
+ locale/ua/pos, locale/ua/ps, locale/ua/pw, locale/ua/rc,
+ locale/ua/rp, locale/ve/COPYING, locale/ve/LANGUAGE,
+ locale/ve/admin, locale/ve/all, locale/ve/am, locale/ve/ap,
+ locale/ve/ar, locale/ve/arap, locale/ve/arapprn, locale/ve/bp,
+ locale/ve/ca, locale/ve/cp, locale/ve/ct, locale/ve/gl,
+ locale/ve/hr, locale/ve/ic, locale/ve/io, locale/ve/ir,
+ locale/ve/is, locale/ve/login, locale/ve/menu, locale/ve/oe,
+ locale/ve/pe, locale/ve/pos, locale/ve/ps, locale/ve/pw,
+ locale/ve/rc, locale/ve/rp, sql/Austria-chart.sql,
+ sql/Austria-gifi.sql, sql/Belgium-chart.sql,
+ sql/Belgium-gifi.sql, sql/Brazil_General-chart.sql,
+ sql/Canada-English-gifi.sql,
+ sql/Canada-English_General-chart.sql, sql/Canada-French-gifi.sql,
+ sql/Colombia-PUC-chart.sql, sql/Colombia-PUC-gifi.sql,
+ sql/Czech-Republic-chart.sql, sql/DB2-create.sql,
+ sql/DB2-indices.sql, sql/DB2-remove.sql, sql/DB2-set.sql,
+ sql/DB2-sql-ledger.order, sql/DB2-tables.sql,
+ sql/Danish_Default-chart.sql, sql/Default-chart.sql,
+ sql/Dutch_Default-chart.sql, sql/Dutch_Standard-chart.sql,
+ sql/Egypt-chart.sql, sql/France-chart.sql,
+ sql/German-Sample-chart.sql, sql/German-Sample-gifi.sql,
+ sql/Germany-DATEV-SKR03-chart.sql,
+ sql/Germany-DATEV-SKR03-gifi.sql, sql/Germany-SKR03-chart.sql,
+ sql/Germany-SKR03-gifi.sql, sql/Hungary-chart.sql,
+ sql/Hungary-gifi.sql, sql/Italy-gifi.sql,
+ sql/Italy_General-chart.sql, sql/Italy_cc2424-chart.sql,
+ sql/Latvia-chart.sql, sql/NAICS.sql,
+ sql/Norwegian_Default-chart.sql, sql/Oracle-indices.sql,
+ sql/Oracle-tables.sql, sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ sql/Oracle-upgrade-2.0.0-2.0.8.sql,
+ sql/Oracle-upgrade-2.0.8-2.2.0.sql, sql/Pg-functions.sql,
+ sql/Pg-indices.sql, sql/Pg-tables.sql,
+ sql/Pg-upgrade-1.2.6-1.2.7.sql, sql/Pg-upgrade-1.2.7-1.4.0.sql,
+ sql/Pg-upgrade-1.4.0-1.6.0.sql, sql/Pg-upgrade-1.6.0-1.8.0.sql,
+ sql/Pg-upgrade-1.8.0-1.8.4.sql, sql/Pg-upgrade-1.8.4-1.8.5.sql,
+ sql/Pg-upgrade-1.8.5-2.0.0.sql, sql/Pg-upgrade-2.0.0-2.0.8.sql,
+ sql/Pg-upgrade-2.0.8-2.2.0.sql, sql/Pg-upgrade-2.2.0-2.3.0.sql,
+ sql/Pg-upgrade-2.3.0-2.3.1.sql, sql/Pg-upgrade-2.3.1-2.3.3.sql,
+ sql/Pg-upgrade-2.3.3-2.3.4.sql, sql/Pg-upgrade-2.3.4-2.3.5.sql,
+ sql/Pg-upgrade-2.3.5-2.3.6.sql, sql/Pg-upgrade-2.3.6-2.3.7.sql,
+ sql/Pg-upgrade-2.3.7-2.3.8.sql, sql/Pg-upgrade-2.3.8-2.3.9.sql,
+ sql/Pg-upgrade-2.3.9-2.4.2.sql, sql/Pg-upgrade-2.4.2-2.4.3.sql,
+ sql/Pg-upgrade-2.4.3-2.4.4.sql, sql/Poland-chart.sql,
+ sql/Simplified-Chinese_Default-UTF8-chart.sql,
+ sql/Simplified-Chinese_Default-chart.sql,
+ sql/Spain-ISO-chart.sql, sql/Spain-UTF8-chart.sql,
+ sql/Swedish-chart.sql, sql/Swiss-German-chart.sql,
+ sql/Swiss-German-gifi.sql,
+ sql/Traditional-Chinese_Default-UTF8-chart.sql,
+ sql/Traditional-Chinese_Default-chart.sql,
+ sql/US_General-chart.sql, sql/US_Manufacturing-chart.sql,
+ sql/US_Service_Company-chart.sql,
+ templates/Brazilian_Portuguese-ap_transaction.html,
+ templates/Brazilian_Portuguese-ap_transaction.tex,
+ templates/Brazilian_Portuguese-ar_transaction.html,
+ templates/Brazilian_Portuguese-ar_transaction.tex,
+ templates/Brazilian_Portuguese-balance_sheet.html,
+ templates/Brazilian_Portuguese-bin_list.html,
+ templates/Brazilian_Portuguese-bin_list.tex,
+ templates/Brazilian_Portuguese-check.tex,
+ templates/Brazilian_Portuguese-income_statement.html,
+ templates/Brazilian_Portuguese-invoice.html,
+ templates/Brazilian_Portuguese-invoice.tex,
+ templates/Brazilian_Portuguese-packing_list.html,
+ templates/Brazilian_Portuguese-packing_list.tex,
+ templates/Brazilian_Portuguese-pick_list.html,
+ templates/Brazilian_Portuguese-pick_list.tex,
+ templates/Brazilian_Portuguese-pos_invoice.txt,
+ templates/Brazilian_Portuguese-purchase_order.html,
+ templates/Brazilian_Portuguese-purchase_order.tex,
+ templates/Brazilian_Portuguese-receipt.tex,
+ templates/Brazilian_Portuguese-request_quotation.html,
+ templates/Brazilian_Portuguese-request_quotation.tex,
+ templates/Brazilian_Portuguese-sales_order.html,
+ templates/Brazilian_Portuguese-sales_order.tex,
+ templates/Brazilian_Portuguese-sales_quotation.html,
+ templates/Brazilian_Portuguese-sales_quotation.tex,
+ templates/Brazilian_Portuguese-statement.html,
+ templates/Brazilian_Portuguese-statement.tex,
+ templates/Brazilian_Portuguese-work_order.html,
+ templates/Brazilian_Portuguese-work_order.tex,
+ templates/Danish-ap_transaction.html,
+ templates/Danish-ap_transaction.tex,
+ templates/Danish-ar_transaction.html,
+ templates/Danish-ar_transaction.tex,
+ templates/Danish-balance_sheet.html,
+ templates/Danish-bin_list.html, templates/Danish-bin_list.tex,
+ templates/Danish-check.tex,
+ templates/Danish-income_statement.html,
+ templates/Danish-invoice.html, templates/Danish-invoice.tex,
+ templates/Danish-packing_list.html,
+ templates/Danish-packing_list.tex,
+ templates/Danish-pick_list.html, templates/Danish-pick_list.tex,
+ templates/Danish-pos_invoice.txt,
+ templates/Danish-purchase_order.html,
+ templates/Danish-purchase_order.tex,
+ templates/Danish-receipt.tex,
+ templates/Danish-request_quotation.html,
+ templates/Danish-request_quotation.tex,
+ templates/Danish-sales_order.html,
+ templates/Danish-sales_order.tex,
+ templates/Danish-sales_quotation.html,
+ templates/Danish-sales_quotation.tex,
+ templates/Danish-statement.html, templates/Danish-statement.tex,
+ templates/Danish-work_order.html,
+ templates/Danish-work_order.tex,
+ templates/Default-ap_transaction.html,
+ templates/Default-ap_transaction.tex,
+ templates/Default-ar_transaction.html,
+ templates/Default-ar_transaction.tex,
+ templates/Default-balance_sheet.html,
+ templates/Default-bin_list.html, templates/Default-bin_list.tex,
+ templates/Default-check.tex,
+ templates/Default-income_statement.html,
+ templates/Default-invoice.html, templates/Default-invoice.tex,
+ templates/Default-packing_list.html,
+ templates/Default-packing_list.tex,
+ templates/Default-pick_list.html,
+ templates/Default-pick_list.tex,
+ templates/Default-pos_invoice.txt,
+ templates/Default-purchase_order.html,
+ templates/Default-purchase_order.tex,
+ templates/Default-receipt.tex,
+ templates/Default-request_quotation.html,
+ templates/Default-request_quotation.tex,
+ templates/Default-sales_order.html,
+ templates/Default-sales_order.tex,
+ templates/Default-sales_quotation.html,
+ templates/Default-sales_quotation.tex,
+ templates/Default-statement.html,
+ templates/Default-statement.tex,
+ templates/Default-work_order.html,
+ templates/Default-work_order.tex,
+ templates/Dutch-ap_transaction.html,
+ templates/Dutch-ap_transaction.tex,
+ templates/Dutch-ar_transaction.html,
+ templates/Dutch-ar_transaction.tex,
+ templates/Dutch-balance_sheet.html,
+ templates/Dutch-bin_list.html, templates/Dutch-bin_list.tex,
+ templates/Dutch-check.tex, templates/Dutch-income_statement.html,
+ templates/Dutch-invoice.html, templates/Dutch-invoice.tex,
+ templates/Dutch-packing_list.html,
+ templates/Dutch-packing_list.tex, templates/Dutch-pick_list.html,
+ templates/Dutch-pick_list.tex, templates/Dutch-pos_invoice.txt,
+ templates/Dutch-purchase_order.html,
+ templates/Dutch-purchase_order.tex, templates/Dutch-receipt.tex,
+ templates/Dutch-request_quotation.html,
+ templates/Dutch-request_quotation.tex,
+ templates/Dutch-sales_order.html,
+ templates/Dutch-sales_order.tex,
+ templates/Dutch-sales_quotation.html,
+ templates/Dutch-sales_quotation.tex,
+ templates/Dutch-statement.html, templates/Dutch-statement.tex,
+ templates/Dutch-work_order.html, templates/Dutch-work_order.tex,
+ templates/Estonian-ap_transaction.html,
+ templates/Estonian-ap_transaction.tex,
+ templates/Estonian-ar_transaction.html,
+ templates/Estonian-ar_transaction.tex,
+ templates/Estonian-balance_sheet.html,
+ templates/Estonian-bin_list.html,
+ templates/Estonian-bin_list.tex, templates/Estonian-check.tex,
+ templates/Estonian-income_statement.html,
+ templates/Estonian-invoice.html, templates/Estonian-invoice.tex,
+ templates/Estonian-packing_list.html,
+ templates/Estonian-packing_list.tex,
+ templates/Estonian-pick_list.html,
+ templates/Estonian-pick_list.tex,
+ templates/Estonian-pos_invoice.txt,
+ templates/Estonian-purchase_order.html,
+ templates/Estonian-purchase_order.tex,
+ templates/Estonian-receipt.tex,
+ templates/Estonian-request_quotation.html,
+ templates/Estonian-request_quotation.tex,
+ templates/Estonian-sales_order.html,
+ templates/Estonian-sales_order.tex,
+ templates/Estonian-statement.html,
+ templates/Estonian-statement.tex,
+ templates/Estonian-work_order.html,
+ templates/Estonian-work_order.tex,
+ templates/French-ap_transaction.html,
+ templates/French-ap_transaction.tex,
+ templates/French-ar_transaction.html,
+ templates/French-ar_transaction.tex,
+ templates/French-balance_sheet.html,
+ templates/French-bin_list.html, templates/French-bin_list.tex,
+ templates/French-check.tex,
+ templates/French-income_statement.html,
+ templates/French-invoice.html, templates/French-invoice.tex,
+ templates/French-packing_list.html,
+ templates/French-packing_list.tex,
+ templates/French-pick_list.html, templates/French-pick_list.tex,
+ templates/French-pos_invoice.txt,
+ templates/French-purchase_order.html,
+ templates/French-purchase_order.tex,
+ templates/French-receipt.tex,
+ templates/French-request_quotation.html,
+ templates/French-request_quotation.tex,
+ templates/French-sales_order.html,
+ templates/French-sales_order.tex,
+ templates/French-sales_quotation.html,
+ templates/French-sales_quotation.tex,
+ templates/French-statement.html, templates/French-statement.tex,
+ templates/French-work_order.html,
+ templates/French-work_order.tex,
+ templates/German-ap_transaction.html,
+ templates/German-ap_transaction.tex,
+ templates/German-ar_transaction.html,
+ templates/German-ar_transaction.tex,
+ templates/German-balance_sheet.html,
+ templates/German-bin_list.html, templates/German-bin_list.tex,
+ templates/German-check.tex,
+ templates/German-income_statement.html,
+ templates/German-invoice.html, templates/German-invoice.tex,
+ templates/German-packing_list.html,
+ templates/German-packing_list.tex,
+ templates/German-pick_list.html, templates/German-pick_list.tex,
+ templates/German-pos_invoice.txt,
+ templates/German-purchase_order.html,
+ templates/German-purchase_order.tex,
+ templates/German-receipt.tex,
+ templates/German-request_quotation.html,
+ templates/German-request_quotation.tex,
+ templates/German-sales_order.html,
+ templates/German-sales_order.tex,
+ templates/German-sales_quotation.html,
+ templates/German-sales_quotation.tex,
+ templates/German-statement.html, templates/German-statement.tex,
+ templates/German-work_order.html,
+ templates/German-work_order.tex,
+ templates/Hungarian-ap_transaction.html,
+ templates/Hungarian-ap_transaction.tex,
+ templates/Hungarian-ar_transaction.html,
+ templates/Hungarian-ar_transaction.tex,
+ templates/Hungarian-balance_sheet.html,
+ templates/Hungarian-bin_list.html,
+ templates/Hungarian-bin_list.tex, templates/Hungarian-check.tex,
+ templates/Hungarian-income_statement.html,
+ templates/Hungarian-invoice.html,
+ templates/Hungarian-invoice.tex,
+ templates/Hungarian-packing_list.html,
+ templates/Hungarian-packing_list.tex,
+ templates/Hungarian-pick_list.html,
+ templates/Hungarian-pick_list.tex,
+ templates/Hungarian-pos_invoice.txt,
+ templates/Hungarian-purchase_order.html,
+ templates/Hungarian-purchase_order.tex,
+ templates/Hungarian-receipt.tex,
+ templates/Hungarian-request_quotation.html,
+ templates/Hungarian-request_quotation.tex,
+ templates/Hungarian-sales_order.html,
+ templates/Hungarian-sales_order.tex,
+ templates/Hungarian-sales_quotation.html,
+ templates/Hungarian-sales_quotation.tex,
+ templates/Hungarian-statement.html,
+ templates/Hungarian-statement.tex,
+ templates/Hungarian-work_order.html,
+ templates/Hungarian-work_order.tex,
+ templates/Italian-ap_transaction.html,
+ templates/Italian-ap_transaction.tex,
+ templates/Italian-ar_transaction.html,
+ templates/Italian-ar_transaction.tex,
+ templates/Italian-balance_sheet.html,
+ templates/Italian-bin_list.html, templates/Italian-bin_list.tex,
+ templates/Italian-check.tex,
+ templates/Italian-income_statement.html,
+ templates/Italian-invoice.html, templates/Italian-invoice.tex,
+ templates/Italian-packing_list.html,
+ templates/Italian-packing_list.tex,
+ templates/Italian-pick_list.html,
+ templates/Italian-pick_list.tex,
+ templates/Italian-pos_invoice.txt,
+ templates/Italian-purchase_order.html,
+ templates/Italian-purchase_order.tex,
+ templates/Italian-receipt.tex,
+ templates/Italian-request_quotation.html,
+ templates/Italian-request_quotation.tex,
+ templates/Italian-sales_order.html,
+ templates/Italian-sales_order.tex,
+ templates/Italian-sales_quotation.html,
+ templates/Italian-sales_quotation.tex,
+ templates/Italian-statement.html,
+ templates/Italian-statement.tex,
+ templates/Italian-work_order.html,
+ templates/Italian-work_order.tex,
+ templates/Norwegian-ap_transaction.html,
+ templates/Norwegian-ap_transaction.tex,
+ templates/Norwegian-ar_transaction.html,
+ templates/Norwegian-ar_transaction.tex,
+ templates/Norwegian-balance_sheet.html,
+ templates/Norwegian-bin_list.html,
+ templates/Norwegian-bin_list.tex, templates/Norwegian-check.tex,
+ templates/Norwegian-income_statement.html,
+ templates/Norwegian-invoice.html,
+ templates/Norwegian-invoice.tex,
+ templates/Norwegian-packing_list.html,
+ templates/Norwegian-packing_list.tex,
+ templates/Norwegian-pick_list.html,
+ templates/Norwegian-pick_list.tex,
+ templates/Norwegian-pos_invoice.txt,
+ templates/Norwegian-purchase_order.html,
+ templates/Norwegian-purchase_order.tex,
+ templates/Norwegian-receipt.tex,
+ templates/Norwegian-request_quotation.html,
+ templates/Norwegian-request_quotation.tex,
+ templates/Norwegian-sales_order.html,
+ templates/Norwegian-sales_order.tex,
+ templates/Norwegian-sales_quotation.html,
+ templates/Norwegian-sales_quotation.tex,
+ templates/Norwegian-statement.html,
+ templates/Norwegian-statement.tex,
+ templates/Norwegian-work_order.html,
+ templates/Norwegian-work_order.tex,
+ templates/Service-ap_transaction.html,
+ templates/Service-ap_transaction.tex,
+ templates/Service-ar_transaction.html,
+ templates/Service-ar_transaction.tex,
+ templates/Service-balance_sheet.html,
+ templates/Service-bin_list.html, templates/Service-bin_list.tex,
+ templates/Service-check.tex,
+ templates/Service-income_statement.html,
+ templates/Service-invoice.html, templates/Service-invoice.tex,
+ templates/Service-packing_list.html,
+ templates/Service-packing_list.tex,
+ templates/Service-pick_list.html,
+ templates/Service-pick_list.tex,
+ templates/Service-pos_invoice.txt,
+ templates/Service-purchase_order.html,
+ templates/Service-purchase_order.tex,
+ templates/Service-receipt.tex,
+ templates/Service-request_quotation.html,
+ templates/Service-request_quotation.tex,
+ templates/Service-sales_order.html,
+ templates/Service-sales_order.tex,
+ templates/Service-sales_quotation.html,
+ templates/Service-sales_quotation.tex,
+ templates/Service-statement.html,
+ templates/Service-statement.tex,
+ templates/Service-work_order.html,
+ templates/Service-work_order.tex,
+ templates/Spanish_A4-ap_transaction.html,
+ templates/Spanish_A4-ap_transaction.tex,
+ templates/Spanish_A4-ar_transaction.html,
+ templates/Spanish_A4-ar_transaction.tex,
+ templates/Spanish_A4-balance_sheet.html,
+ templates/Spanish_A4-bin_list.html,
+ templates/Spanish_A4-bin_list.tex,
+ templates/Spanish_A4-check.tex,
+ templates/Spanish_A4-income_statement.html,
+ templates/Spanish_A4-invoice.html,
+ templates/Spanish_A4-invoice.tex,
+ templates/Spanish_A4-packing_list.html,
+ templates/Spanish_A4-packing_list.tex,
+ templates/Spanish_A4-pick_list.html,
+ templates/Spanish_A4-pick_list.tex,
+ templates/Spanish_A4-pos_invoice.txt,
+ templates/Spanish_A4-purchase_order.html,
+ templates/Spanish_A4-purchase_order.tex,
+ templates/Spanish_A4-receipt.tex,
+ templates/Spanish_A4-request_quotation.html,
+ templates/Spanish_A4-request_quotation.tex,
+ templates/Spanish_A4-sales_order.html,
+ templates/Spanish_A4-sales_order.tex,
+ templates/Spanish_A4-sales_quotation.html,
+ templates/Spanish_A4-sales_quotation.tex,
+ templates/Spanish_A4-statement.html,
+ templates/Spanish_A4-statement.tex,
+ templates/Spanish_A4-work_order.html,
+ templates/Spanish_A4-work_order.tex,
+ templates/Spanish_Letter-ap_transaction.html,
+ templates/Spanish_Letter-ap_transaction.tex,
+ templates/Spanish_Letter-ar_transaction.html,
+ templates/Spanish_Letter-ar_transaction.tex,
+ templates/Spanish_Letter-balance_sheet.html,
+ templates/Spanish_Letter-bin_list.html,
+ templates/Spanish_Letter-bin_list.tex,
+ templates/Spanish_Letter-check.tex,
+ templates/Spanish_Letter-income_statement.html,
+ templates/Spanish_Letter-invoice.html,
+ templates/Spanish_Letter-invoice.tex,
+ templates/Spanish_Letter-packing_list.html,
+ templates/Spanish_Letter-packing_list.tex,
+ templates/Spanish_Letter-pick_list.html,
+ templates/Spanish_Letter-pick_list.tex,
+ templates/Spanish_Letter-pos_invoice.txt,
+ templates/Spanish_Letter-purchase_order.html,
+ templates/Spanish_Letter-purchase_order.tex,
+ templates/Spanish_Letter-receipt.tex,
+ templates/Spanish_Letter-request_quotation.html,
+ templates/Spanish_Letter-request_quotation.tex,
+ templates/Spanish_Letter-sales_order.html,
+ templates/Spanish_Letter-sales_order.tex,
+ templates/Spanish_Letter-sales_quotation.html,
+ templates/Spanish_Letter-sales_quotation.tex,
+ templates/Spanish_Letter-statement.html,
+ templates/Spanish_Letter-statement.tex,
+ templates/Spanish_Letter-work_order.html,
+ templates/Spanish_Letter-work_order.tex, users/sql-ledger.eps,
+ users/sql-ledger.png: there's no reason this should still be
+ hanging aroudn the tree
+
+2007-12-04 12:51 ivan
+
+ * httemplate/: elements/menu.html, elements/select-otaker.html,
+ elements/tr-select-otaker.html, search/report_cust_credit.html,
+ search/report_rt_transaction.html, search/rt_transaction.html,
+ search/elements/search.html: add some time-worked reporting
+
+2007-12-04 10:35 jeff
+
+ * httemplate/search/cust_pkg.cgi: add suspend/cancel reason to
+ advanced package report (#2779)
+
+2007-12-04 10:19 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/Setup.pm, FS/FS/Upgrade.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_main.pm, FS/FS/Conf_compat17.pm, FS/FS/cust_pkg.pm,
+ FS/FS/reason.pm, FS/FS/reason_type.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/ClientAPI/Signup.pm,
+ FS/FS/part_pkg/flat_comission.pm,
+ FS/FS/part_pkg/flat_comission_cust.pm,
+ FS/FS/part_pkg/flat_comission_pkg.pm, FS/bin/freeside-upgrade,
+ httemplate/browse/reason.html,
+ httemplate/browse/reason_type.html,
+ httemplate/edit/cust_credit.cgi, httemplate/edit/reason.html,
+ httemplate/edit/reason_type.html,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/elements/menu.html,
+ httemplate/elements/tr-select-reason.html: change credit reasons
+ from freetext to new reason/reason type system (#2777)
+
+2007-12-02 16:18 ivan
+
+ * htetc/freeside-rt.conf: would help if i got the closing tag right
+
+2007-12-02 16:13 ivan
+
+ * htetc/freeside-rt.conf: this should get the Chart stuff in RT
+ statistic running, i hope
+
+2007-11-30 17:37 ivan
+
+ * FS/FS/part_pkg/prorate.pm: cleanup
+
+2007-11-30 17:34 ivan
+
+ * FS/FS/h_cust_svc.pm: add date_deleted method
+
+2007-11-30 17:34 ivan
+
+ * FS/FS/cust_svc.pm: add date_inserted method and reorganize things
+ slightly
+
+2007-11-30 17:33 ivan
+
+ * FS/FS/h_Common.pm: this doesn't actually have anything to do with
+ cancellation persay, since its generic now
+
+2007-11-30 17:32 ivan
+
+ * FS/FS/Record.pm: add h_date method too
+
+2007-11-30 17:30 ivan
+
+ * FS/FS/Record.pm: add h_search method, and reorganize mixed up
+ methods and subroutines
+
+2007-11-30 17:29 ivan
+
+ * FS/FS/part_pkg/bulk.pm: add bulk price plan
+
+2007-11-30 13:07 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/graph/money_time.cgi,
+ httemplate/search/cust_bill.html: add net vs gross amounts to
+ invoice report; make the "net sales" links on
+ sales/credit/receipts report & graph clickable
+
+2007-11-30 12:55 ivan
+
+ * httemplate/graph/elements/monthly.html: UI: download full results
+ links on separate lines, for consistency with search.html
+
+2007-11-30 10:13 ivan
+
+ * FS/FS/cust_bill.pm: fix bug specifying an HTML return address
+ separately
+
+2007-11-29 19:24 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/cust_main-import.cgi: add
+ customer import format with company
+
+2007-11-29 17:24 ivan
+
+ * httemplate/browse/access_user.html: update inline documentation
+
+2007-11-29 17:16 ivan
+
+ * FS/FS/cust_main.pm: remove unnecessary redefinition of
+ %method2payby, add a quick hack to fake B:OP success and failure
+ for testing purposes
+
+2007-11-29 15:51 ivan
+
+ * httemplate/edit/: REAL_cust_pkg.cgi, process/REAL_cust_pkg.cgi:
+ fix dates going all wacky on errors, when you're asked to confirm
+ a date move into the past
+
+2007-11-28 19:38 ivan
+
+ * FS/FS/cust_pay_pending.pm: double doh, remove cruft checking
+ nonexistent column and fix the statustext check
+
+2007-11-28 19:05 ivan
+
+ * FS/FS/Schema.pm: doh, fix primary key name in new table
+
+2007-11-28 18:54 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pay_pending.pm,
+ FS/t/cust_pay_pending.t, httemplate/misc/payment.cgi,
+ httemplate/misc/process/payment.cgi: even more reliable
+ multiple-payment/double-click/concurrent-payment-form protection
+
+2007-11-28 12:18 jeff
+
+ * httemplate/edit/: part_pkg.cgi, process/part_pkg.cgi: better
+ select multiple, discourage creation of packages no agent can
+ sell
+
+2007-11-28 10:49 jeff
+
+ * FS/FS/ConfDefaults.pm, FS/FS/UI/Web.pm,
+ httemplate/search/cust_main_ADV.cgi,
+ httemplate/search/report_cust_main.html: advanced customer report
+ rearrangement
+
+2007-11-28 00:46 ivan
+
+ * FS/FS/ClientAPI_SessionCache.pm, Makefile: default to FileCache
+ for selfservice session cache
+
+2007-11-27 17:54 ivan
+
+ * httemplate/search/cust_bill_event.cgi: removed unused \$failed
+ var
+
+2007-11-27 17:30 ivan
+
+ * README: license clarification for self-service code
+
+2007-11-27 15:47 ivan
+
+ * httemplate/search/cust_bill.html: fix small side-effect of
+ mysql-compat change eliminating DISTINCT ON: map changing values
+ of @where array
+
+2007-11-27 14:33 jeff
+
+ * FS/FS/part_export/prizm.pm: comma, please
+
+2007-11-27 14:30 jeff
+
+ * FS/FS/part_export/prizm.pm: name management tweaking
+
+2007-11-27 11:34 jeff
+
+ * FS/FS/part_export/prizm.pm: slop correction
+
+2007-11-26 19:02 jeff
+
+ * FS/FS/part_export/prizm.pm: attach SM's to default network,
+ improved unsuspend & delete, option for BAM only or EMS
+
+2007-11-26 18:51 jeff
+
+ * FS/FS/ClientAPI/MyAccount.pm: prevent BILL, DCRD, and DCHK
+ customers from circumventing a suspension via selfservice (2768)
+
+2007-11-25 18:19 ivan
+
+ * httemplate/search/elements/search.html: add a "printable copy"
+ link to searches to get full results as printable HTML without
+ other cruft, closes: #1885
+
+2007-11-25 18:18 ivan
+
+ * httemplate/elements/header-popup.html: add our stylesheet to
+ popup/print headers
+
+2007-11-23 17:26 ivan
+
+ * Makefile: hello brave new world of defaulting to apache2 in 1.9
+
+2007-11-23 12:25 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix stickiness of primary radio
+ buttons on errors, closes: RT#1035
+
+2007-11-21 17:03 ivan
+
+ * httemplate/edit/cust_main.cgi: usability: don't offer 'Select
+ agent' choice if the dropdown already has a value
+
+2007-11-20 09:18 ivan
+
+ * AGPL, GPL: it finally happened
+
+2007-11-18 12:02 ivan
+
+ * httemplate/search/: report_cust_pkg.html, svc_acct.cgi: add
+ "multiplier of monthly" info to "paid time" column in
+ svc_acct-display_paid_time_remaining report
+
+2007-11-14 15:10 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm,
+ httemplate/view/cust_main/tickets.html: add link to resolved
+ tickets too
+
+2007-11-09 11:20 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: add
+ business-onlinepayment-email_customer flag
+
+2007-11-08 19:26 ivan
+
+ * httemplate/search/report_receivables.html: better visual
+ indication of disabled "days" field on IE
+
+2007-11-08 19:12 ivan
+
+ * httemplate/search/: report_receivables.cgi,
+ report_receivables.html: add option for listing customers without
+ a balance (closes: RT#2752) and fix bug in total row (closes:
+ RT#2736)
+
+2007-11-08 16:44 jeff
+
+ * FS/FS/cust_main.pm: correct realtime_bop cvv handling
+
+2007-11-07 20:21 ivan
+
+ * FS/FS/: Conf.pm, ClientAPI/MyAccount.pm: add
+ selfservice-session_timeout config
+
+2007-11-07 18:10 ivan
+
+ * FS/FS/cust_main.pm: prevent warning: "Use of uninitialized value
+ in concatenation (.) or string at
+ /usr/local/share/perl/5.8.8/FS/cust_main.pm line 1668."
+
+2007-11-07 16:59 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ FS/bin/freeside-expiration-alerter, conf/alerter_template,
+ conf/company_address, conf/company_name,
+ conf/impending_recur_template, conf/invoice_latexfooter,
+ conf/invoice_latexnotes, conf/invoice_latexreturnaddress,
+ conf/invoice_latexsmallfooter, conf/invoice_template,
+ conf/invoice_template_statement, conf/welcome_letter: for new
+ installs, centralize some stuff that was spread around different
+ config files.
+
+2007-11-05 17:59 ivan
+
+ * bin/customer-faker: keep our own list of states; remove some
+ states that Data::Faker and Locale::SubCountry disagree on
+
+2007-11-04 21:42 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: doc: amount param
+ to process_payment. just a bit important.
+
+2007-11-04 21:27 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add
+ process_payment_order_pkg method
+
+2007-11-04 10:22 jeff
+
+ * httemplate/search/cust_main_ADV.cgi: comma is a bad delimiter
+ choice according to ut_text()
+
+2007-11-03 10:38 ivan
+
+ * httemplate/elements/menu.html: move menu option for adv. customer
+ reports to second level, same as advanced invoice & package
+ reports
+
+2007-11-02 17:55 jeff
+
+ * httemplate/: elements/menu.html, search/cust_main_ADV.cgi,
+ search/report_cust_main.html: new customer report/flattened
+ package report (ticket 1428)
+
+2007-10-29 05:04 ivan
+
+ * httemplate/search/cust_pkg.cgi: bug ya bug resulting from
+ agent-virtualized packages
+
+2007-10-29 05:03 ivan
+
+ * httemplate/search/report_receivables.cgi: famous last mysql bug
+
+2007-10-29 04:34 ivan
+
+ * httemplate/edit/rate.cgi: yup, mysql-ing me harder
+
+2007-10-29 04:32 ivan
+
+ * httemplate/search/cdr.html: mysql
+
+2007-10-29 04:18 ivan
+
+ * FS/bin/freeside-setup: forgotton freeside-setup bits of mysql
+ locking workaround
+
+2007-10-29 03:31 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/part_event/Condition.pm,
+ FS/FS/part_event/Condition/balance_age.pm,
+ FS/FS/part_event/Condition/cust_bill_age.pm,
+ httemplate/search/cdr.html: mysql me 1.9 more times
+
+2007-10-29 03:30 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/h_Common.pm, httemplate/edit/rate.cgi,
+ httemplate/search/cust_bill.html,
+ httemplate/search/report_tax.cgi: mysql has no DISTINCT ON
+ either, sigh
+
+2007-10-28 18:08 ivan
+
+ * httemplate/view/cust_pay.html: still have link back to the
+ customer on printable receipt... should hide it from print at
+ some point though
+
+2007-10-28 05:51 ivan
+
+ * FS/: FS/Schema.pm, FS/Setup.pm, FS/svc_acct.pm,
+ bin/freeside-upgrade: finish mysql locking workaround
+
+2007-10-27 20:55 ivan
+
+ * FS/FS/Record.pm, FS/FS/cust_svc.pm,
+ FS/FS/part_export/sqlradius.pm, htetc/handler.pl,
+ httemplate/search/report_receivables.cgi: mysql me harder
+
+2007-10-26 21:46 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ httemplate/misc/process/payment.cgi,
+ httemplate/search/cust_pay.cgi, httemplate/view/cust_pay.html,
+ httemplate/view/cust_main/payment_history.html: simple payment
+ receipts in web interface, sorry arnie, RT#2738
+
+2007-10-25 12:01 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm, FS/FS/Schema.pm, Makefile:
+ mysql, yes, mysql.
+
+2007-10-25 01:29 ivan
+
+ * FS/bin/freeside-setup: fix error handling
+
+2007-10-22 15:29 ivan
+
+ * FS/FS/Report/Table/Monthly.pm: fix more fallout from
+ agent-virtualized packages
+
+2007-10-17 09:07 jayce
+
+ * FS/FS/cust_pkg.pm: insert_reason only worked if you passed in an
+ existing reason, the code to insert a new reason was in place,
+ but didn't let the new reason get used. Code to do this was
+ already in place, just not utilized.
+
+2007-10-14 16:14 ivan
+
+ * conf/invoice_html: this aligns better. i wonder how 1.9 loads up
+ config from here, though?
+
+2007-10-14 16:10 ivan
+
+ * FS/FS/cust_bill.pm: escape \dollar in invoice_latexnotes
+
+2007-10-14 13:07 ivan
+
+ * FS/FS/Cron/bill.pm: don't fill up memory with objects for every
+ customer being billed
+
+2007-10-13 18:51 ivan
+
+ * fs_selfservice/php/: freeside.class.php,
+ freeside.login_example.php, freeside_signup_example.php: adding
+ php examples
+
+2007-10-13 10:33 jeff
+
+ * httemplate/edit/: part_pkg.cgi, process/part_pkg.cgi: correct
+ agent_defaultpkg handling
+
+2007-10-10 13:54 ivan
+
+ * FS/FS/cust_main.pm: set expandtab
+
+2007-10-10 13:52 jayce
+
+ * FS/FS/cust_main.pm: With this line missing, cust_event objects
+ would not fully create (eventpart wasn't loading), causing the _X
+ methods to fail on ->part_event. Only noticed when you retried
+ events that had previously failed.
+
+2007-10-10 11:14 ivan
+
+ * httemplate/browse/part_pkg.cgi: REALLY fix the package browsing
+ this time, without messing up the ordering
+
+2007-10-10 10:55 ivan
+
+ * httemplate/edit/part_pkg.cgi: concurrent fix for package editing
+ also cleans this up slightly
+
+2007-10-10 10:50 jeff
+
+ * httemplate/edit/part_pkg.cgi: close:}
+
+2007-10-09 10:57 ivan
+
+ * FS/FS/cust_main.pm: be polite! don't spew debugging info unless
+ its asked for.
+
+2007-10-08 21:58 ivan
+
+ * FS/FS/Conf.pm: fix documenation links to point into wiki where
+ they belong
+
+2007-10-08 21:48 ivan
+
+ * FS/FS/: Conf.pm, TicketSystem/RT_External.pm: add
+ ticket_system-priority_reverse config
+
+2007-10-08 18:40 jeff
+
+ * httemplate/misc/timeworked.html: preserve order
+
+2007-10-08 18:06 ivan
+
+ * httemplate/misc/timeworked.html: interpolating the links would
+ help too
+
+2007-10-08 18:01 ivan
+
+ * httemplate/misc/timeworked.html: i think this should fix
+ timeworked subjects, and link to the transactions as well
+
+2007-10-08 16:48 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/view_support_details.html: line
+ up things better
+
+2007-10-08 16:32 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: self-service POD
+ cleanups
+
+2007-10-08 14:06 ivan
+
+ * FS/FS/part_event/Condition/cust_bill_owed.pm,
+ bin/freeside-migrate-events, httemplate/edit/part_event.html: add
+ cust_bill_owed as an implicit condition (whew), and make sure it
+ is added on migrations (also: fixed implicit conditions like this
+ which only apply to a subset of eventtables)
+
+2007-10-08 14:05 jeff
+
+ * httemplate/edit/part_pkg.cgi: disallow agent changing on cloned
+ packages
+
+2007-10-08 12:14 jeff
+
+ * htetc/handler.pl, httemplate/edit/rate_region.cgi,
+ httemplate/edit/reg_code.cgi,
+ httemplate/edit/process/cust_svc.cgi,
+ httemplate/edit/process/domain_record.cgi,
+ httemplate/edit/process/reg_code.cgi,
+ httemplate/elements/errorpage.html,
+ httemplate/elements/tr-select-part_referral.html,
+ httemplate/misc/bill.cgi, httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/delete-agent_payment_gateway.cgi,
+ httemplate/misc/delete-cust_credit.cgi,
+ httemplate/misc/delete-cust_pay.cgi,
+ httemplate/misc/delete-cust_refund.cgi,
+ httemplate/misc/delete-domain_record.cgi,
+ httemplate/misc/delete-part_export.cgi, httemplate/misc/dump.cgi,
+ httemplate/misc/inventory_item-import.html,
+ httemplate/misc/unapply-cust_credit.cgi,
+ httemplate/misc/unapply-cust_pay.cgi,
+ httemplate/misc/unprovision.cgi, httemplate/misc/unsusp_pkg.cgi,
+ httemplate/misc/unvoid-cust_pay_void.cgi,
+ httemplate/misc/upload-batch.cgi,
+ httemplate/misc/void-cust_pay.cgi,
+ httemplate/misc/process/cdr-import.html,
+ httemplate/misc/process/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import_charges.cgi,
+ httemplate/misc/process/inventory_item-import.html,
+ httemplate/misc/process/link.cgi,
+ httemplate/misc/process/payment.cgi,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_svc.html,
+ httemplate/search/inventory_item.html,
+ httemplate/search/reg_code.html, httemplate/search/sql.html,
+ httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_broadband.cgi: Remove remaining calls to
+ idiot/eidiot. Should fix 1479
+
+2007-10-05 13:41 ivan
+
+ * FS/FS/part_event/Condition/cust_bill_has_service.pm: reenalbe
+ this condition
+
+2007-10-05 12:53 jeff
+
+ * httemplate/misc/: timeworked.html, process/timeworked.html: new
+ ui for assigning support time
+
+2007-10-05 12:45 ivan
+
+ * httemplate/elements/tr-input-beginning_ending.html: fix date
+ selection on advanced invoice report, or future places where date
+ selection component is included multiple times
+
+2007-10-05 07:26 jayce
+
+ * httemplate/elements/tr-select-part_svc.html: Initial checkin, was
+ missing from the cust_bill_has_service condition checkin.
+
+2007-10-04 17:39 ivan
+
+ * FS/FS/: part_event_condition.pm, part_event/Condition.pm,
+ part_event/Condition/cust_bill_has_service.pm: add disable
+ ability to conditions & disable cust_bill_has_service, so the
+ condition edit page renders again
+
+2007-10-04 16:55 ivan
+
+ * FS/FS/part_event/Condition/once.pm: whitespace
+
+2007-10-04 16:52 ivan
+
+ * FS/FS/part_event/Condition/once.pm: such a dumb little thing, but
+ i think that should really do it. whew
+
+2007-10-04 16:41 ivan
+
+ * FS/FS/cust_main.pm: don't leave stray 'new' events around if they
+ don't pass their final condition check
+
+2007-10-04 16:40 ivan
+
+ * FS/FS/part_event/Condition/once.pm: hopefully fix once.pm
+ properly...
+
+2007-10-04 14:38 ivan
+
+ * FS/FS/part_event_condition.pm: add SKIP_CONDITION_SQL debugging
+ aid
+
+2007-10-04 12:14 ivan
+
+ * FS/FS/Cron/bill.pm: additional due_cust_event debugging
+
+2007-10-04 12:04 ivan
+
+ * FS/FS/cust_main.pm: nobody likes it when you forget ions
+
+2007-10-04 12:03 ivan
+
+ * FS/FS/cust_main.pm: additional due_cust_event debugging
+
+2007-10-04 11:28 ivan
+
+ * FS/FS/cust_main.pm: additional due_cust_event debugging
+
+2007-10-04 09:45 ivan
+
+ * httemplate/search/cust_bill_event.cgi: fix compilation error!
+
+2007-10-03 21:21 ivan
+
+ * FS/FS/cust_main.pm: i really hope this finally does it
+
+2007-10-03 21:09 ivan
+
+ * FS/FS/cust_main.pm: dot strikes again
+
+2007-10-03 21:08 ivan
+
+ * FS/FS/cust_main.pm: whew, i think this might actually fix it
+
+2007-10-03 20:48 ivan
+
+ * FS/FS/cust_main.pm: doh! does that really fix agent-specific
+ agent template migration from 1.7? sure hope so
+
+2007-10-03 20:37 ivan
+
+ * FS/FS/Record.pm: add debugging option to qsearch
+
+2007-10-03 19:52 ivan
+
+ * bin/pod2x: wikify individual files
+
+2007-10-03 19:22 ivan
+
+ * bin/pod2x: fix FS::SelfService::XMLRPC pod generation
+
+2007-10-03 19:15 ivan
+
+ * FS/FS/cust_main.pm: add missing =back
+
+2007-10-03 19:07 ivan
+
+ * bin/pod2x: bah! THIS should fix munging of non-internal links, i
+ hope
+
+2007-10-03 19:06 jeff
+
+ * FS/FS/UI/bytecount.pm, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/prorate.pm, FS/FS/part_pkg/subscription.pm,
+ httemplate/edit/process/part_pkg.cgi: support part_pkg option
+ input validation, check bytecounts and allow commas (closes 1863)
+
+2007-10-03 18:56 ivan
+
+ * bin/pod2x: this *should* fix munging of non-internal links, i
+ hope
+
+2007-10-03 18:49 ivan
+
+ * Makefile, bin/pod2x: wiki documentation convertor now
+
+2007-10-03 18:47 ivan
+
+ * FS/FS.pm: add missing CLI utilities to FS.pm too
+
+2007-10-03 18:45 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: fixing wrong POD NAME doc
+
+2007-10-03 18:29 ivan
+
+ * FS/t/cust_tax_exempt.pm: wtf!
+
+2007-10-03 18:21 ivan
+
+ * FS/FS.pm: update FS base page for new stuff in 1.9
+
+2007-10-03 18:15 ivan
+
+ * FS/: FS.pm: update top-level FS manpage
+
+2007-10-03 17:51 ivan
+
+ * FS/FS/: access_right.pm, access_user_pref.pm,
+ access_usergroup.pm, pay_batch.pm: POD documentation updates
+
+2007-10-02 14:56 ivan
+
+ * FS/FS/cust_event.pm: doh!
+
+2007-10-02 08:31 jeff
+
+ * FS/FS/cust_bill_event.pm, FS/FS/UI/Web.pm,
+ httemplate/search/cust_bill_event.cgi: fix up re-email these
+ events
+
+2007-10-02 08:11 jeff
+
+ * httemplate/misc/process/timeworked.html: missed file in self
+ service support usage improvements
+
+2007-10-01 17:44 ivan
+
+ * httemplate/: browse/part_referral.html, elements/menu.html:
+ Configuration right no longer gives access to things controlled
+ by their own ACLs (advertising source & package edit
+
+2007-10-01 17:40 ivan
+
+ * httemplate/elements/menu.html: package definitions controlled by
+ their own ACL now
+
+2007-10-01 17:32 ivan
+
+ * FS/bin/freeside-daily: need the space
+
+2007-10-01 17:31 ivan
+
+ * FS/FS/Schema.pm: this flag has nothing to do with recur tax :)
+
+2007-10-01 17:29 ivan
+
+ * FS/FS/Cron/bill.pm: fix small problems with earlier commit: add
+ back earlier commits reverted by this patch, also revert
+ gratuitous whitespace changes
+
+2007-10-01 17:22 ivan
+
+ * FS/FS/cust_event.pm: proper fix for once.pm bug? hopefully it
+ works :)
+
+2007-10-01 17:18 ivan
+
+ * FS/FS/part_event/: Condition.pm, Condition/once.pm: proper fix
+ for once.pm bug? hopefully it works :)
+
+2007-09-29 17:26 ivan
+
+ * httemplate/search/: cdr.html, report_cdr.html: better CDR
+ searching
+
+2007-09-29 17:25 ivan
+
+ * httemplate/edit/REAL_cust_pkg.cgi: fix argument stickiness on
+ date editing errors (especially because resetting them pops up
+ the error confirmation)
+
+2007-09-29 17:23 ivan
+
+ * FS/FS/cust_main.pm: this might fix agent-specific invoicing when
+ migrated from 1.7?
+
+2007-09-29 17:22 ivan
+
+ * bin/freeside-upgrade-unicode: [no log message]
+
+2007-09-28 19:17 ivan
+
+ * FS/FS/access_user.pm, httemplate/search/cust_event.html,
+ httemplate/search/report_tax.cgi: fix ambiguous agentnum errors
+ in cust_event.html & report_tax.cgi (provide a table option in
+ access_user::agentnums_sql so this is easy to fix for other
+ reports too)
+
+2007-09-27 17:33 jayce
+
+ * FS/FS/cust_main.pm: Fixes a bug where retry_realtime isn't
+ limiting to that user's events, therefore selecting all retryable
+ events, and having to filter later. On a system with a running
+ history, this caused bad O() types of situations for performance,
+ especially bad when this was called by something that a user
+ would be awaiting feedback from
+
+2007-09-27 17:19 jayce
+
+ * FS/FS/Record.pm: Cleanup qsearch for readability, removes heinous
+ map {} of several hundred lines into two simple method calls
+
+2007-09-27 14:25 jeff
+
+ * httemplate/edit/svc_acct.cgi: hide fixed passwords
+
+2007-09-27 11:24 jayce
+
+ * FS/: FS/Schema.pm, FS/cust_main.pm, FS/Cron/bill.pm,
+ bin/freeside-daily: Multi-System Billing: with a -m flag, daily
+ will queue billing jobs instead of running each. freeside-queued
+ will then pick it up, allowing multiple simultaneous jobs to run,
+ as well as multiple machines. Also adds a 'Secure' column to the
+ queue system, allowing for billing jobs to define themselves as
+ 'secure only' in cases where a box might be using the encryption.
+ This allows you to run secure only jobs (such as a collect) on
+ boxes that can.
+
+2007-09-26 12:27 jayce
+
+ * FS/FS/part_event/Condition/cust_bill_has_service.pm: Initial
+ import. Condition tests to see if the Invoice bills for a
+ particular service.
+
+2007-09-26 12:24 jayce
+
+ * FS/FS/part_event/Condition/once.pm: Event loop changes after
+ initial creation caused this to never trigger, as the event loop
+ creates a 'NEW' record, as a placeholder. We need to not die
+ from that.
+
+2007-09-26 09:06 ivan
+
+ * httemplate/browse/part_pkg.cgi: fix package browse query, doh
+
+2007-09-24 08:47 jeff
+
+ * FS/FS/Schema.pm, FS/FS/acct_rt_transaction.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/TicketSystem/RT_External.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_support_details.html:
+ self-service support usage improvements (1733)
+
+2007-09-23 17:56 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/Schema.pm, FS/FS/part_event.pm,
+ FS/FS/part_pkg.pm, httemplate/browse/part_pkg.cgi: beginning of
+ agent-virtualization of packages
+
+2007-09-23 16:17 ivan
+
+ * httemplate/edit/svc_www.cgi: i think this is a bug; should not
+ show the svc_www.usersvc selector unless it is non-fixed or
+ non-blank, NOT non-fixed or blank
+
+2007-09-23 16:16 ivan
+
+ * FS/FS/Record.pm: remove compat with pre-0.33 DBIx::DBSchema
+
+2007-09-23 13:21 ivan
+
+ * FS/FS/Conf.pm, httemplate/search/svc_acct.cgi: accounts w/time
+ remaining search
+
+2007-09-23 13:00 ivan
+
+ * httemplate/search/svc_acct.cgi: accounts w/time remaining search
+
+2007-09-23 12:54 ivan
+
+ * httemplate/search/svc_acct.cgi: accounts w/time remaining search
+
+2007-09-23 12:18 ivan
+
+ * httemplate/search/elements/search.html: remove extraneous blank
+ line causing Excel exports to fail
+
+2007-09-23 11:32 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/elements/menu.html,
+ httemplate/search/svc_acct.cgi: accounts w/time remaining search
+
+2007-09-22 15:45 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/myaccount_menu.html: fix
+ menubar border in example self-service template
+
+2007-09-22 14:31 ivan
+
+ * httemplate/config/: config-view.cgi, config.cgi: improve config
+ UI, especially for textareas
+
+2007-09-22 12:40 ivan
+
+ * httemplate/view/svc_acct.cgi: UI
+
+2007-09-22 12:03 ivan
+
+ * FS/FS/svc_domain.pm: have to import tld_exists function if we're
+ going to use it
+
+2007-09-22 11:27 ivan
+
+ * httemplate/view/svc_acct.cgi: add a list of any hosts associated
+ with accounts
+
+2007-09-20 19:24 ivan
+
+ * httemplate/search/timeworked.html: fix problems with time queue
+ search: ticket subjects need to be HTML-escaped, 'remaining time'
+ calculation had a NULL vs 0 issue, and link to tickets
+
+2007-09-19 15:38 ivan
+
+ * rt/lib/RT/SearchBuilder.pm: we need SearchBuilder 1.48 to avoid
+ annoying Pg bugs causing "This user's 10 highest priority
+ tickets" to be blank
+
+2007-09-18 17:27 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/myaccount.html: support custom
+ priorities
+
+2007-09-18 17:12 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/search/cust_bill.html: fix at
+ least one small problem with reprint/email/fax functionality: now
+ should understand the "most recent invoice per customer" and
+ invoice # min/max options
+
+2007-09-18 16:19 ivan
+
+ * httemplate/edit/cust_main.cgi: fix advertising source stickiness
+ when page is reloaded with an error
+
+2007-09-18 15:51 ivan
+
+ * rt/etc/RT_SiteConfig.pm: MyTicketsLength has been replaced with
+ an official upstream config
+
+2007-09-18 14:41 ivan
+
+ * httemplate/search/svc_broadband.cgi: and parens help alot, doh
+
+2007-09-18 14:37 ivan
+
+ * httemplate/search/svc_broadband.cgi: fix svc_broadband search by
+ svcpart (links from browse/part_svc, in particular
+
+2007-09-18 10:07 ivan
+
+ * FS/FS/Schema.pm: add missing column access_user_pref.expiration
+
+2007-09-17 23:32 jeff
+
+ * FS/FS/: cust_pkg.pm, part_pkg/base_rate.pm, part_pkg/flat.pm,
+ part_pkg/prorate.pm, part_pkg/subscription.pm: allow assignment
+ of auto recharge values AND rollover
+
+2007-09-17 23:07 jeff
+
+ * FS/FS/Cron/expire_user_pref.pm: auto commit for vacuum
+
+2007-09-17 17:21 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/myaccount.html: close table
+ tag; fix spacing
+
+2007-09-17 14:12 ivan
+
+ * FS/FS/cust_main.pm: fix scoping issues with $1 and $2 resulting
+ in payinfo trying getting set to xxEK, thanks to _vlad_ for
+ tracking this down and providing a fix
+
+2007-09-17 13:52 ivan
+
+ * FS/FS/Conf.pm: elaborate on ambiguous instructions
+
+2007-09-13 20:45 ivan
+
+ * httemplate/edit/process/quick-charge.cgi: Fix 'Can't use an
+ undefined value as an ARRAY reference at
+ /usr/local/share/perl/5.8.8/FS/cust_main.pm line 4383.' error
+
+2007-09-13 20:31 ivan
+
+ * rt/html/Elements/TicketList: fix visual glitch on "RT at a
+ glance" / Ticketing main
+
+2007-09-13 19:14 ivan
+
+ * rt/html/Ticket/Elements/ShowTransactionAttachments: turn off
+ Text::Quoted usage, it segfaults and its optional
+
+2007-09-13 16:45 ivan
+
+ * rt/html/NoAuth/css/3.5-default/freeside.css: make boxes distinct
+ from the background
+
+2007-09-13 15:35 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/acct_rt_transaction.pm,
+ FS/FS/svc_acct_rt_transaction.pm, FS/t/acct_rt_transaction.t,
+ FS/t/svc_acct_rt_transaction.t, htetc/handler.pl,
+ httemplate/misc/process/timeworked.html,
+ httemplate/search/timeworked.html: rename svc_acct_rt_transaction
+ to acct_rt_transaction, as it is not a service, its something
+ that hangs off of an svc_acct (like an acct_snarf). thank
+ goodness was able to do this before its any sort of migration
+ problem...
+
+2007-09-13 15:25 ivan
+
+ * httemplate/browse/part_svc.cgi: random indentation fix
+
+2007-09-13 15:25 ivan
+
+ * FS/bin/freeside-upgrade: some notes about old part_svc columns,
+ since DBIx::DBSchema 0.33+ will now drop them...
+
+2007-09-13 15:24 ivan
+
+ * CREDITS: too little, too late attempt at spam reduction
+
+2007-09-13 15:05 ivan
+
+ * httemplate/search/cust_main.cgi: fix status color on customer
+ list
+
+2007-09-13 15:05 ivan
+
+ * httemplate/search/report_receivables.cgi: clean up some unused
+ code
+
+2007-09-13 13:16 ivan
+
+ * httemplate/misc/cust_main-import.cgi: add better inline docs
+ explaining fields on customer CSV import
+
+2007-09-12 19:44 ivan
+
+ * rt/html/NoAuth/css/3.5-default/freeside.css: it would help to
+ check this in.
+
+2007-09-12 13:40 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: don't want a fatal error when
+ we can't fetch the name for a queue...
+
+2007-09-11 22:38 ivan
+
+ * bin/freeside-migrate-events: freeside-migrate-events now moves
+ event options, whew
+
+2007-09-11 21:23 ivan
+
+ * FS/FS/cust_event.pm: fix problems migrating weird statustext from
+ cust_bill_event records
+
+2007-09-11 21:23 ivan
+
+ * FS/FS/cust_bill_event.pm: prevent (less than) and (greater than)
+ in statustext message (or anything else weird) from causing them
+ not to get inserted
+
+2007-09-11 21:20 ivan
+
+ * bin/freeside-migrate-events: fix for freeside-migrate-events bug
+ that would throw a duplicate row error instead of completing the
+ migration
+
+2007-09-11 20:39 ivan
+
+ * FS/FS/svc_domain.pm: fix "Useless use of a variable in void
+ context at /usr/local/share/perl/5.8.8/FS/svc_domain.pm line
+ 367." that might have possible set an incorrest svc_domain.suffix
+
+2007-09-10 18:33 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: add cust_main-require_phone and
+ cust_main-require_invoicing_list_email options
+
+2007-09-10 17:28 ivan
+
+ * FS/FS/cust_main.pm: better default paydate for letters
+
+2007-09-06 20:45 ivan
+
+ * FS/FS/cust_pkg.pm: default cancellation subject so the emails
+ work even when people don't set one in config
+
+2007-09-06 20:36 ivan
+
+ * FS/FS/part_export/sqlradius.pm: tweak debugging
+
+2007-08-23 01:23 ivan
+
+ * FS/FS/: Conf.pm, part_export/sqlradius.pm: fix bug where user
+ could log in to RADIUS with uppercase usernameand avoid bandwidth
+ acconting (mysql is case-insensitive? wtf! thanks a fucking lot
+ for nothing, grr!)
+
+2007-08-17 07:01 jeff
+
+ * FS/FS/cust_main.pm: miss use
+
+2007-08-17 06:59 jeff
+
+ * httemplate/misc/process/timeworked.html: access control
+
+2007-08-16 21:27 ivan
+
+ * Makefile: remove redunant redundancy
+
+2007-08-16 11:22 jeff
+
+ * FS/FS/svc_acct.pm: correct labels in service definition edit for
+ svc_acct (#1745)
+
+2007-08-16 10:40 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: remove debugging
+
+2007-08-16 09:19 jeff
+
+ * FS/bin/freeside-upgrade: agent_custid bugfix (1746)
+
+2007-08-16 06:40 jeff
+
+ * FS/FS/svc_acct_rt_transaction.pm, FS/FS/AccessRight.pm,
+ FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/t/svc_acct_rt_transaction.t,
+ httemplate/misc/batch-cust_pay.html,
+ httemplate/misc/timeworked.html,
+ httemplate/misc/elements/customer-table.html, FS/MANIFEST,
+ httemplate/misc/process/timeworked.html,
+ httemplate/search/timeworked.html, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ htetc/handler.pl, httemplate/elements/menu.html,
+ httemplate/view/cust_main/tickets.html: support hours 'usage'
+ tracking for our own internal use (#1733)
+
+2007-08-15 17:09 ivan
+
+ * FS/FS/cust_main.pm: have generate_letter assume a default paydate
+ of 2037-12 so it doesn't bomb out on empty paydates
+
+2007-08-15 16:46 ivan
+
+ * FS/bin/freeside-sqlradius-reset: add -n option to
+ freeside-sqlradius-reset to supress deleting data
+
+2007-08-15 14:51 ivan
+
+ * httemplate/edit/cust_main.cgi: fix customer status color here too
+
+2007-08-14 20:26 ivan
+
+ * httemplate/browse/part_export.cgi: little more low-hanging fruit:
+ table-grid the export listing
+
+2007-08-14 14:46 ivan
+
+ * FS/FS/Report/Table/Monthly.pm, httemplate/elements/menu.html,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/cust_pkg.cgi, httemplate/graph/money_time.cgi,
+ httemplate/graph/report_cust_pkg.html,
+ httemplate/graph/elements/monthly.html,
+ httemplate/browse/agent.cgi: add package churn report/graph
+
+2007-08-14 13:18 ivan
+
+ * FS/FS/Cron/bill.pm: removing unneeded %saw var
+
+2007-08-13 19:40 ivan
+
+ * httemplate/elements/tr-select-cust_pkg-status.html: restore label
+ on package status selector
+
+2007-08-10 16:50 ivan
+
+ * bin/dbdef-create, FS/bin/freeside-dbdef-create: rename
+ dbdef-create to freeside-dbdef-create and move it to FS/bin, so
+ it gets %%%FREESIDE_CONF%%% substituted
+
+2007-08-10 15:48 ivan
+
+ * FS/FS/part_pkg.pm: add 3 day, 4 month and 4.5 month (137 day)
+ frequencies
+
+2007-08-10 00:01 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_pkg.pm,
+ httemplate/view/cust_main/packages.html: on changing packages,
+ don't set setup date unless old package has one
+
+2007-08-08 17:31 ivan
+
+ * FS/FS/svc_domain.pm: add TLD checking to svc_domain
+
+2007-08-08 12:18 ivan
+
+ * FS/FS/cust_pkg.pm: fix otaker regex
+
+2007-08-07 13:05 ivan
+
+ * FS/FS/cust_main.pm: more informative error msg
+
+2007-08-06 12:45 jeff
+
+ * fs_selfservice/FS-SelfService/SelfService/XMLRPC.pm:
+ documentation improvements
+
+2007-08-06 01:51 jeff
+
+ * fs_selfservice/FS-SelfService/MANIFEST: there is a server
+
+2007-08-06 01:46 jeff
+
+ * fs_selfservice/FS-SelfService/: MANIFEST, Makefile.PL,
+ freeside-selfservice-xmlrpc-server, SelfService/XMLRPC.pm,
+ cgi/xmlrpc.cgi: add selfservice xmlrpc facilities (#591)
+
+2007-08-05 10:32 jeff
+
+ * FS/FS/ClientAPI/MyAccount.pm: eeb! fix realtime recharge
+
+2007-08-03 19:06 ivan
+
+ * rt/etc/RT_SiteConfig.pm: fix URL handling on RT redirects
+
+2007-08-03 18:58 ivan
+
+ * Makefile: update Makefile to always substitute in
+ RT_SiteConfig.pm when running install-rt
+
+2007-08-03 18:57 ivan
+
+ * rt/html/Elements/Header, httemplate/elements/header.html: point
+ 1.9 to 1.9 documentation
+
+2007-08-03 17:13 ivan
+
+ * rt/: FREESIDE_MODIFIED, Makefile, config.log, config.status,
+ bin/mason_handler.fcgi, bin/mason_handler.scgi,
+ bin/mason_handler.svc, bin/rt-crontool, bin/rt-mailgate,
+ html/Elements/Footer, html/Elements/Header,
+ html/Elements/PageLayout, html/NoAuth/css/3.5-default/main.css,
+ html/NoAuth/css/3.5-default/misc.css,
+ html/NoAuth/css/3.5-default/transactions.css,
+ html/NoAuth/images/css/cb.gif, html/NoAuth/images/css/cbr.gif,
+ html/NoAuth/images/css/ct.gif, html/NoAuth/images/css/ctr.gif,
+ lib/RT.pm: clean up corners & colors
+
+2007-08-03 16:14 ivan
+
+ * rt/html/Elements/PageLayout: fix nit sorting out tops earchboxes
+
+2007-08-03 16:00 ivan
+
+ * rt/html/Elements/PageLayout: at least sort out the top
+ searchboxes
+
+2007-08-03 15:43 ivan
+
+ * rt/etc/: RT_Config.pm, RT_Config.pm.in: fix path so we can find
+ .css files
+
+2007-08-03 15:10 ivan
+
+ * rt/html/Ticket/Elements/ShowSummary: fix merge nit
+
+2007-08-03 15:06 ivan
+
+ * rt/FREESIDE_MODIFIED: [no log message]
+
+2007-08-03 14:49 ivan
+
+ * rt/: FREESIDE_MODIFIED, etc/RT_SiteConfig.pm,
+ html/Elements/Footer, html/Elements/Header, html/Elements/Menu,
+ html/Elements/PageLayout, html/Elements/QuickCreate,
+ html/Elements/SimpleSearch, html/Elements/Tabs,
+ html/Elements/TicketList, html/Elements/TitleBoxStart,
+ html/Elements/CollectionAsTable/Row, html/NoAuth/printrt.css,
+ html/NoAuth/webrt.css, html/NoAuth/images/space.gif,
+ html/Search/Bulk.html, html/Ticket/Elements/ShowMemberOf,
+ html/Ticket/Elements/ShowReferences,
+ html/Ticket/Elements/ShowSummary, html/Ticket/Elements/Tabs,
+ html/Widgets/TitleBoxStart, lib/RT/SearchBuilder.pm,
+ sbin/rt-setup-database.in: merging RT_3_6_4 to HEAD
+
+2007-08-02 16:44 ivan
+
+ * httemplate/view/cust_main/packages.html: increase package popup
+ width
+
+2007-08-02 16:09 ivan
+
+ * httemplate/: edit/process/cust_pkg.cgi,
+ elements/select-table.html, misc/change_pkg.cgi,
+ misc/order_pkg.html, view/cust_main/packages.html: fix slowness
+ on change package and also make it into a popup
+
+2007-08-02 16:01 ivan
+
+ * httemplate/elements/select-cust-part_pkg.html: fix slowness on
+ change package and also make it into a popup
+
+2007-08-02 15:55 ivan
+
+ * FS/FS/CGI.pm: fix status color on small_custview
+
+2007-08-02 14:57 ivan
+
+ * httemplate/view/cust_main/packages.html: line up package acitons
+ all on one line
+
+2007-08-02 12:54 ivan
+
+ * rt/: lib/RT/I18N/tr.po, lib/RT/Report/Tickets.pm,
+ lib/RT/Report/Tickets/Entry.pm,
+ lib/t/data/subject-with-folding-ws, lib/t/data/lorem-ipsum,
+ lib/t/data/very-long-subject,
+ lib/t/regression/06-mime_decoding.t,
+ lib/t/regression/15cf_pattern.t,
+ lib/t/regression/23-batch-upload-csv.t,
+ lib/t/regression/25scrip_order.t, lib/t/regression/27verp.t,
+ lib/t/regression/17custom_search.t,
+ lib/t/regression/19quicksearch.t, lib/t/regression/23cfsort.t,
+ lib/t/regression/00-mason-syntax.t,
+ lib/t/regression/26command_line.t,
+ lib/t/regression/15cf_combo_cascade.t,
+ lib/t/regression/18custom_frontpage.t,
+ lib/t/regression/24pawsort.t,
+ lib/t/regression/20-sort-by-requestor.t,
+ lib/t/regression/23-web_attachments.t,
+ docs/design_docs/ruleset-workflow.txt,
+ html/Elements/SelectTimeUnits, html/Elements/RefreshHomepage,
+ html/Elements/MyAdminQueues, html/Elements/MyRT,
+ html/Elements/MyReminders, html/Elements/MySupportQueues,
+ html/Elements/QueueSummary, html/Elements/ShowSearch,
+ html/Elements/ValidateCustomFields, html/Elements/Logo,
+ html/Elements/EditCustomFieldCombobox, html/Prefs/MyRT.html,
+ html/Prefs/Quicksearch.html, html/Prefs/Search.html,
+ html/Prefs/SearchOptions.html, html/Prefs/Elements/Tabs,
+ html/Search/Chart.html, html/Search/Simple.html,
+ html/Search/Chart, html/Search/Elements/SelectGroupBy,
+ html/Search/Elements/Chart,
+ html/Search/Elements/SearchesForObject,
+ html/Search/Elements/SelectChartType,
+ html/REST/1.0/Forms/ticket/merge,
+ html/REST/1.0/Forms/ticket/comment,
+ html/REST/1.0/Forms/ticket/take,
+ html/REST/1.0/Forms/transaction/default,
+ html/NoAuth/css/autohandler, html/NoAuth/css/print.css,
+ html/NoAuth/css/3.4-compat/footer.css,
+ html/NoAuth/css/3.4-compat/header.css,
+ html/NoAuth/css/3.4-compat/login.css,
+ html/NoAuth/css/3.4-compat/nav.css,
+ html/NoAuth/css/3.4-compat/ticket.css,
+ html/NoAuth/css/3.4-compat/transactions.css,
+ html/NoAuth/css/3.4-compat/body.css,
+ html/NoAuth/css/3.4-compat/forms.css,
+ html/NoAuth/css/3.4-compat/main.css,
+ html/NoAuth/css/3.4-compat/misc.css,
+ html/NoAuth/css/3.4-compat/quickbar.css,
+ html/NoAuth/css/3.4-compat/titlebox.css,
+ html/NoAuth/css/3.5-default/footer.css,
+ html/NoAuth/css/3.5-default/login.css,
+ html/NoAuth/css/3.5-default/nav.css,
+ html/NoAuth/css/3.5-default/ticket.css,
+ html/NoAuth/css/3.5-default/approvals.css,
+ html/NoAuth/css/3.5-default/body.css,
+ html/NoAuth/css/3.5-default/forms.css,
+ html/NoAuth/css/3.5-default/header.css,
+ html/NoAuth/css/3.5-default/logo.css,
+ html/NoAuth/css/3.5-default/main.css,
+ html/NoAuth/css/3.5-default/misc.css,
+ html/NoAuth/css/3.5-default/quickbar.css,
+ html/NoAuth/css/3.5-default/titlebox.css,
+ html/NoAuth/css/3.5-default/transactions.css,
+ html/NoAuth/images/css/cb-light.gif,
+ html/NoAuth/images/css/cb.gif,
+ html/NoAuth/images/css/cbr-b2g.gif,
+ html/NoAuth/images/css/cbr-b2lb.gif,
+ html/NoAuth/images/css/cbr-gray.gif,
+ html/NoAuth/images/css/cbr-trans.gif,
+ html/NoAuth/images/css/cbr.gif,
+ html/NoAuth/images/css/ct-light.gif,
+ html/NoAuth/images/css/ct.gif,
+ html/NoAuth/images/css/ctr-b2g.gif,
+ html/NoAuth/images/css/ctr-b2lb.gif,
+ html/NoAuth/images/css/ctr-gray.gif,
+ html/NoAuth/images/css/ctr-trans.gif,
+ html/NoAuth/images/css/ctr.gif,
+ html/NoAuth/images/css/dark-arrow-up.png,
+ html/NoAuth/images/css/dark-arrow.png,
+ html/NoAuth/images/css/light-arrow-up.png,
+ html/NoAuth/images/css/light-arrow.png,
+ html/NoAuth/images/css/rolldown-arrow.gif,
+ html/NoAuth/images/css/rolldown-arrow.png,
+ html/NoAuth/images/css/rollup-arrow.gif,
+ html/NoAuth/js/cascaded.js, html/NoAuth/js/util.js,
+ html/NoAuth/js/autohandler, html/NoAuth/js/combobox.js,
+ html/NoAuth/js/list.js, html/NoAuth/js/ahah.js,
+ html/NoAuth/js/class.js, html/NoAuth/js/titlebox-state.js,
+ html/Widgets/ComboBox, html/Widgets/SavedSearch,
+ html/Widgets/SelectionBox, html/Widgets/TitleBox,
+ html/Widgets/TitleBoxEnd, html/Widgets/TitleBoxStart,
+ html/Helpers/CalPopup.html, html/Tools/index.html,
+ html/Tools/Reports/CreatedByDates.html,
+ html/Tools/Reports/ResolvedByDates.html,
+ html/Tools/Reports/ResolvedByOwner.html,
+ html/Tools/Reports/index.html, html/Tools/Reports/Elements/Tabs,
+ html/Admin/Elements/ConfigureMyRT, html/Admin/Global/MyRT.html,
+ html/Admin/Users/MyRT.html, html/Ticket/Reminders.html,
+ html/Ticket/Elements/ShowTime, html/Ticket/Elements/Reminders,
+ etc/upgrade/3.5.1/content: Initial revision
+
+2007-08-02 12:51 ivan
+
+ * rt/lib/RT/: Reminders.pm, Interface/Web/Menu.pm,
+ Interface/Web/Menu/Item.pm, Search/Googleish.pm, I18N/sv.po:
+ Initial revision
+
+2007-08-01 15:33 ivan
+
+ * FS/FS/Schema.pm: i guess svc_www.usersvc can be null...
+
+2007-08-01 15:24 ivan
+
+ * ANNOUNCE.1.5, CREDITS, FS/MANIFEST, FS/README,
+ FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/Record.pm,
+ FS/FS/Schema.pm, FS/FS/Setup.pm, FS/FS/access_group.pm,
+ FS/FS/access_user.pm, FS/FS/access_user_pref.pm, FS/FS/agent.pm,
+ FS/FS/cust_bill.pm, FS/FS/cust_credit.pm, FS/FS/cust_event.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pay.pm, FS/FS/cust_pay_batch.pm,
+ FS/FS/cust_pkg.pm, FS/FS/cust_refund.pm, FS/FS/m2name_Common.pm,
+ FS/FS/option_Common.pm, FS/FS/part_bill_event.pm,
+ FS/FS/part_event.pm, FS/FS/part_event_condition.pm,
+ FS/FS/part_event_condition_option.pm,
+ FS/FS/part_event_condition_option_option.pm,
+ FS/FS/part_event_option.pm, FS/FS/pay_batch.pm, FS/FS/payby.pm,
+ FS/FS/pkg_referral.pm, FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_domain.pm, FS/FS/svc_forward.pm, FS/FS/svc_www.pm,
+ FS/FS/Cron/bill.pm, FS/FS/Cron/expire_user_pref.pm,
+ FS/FS/part_event/Action.pm, FS/FS/part_event/Condition.pm,
+ FS/FS/part_event/Action/addpost.pm,
+ FS/FS/part_event/Action/apply.pm,
+ FS/FS/part_event/Action/bill.pm,
+ FS/FS/part_event/Action/cancel.pm,
+ FS/FS/part_event/Action/collect.pm,
+ FS/FS/part_event/Action/cust_bill_batch.pm,
+ FS/FS/part_event/Action/cust_bill_comp.pm,
+ FS/FS/part_event/Action/cust_bill_fee_percent.pm,
+ FS/FS/part_event/Action/cust_bill_realtime_card.pm,
+ FS/FS/part_event/Action/cust_bill_realtime_check.pm,
+ FS/FS/part_event/Action/cust_bill_realtime_lec.pm,
+ FS/FS/part_event/Action/cust_bill_send.pm,
+ FS/FS/part_event/Action/cust_bill_send_agent.pm,
+ FS/FS/part_event/Action/cust_bill_send_alternate.pm,
+ FS/FS/part_event/Action/cust_bill_send_csv_ftp.pm,
+ FS/FS/part_event/Action/cust_bill_send_if_newest.pm,
+ FS/FS/part_event/Action/cust_bill_spool_csv.pm,
+ FS/FS/part_event/Action/cust_bill_suspend_if_balance.pm,
+ FS/FS/part_event/Action/fee.pm,
+ FS/FS/part_event/Action/suspend.pm,
+ FS/FS/part_event/Action/suspend_if_pkgpart.pm,
+ FS/FS/part_event/Action/suspend_unless_pkgpart.pm,
+ FS/FS/part_event/Condition/agent.pm,
+ FS/FS/part_event/Condition/agent_type.pm,
+ FS/FS/part_event/Condition/balance.pm,
+ FS/FS/part_event/Condition/balance_age.pm,
+ FS/FS/part_event/Condition/balance_under.pm,
+ FS/FS/part_event/Condition/cust_bill_age.pm,
+ FS/FS/part_event/Condition/cust_bill_owed.pm,
+ FS/FS/part_event/Condition/cust_bill_owed_under.pm,
+ FS/FS/part_event/Condition/cust_pay_batch_declined.pm,
+ FS/FS/part_event/Condition/cust_status.pm,
+ FS/FS/part_event/Condition/every.pm,
+ FS/FS/part_event/Condition/once.pm,
+ FS/FS/part_event/Condition/payby.pm,
+ FS/FS/part_event/Condition/pkg_class.pm,
+ FS/FS/part_event/Condition/pkg_status.pm,
+ FS/FS/part_export/textradius.pm, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/flat_delayed.pm, FS/FS/part_pkg/prorate.pm,
+ FS/FS/part_pkg/prorate_delayed.pm,
+ FS/FS/part_pkg/subscription.pm, FS/bin/freeside-daily,
+ FS/bin/freeside-monthly, FS/t/cust_event.t,
+ FS/t/part_event-Action.t, FS/t/part_event-Condition.t,
+ FS/t/part_event.t, FS/t/part_event_condition.t,
+ FS/t/part_event_condition_option.t,
+ FS/t/part_event_condition_option_option.t,
+ FS/t/part_event_option.t, FS/t/pkg_referral.t,
+ bin/freeside-migrate-events, eg/part_event-Action-template.pm,
+ eg/part_event-Condition-template.pm, fs_selfservice/DEPLOY,
+ htetc/handler.pl, httemplate/browse/access_group.html,
+ httemplate/browse/access_user.html, httemplate/browse/agent.cgi,
+ httemplate/browse/invoice_template.html,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/browse/part_event.html,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.html,
+ httemplate/browse/pkg_class.html, httemplate/browse/reason.html,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/edit/access_group.html, httemplate/edit/agent.cgi,
+ httemplate/edit/cust_main.cgi, httemplate/edit/invoice_logo.html,
+ httemplate/edit/invoice_template.html,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_event.html, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_referral.html, httemplate/edit/reason.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/access_group.html,
+ httemplate/edit/process/invoice_logo.html,
+ httemplate/edit/process/invoice_template.html,
+ httemplate/edit/process/part_event.html,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/edit/process/elements/process.html,
+ httemplate/elements/checkboxes-table-name.html,
+ httemplate/elements/freeside.css,
+ httemplate/elements/hidden.html, httemplate/elements/menu.html,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-agent_type.html,
+ httemplate/elements/select-cust_main-status.html,
+ httemplate/elements/select-cust_pkg-status.html,
+ httemplate/elements/select-part_referral.html,
+ httemplate/elements/select-pkg_class.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/selectlayers.html,
+ httemplate/elements/table-grid.html,
+ httemplate/elements/tr-checkbox-multiple.html,
+ httemplate/elements/tr-checkbox.html,
+ httemplate/elements/tr-fixed.html,
+ httemplate/elements/tr-freq.html,
+ httemplate/elements/tr-input-money.html,
+ httemplate/elements/tr-input-text.html,
+ httemplate/elements/tr-password.html,
+ httemplate/elements/tr-select-agent.html,
+ httemplate/elements/tr-select-agent_type.html,
+ httemplate/elements/tr-select-cust_main-status.html,
+ httemplate/elements/tr-select-cust_pkg-status.html,
+ httemplate/elements/tr-select-invoice_template.html,
+ httemplate/elements/tr-select-part_pkg.html,
+ httemplate/elements/tr-select-part_referral.html,
+ httemplate/elements/tr-select-pkg_class.html,
+ httemplate/elements/tr-select-reason.html,
+ httemplate/elements/tr-select-taxclass.html,
+ httemplate/elements/tr-select.html,
+ httemplate/elements/tr-selectlayers.html,
+ httemplate/elements/tr-selectmultiple-part_pkg.html,
+ httemplate/elements/tr-td-label.html,
+ httemplate/elements/tr-title.html,
+ httemplate/elements/fckeditor/fckconfig.js,
+ httemplate/elements/fckeditor/fckeditor.js,
+ httemplate/elements/fckeditor/fckpackager.xml,
+ httemplate/elements/fckeditor/fckstyles.xml,
+ httemplate/elements/fckeditor/fcktemplates.xml,
+ httemplate/elements/fckeditor/editor/fckdebug.html,
+ httemplate/elements/fckeditor/editor/fckdialog.html,
+ httemplate/elements/fckeditor/editor/fckeditor.html,
+ httemplate/elements/fckeditor/editor/fckeditor.original.html,
+ httemplate/elements/fckeditor/editor/css/fck_editorarea.css,
+ httemplate/elements/fckeditor/editor/css/fck_internal.css,
+ httemplate/elements/fckeditor/editor/css/fck_showtableborders_gecko.css,
+ httemplate/elements/fckeditor/editor/css/behaviors/disablehandles.htc,
+ httemplate/elements/fckeditor/editor/css/behaviors/showtableborders.htc,
+ httemplate/elements/fckeditor/editor/css/images/fck_anchor.gif,
+ httemplate/elements/fckeditor/editor/css/images/fck_flashlogo.gif,
+ httemplate/elements/fckeditor/editor/css/images/fck_hiddenfield.gif,
+ httemplate/elements/fckeditor/editor/css/images/fck_pagebreak.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_about.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_anchor.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_button.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_checkbox.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_colorselector.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_docprops.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_find.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_flash.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_form.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_hiddenfield.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_image.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_link.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_listprop.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_paste.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_radiobutton.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_replace.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_select.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_smiley.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_source.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_specialchar.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_table.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_tablecell.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_template.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_textarea.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_textfield.html,
+ httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.css,
+ httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.js,
+ httemplate/elements/fckeditor/editor/dialog/common/fcknumericfield.htc,
+ httemplate/elements/fckeditor/editor/dialog/common/moz-bindings.xml,
+ httemplate/elements/fckeditor/editor/dialog/common/images/locked.gif,
+ httemplate/elements/fckeditor/editor/dialog/common/images/reset.gif,
+ httemplate/elements/fckeditor/editor/dialog/common/images/unlocked.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fredck.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image_preview.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_link/fck_link.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_select/fck_select.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js,
+ httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl,
+ httemplate/elements/fckeditor/editor/dialog/fck_template/images/template1.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_template/images/template2.gif,
+ httemplate/elements/fckeditor/editor/dialog/fck_template/images/template3.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.css,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmactualfolder.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmfolders.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourceslist.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourcetype.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/frmupload.html,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder32.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/spacer.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/html.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/js.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/png.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/js/common.js,
+ httemplate/elements/fckeditor/editor/filemanager/browser/default/js/fckxml.js,
+ httemplate/elements/fckeditor/editor/filemanager/upload/test.html,
+ httemplate/elements/fckeditor/editor/images/anchor.gif,
+ httemplate/elements/fckeditor/editor/images/arrow_ltr.gif,
+ httemplate/elements/fckeditor/editor/images/arrow_rtl.gif,
+ httemplate/elements/fckeditor/editor/images/spacer.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/angel_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/angry_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/broken_heart.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/cake.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/confused_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/cry_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/devil_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/embaressed_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/envelope.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/heart.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/kiss.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/lightbulb.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/omg_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/regular_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/sad_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/shades_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/teeth_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_down.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_up.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/tounge_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif,
+ httemplate/elements/fckeditor/editor/images/smiley/msn/wink_smile.gif,
+ httemplate/elements/fckeditor/editor/js/fckeditorcode_gecko.js,
+ httemplate/elements/fckeditor/editor/js/fckeditorcode_ie.js,
+ httemplate/elements/fckeditor/editor/lang/_getfontformat.html,
+ httemplate/elements/fckeditor/editor/lang/_translationstatus.txt,
+ httemplate/elements/fckeditor/editor/lang/af.js,
+ httemplate/elements/fckeditor/editor/lang/ar.js,
+ httemplate/elements/fckeditor/editor/lang/bg.js,
+ httemplate/elements/fckeditor/editor/lang/bn.js,
+ httemplate/elements/fckeditor/editor/lang/bs.js,
+ httemplate/elements/fckeditor/editor/lang/ca.js,
+ httemplate/elements/fckeditor/editor/lang/cs.js,
+ httemplate/elements/fckeditor/editor/lang/da.js,
+ httemplate/elements/fckeditor/editor/lang/de.js,
+ httemplate/elements/fckeditor/editor/lang/el.js,
+ httemplate/elements/fckeditor/editor/lang/en-au.js,
+ httemplate/elements/fckeditor/editor/lang/en-ca.js,
+ httemplate/elements/fckeditor/editor/lang/en-uk.js,
+ httemplate/elements/fckeditor/editor/lang/en.js,
+ httemplate/elements/fckeditor/editor/lang/eo.js,
+ httemplate/elements/fckeditor/editor/lang/es.js,
+ httemplate/elements/fckeditor/editor/lang/et.js,
+ httemplate/elements/fckeditor/editor/lang/eu.js,
+ httemplate/elements/fckeditor/editor/lang/fa.js,
+ httemplate/elements/fckeditor/editor/lang/fi.js,
+ httemplate/elements/fckeditor/editor/lang/fo.js,
+ httemplate/elements/fckeditor/editor/lang/fr.js,
+ httemplate/elements/fckeditor/editor/lang/gl.js,
+ httemplate/elements/fckeditor/editor/lang/he.js,
+ httemplate/elements/fckeditor/editor/lang/hi.js,
+ httemplate/elements/fckeditor/editor/lang/hr.js,
+ httemplate/elements/fckeditor/editor/lang/hu.js,
+ httemplate/elements/fckeditor/editor/lang/it.js,
+ httemplate/elements/fckeditor/editor/lang/ja.js,
+ httemplate/elements/fckeditor/editor/lang/km.js,
+ httemplate/elements/fckeditor/editor/lang/ko.js,
+ httemplate/elements/fckeditor/editor/lang/lt.js,
+ httemplate/elements/fckeditor/editor/lang/lv.js,
+ httemplate/elements/fckeditor/editor/lang/mn.js,
+ httemplate/elements/fckeditor/editor/lang/ms.js,
+ httemplate/elements/fckeditor/editor/lang/nb.js,
+ httemplate/elements/fckeditor/editor/lang/nl.js,
+ httemplate/elements/fckeditor/editor/lang/no.js,
+ httemplate/elements/fckeditor/editor/lang/pl.js,
+ httemplate/elements/fckeditor/editor/lang/pt-br.js,
+ httemplate/elements/fckeditor/editor/lang/pt.js,
+ httemplate/elements/fckeditor/editor/lang/ro.js,
+ httemplate/elements/fckeditor/editor/lang/ru.js,
+ httemplate/elements/fckeditor/editor/lang/sk.js,
+ httemplate/elements/fckeditor/editor/lang/sl.js,
+ httemplate/elements/fckeditor/editor/lang/sr-latn.js,
+ httemplate/elements/fckeditor/editor/lang/sr.js,
+ httemplate/elements/fckeditor/editor/lang/sv.js,
+ httemplate/elements/fckeditor/editor/lang/th.js,
+ httemplate/elements/fckeditor/editor/lang/tr.js,
+ httemplate/elements/fckeditor/editor/lang/uk.js,
+ httemplate/elements/fckeditor/editor/lang/vi.js,
+ httemplate/elements/fckeditor/editor/lang/zh-cn.js,
+ httemplate/elements/fckeditor/editor/lang/zh.js,
+ httemplate/elements/fckeditor/editor/plugins/autogrow/fckplugin.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/fck_placeholder.html,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/fckplugin.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/placeholder.gif,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/lang/de.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/lang/en.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/lang/fr.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/lang/it.js,
+ httemplate/elements/fckeditor/editor/plugins/placeholder/lang/pl.js,
+ httemplate/elements/fckeditor/editor/plugins/simplecommands/fckplugin.js,
+ httemplate/elements/fckeditor/editor/plugins/tablecommands/fckplugin.js,
+ httemplate/elements/fckeditor/editor/skins/_fckviewstrips.html,
+ httemplate/elements/fckeditor/editor/skins/default/fck_dialog.css,
+ httemplate/elements/fckeditor/editor/skins/default/fck_editor.css,
+ httemplate/elements/fckeditor/editor/skins/default/fck_strip.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.arrowright.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.collapse.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.end.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.expand.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.separator.gif,
+ httemplate/elements/fckeditor/editor/skins/default/images/toolbar.start.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/fck_dialog.css,
+ httemplate/elements/fckeditor/editor/skins/office2003/fck_editor.css,
+ httemplate/elements/fckeditor/editor/skins/office2003/fck_strip.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.bg.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.end.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.expand.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.separator.gif,
+ httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.start.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/fck_dialog.css,
+ httemplate/elements/fckeditor/editor/skins/silver/fck_editor.css,
+ httemplate/elements/fckeditor/editor/skins/silver/fck_strip.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.collapse.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.end.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.expand.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.separator.gif,
+ httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.start.gif,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/graph/report_money_time.html,
+ httemplate/misc/cancel_cust.html,
+ httemplate/misc/cancel_pkg.html,
+ httemplate/misc/cust_main-cancel.cgi,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/email_events.cgi, httemplate/misc/fax_events.cgi,
+ httemplate/misc/order_pkg.html, httemplate/misc/print_events.cgi,
+ httemplate/misc/process/cancel_pkg.html,
+ httemplate/pref/pref-process.html,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_bill_event.html,
+ httemplate/search/cust_event.html,
+ httemplate/search/report_cust_bill.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_event.html,
+ httemplate/search/report_cust_main-zip.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_cust_pay_batch.html,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_broadband.cgi,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_forward.cgi,
+ httemplate/search/svc_phone.cgi, httemplate/search/svc_www.cgi,
+ httemplate/search/elements/search.html,
+ httemplate/view/cust_bill-logo.cgi,
+ httemplate/view/cust_bill.cgi, httemplate/view/cust_main.cgi,
+ httemplate/view/logo.cgi, httemplate/view/svc_Common.html,
+ httemplate/view/cust_main/order_pkg.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html, test/cgi-test:
+ event refactor, landing on HEAD!
+
+2007-08-01 15:20 ivan
+
+ * rt/: Makefile, config.log, config.status, bin/mason_handler.fcgi,
+ bin/mason_handler.scgi, bin/mason_handler.svc,
+ bin/rt-commit-handler, bin/rt-crontool, bin/rt-mailgate,
+ bin/webmux.pl, etc/RT_Config.pm, lib/RT.pm,
+ lib/RTx/WebCronTool.pm, lib/t/02regression.t, lib/t/03web.pl,
+ lib/t/04_send_email.pl: commit these RT differences, seem to be
+ mostly in autogen'ed stuff
+
+2007-08-01 15:13 ivan
+
+ * rt/html/Callbacks/kStatistics/Elements/Tabs/Default: because i
+ had missed commiting this on HEAD, that's why
+
+2007-08-01 12:24 ivan
+
+ * httemplate/misc/process/cancel_pkg.html: comment out unused code
+
+2007-08-01 12:22 ivan
+
+ * httemplate/elements/xmlhttp.html: masonization
+
+2007-08-01 12:21 ivan
+
+ * FS/bin/freeside-upgrade: freeside-upgrade: add'l documentation &
+ turn on DBIx::DBSchema::Index debugging too
+
+2007-08-01 12:19 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: better error reporting: all three
+ of these methods might return an error
+
+2007-08-01 12:19 ivan
+
+ * FS/FS/reason.pm: more generic modules first
+
+2007-08-01 12:18 ivan
+
+ * FS/FS/Conf.pm: some comments on config_orbase sub and add'l
+ description for emailcancel config
+
+2007-07-26 04:13 ivan
+
+ * FS/FS/Schema.pm: add index
+
+2007-07-20 12:58 ivan
+
+ * bin/apache.export: apache export: don't bomb out when svc_www
+ records aren't associated with an svc_acct, just leave those
+ subsitution vars blank
+
+2007-07-19 07:05 jeff
+
+ * httemplate/config/config-view.cgi: do not include description in
+ link to popup
+
+2007-07-18 14:13 ivan
+
+ * FS/FS/Schema.pm: Schema.pm doesn't need FS::UID datasrc anyway,
+ wtf
+
+2007-07-18 11:07 jeff
+
+ * FS/FS/Conf.pm, httemplate/browse/agent.cgi,
+ httemplate/config/config-delete.cgi,
+ httemplate/config/config-download.cgi,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi:
+ config in database cleanup, editing, and agent-specific config
+ (452, 1419)
+
+2007-07-17 20:23 jeff
+
+ * FS/FS/AccessRight.pm, httemplate/edit/svc_acct.cgi: svc_acct.dir
+ should be editable with ACL (#1730)
+
+2007-07-13 17:44 ivan
+
+ * bin/find-overapplied: a payment, by any other name
+
+2007-07-13 16:58 ivan
+
+ * bin/find-overapplied: adding quick find-overapplied script
+
+2007-07-13 16:52 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ FS/FS/ClientAPI/Signup.pm, FS/FS/Cron/bill.pm,
+ FS/bin/freeside-prepaidd, httemplate/misc/bill.cgi,
+ httemplate/misc/process/recharge_svc.html,
+ httemplate/edit/process/cust_main.cgi: fix race condition where
+ ->apply_payments_and_credits could double-apply in rare cases
+
+2007-07-13 10:00 jeff
+
+ * FS/FS/Conf.pm: a touch should not obliterate
+
+2007-07-12 14:41 ivan
+
+ * bin/apache.export: add debugging flag to apache export
+
+2007-07-12 14:08 jeff
+
+ * FS/FS/UID.pm: redundant test
+
+2007-07-12 06:36 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Conf_compat17.pm, FS/FS/Misc.pm,
+ FS/FS/Record.pm, FS/FS/UID.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ FS/bin/freeside-init-config, FS/bin/freeside-setup,
+ FS/bin/freeside-upgrade, httemplate/misc/download-batch.cgi:
+ refactor freeside-init-config to module code, compare results of
+ old/new code, have freeside-upgrade complain and revert to old
+ code/config on failure (#1477)
+
+2007-07-11 04:10 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: show bad
+ amount in error message
+
+2007-07-11 01:35 ivan
+
+ * FS/FS/cust_main.pm: finish adding payunique field
+
+2007-07-11 01:08 ivan
+
+ * FS/FS/cust_pay.pm, httemplate/misc/payment.cgi,
+ httemplate/misc/process/payment.cgi: finish adding payunique
+ field
+
+2007-07-10 21:23 jeff
+
+ * FS/FS/cust_main.pm: honor bop_realtime options for paystate,
+ paytype, stateid, and stateid_state for CHEK transactions (#1718)
+
+2007-07-06 16:55 jeff
+
+ * httemplate/edit/process/svc_acct.cgi: manually editing usage
+ counters removes overlimit status (#1706)
+
+2007-07-06 01:08 ivan
+
+ * GPL, README: v3!
+
+2007-07-05 15:05 ivan
+
+ * FS/FS/Record.pm: fix for compatibility w/DBIx::DBSchema v0.33+
+ (without requiring it)
+
+2007-07-01 17:15 ivan
+
+ * FS/FS/cust_pkg.pm: missing method name in docs
+
+2007-07-01 11:26 ivan
+
+ * fs_selfadmin/FS-MailAdminServer/MailAdminClient.pm,
+ fs_sesmon/FS-SessionClient/SessionClient.pm: this stuff is
+ probably obsoleted, but get rid of CVS Id tags causing merge pain
+ anyway
+
+2007-07-01 11:09 ivan
+
+ * TODO: remove obsolete information and dollar sign Id dollar sign
+ from TODO
+
+2007-06-30 17:36 ivan
+
+ * httemplate/edit/agent.cgi: separate agent interface is
+ deprecated...
+
+2007-06-29 14:06 ivan
+
+ * httemplate/: edit/svc_www.cgi, view/svc_www.cgi: add regular
+ header/footer to svc_www view and edit
+
+2007-06-28 18:45 ivan
+
+ * FS/FS/Record.pm: last small fix for new DBIx::DBSchema
+
+2007-06-28 18:42 ivan
+
+ * FS/FS/cust_pay.pm: silly missing parenthesis
+
+2007-06-28 18:27 ivan
+
+ * bin/: create-history-tables, strip-eps: removing
+ create-history-tables, freeside-upgrade does this anyway
+
+2007-06-28 18:23 ivan
+
+ * FS/FS/: Schema.pm, cust_pay.pm: add payunique field and dup
+ checking
+
+2007-06-28 18:16 ivan
+
+ * FS/FS/: Schema.pm: update Schema.pm to handle index updates, with
+ new DBIx::DBSchema
+
+2007-06-28 13:57 ivan
+
+ * bin/: bill-as-nextmonth, bill-as-nextmonth-BILL,
+ bill-as-nextyear, bill-as-nextyear-BILL: add some quick scripts
+ for cron jobs
+
+2007-06-26 11:58 ivan
+
+ * httemplate/search/cust_pay.cgi: fix check# search
+
+2007-06-26 11:20 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: we need
+ Number::Format 1.50, not just any version
+
+2007-06-26 09:55 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/view_usage_details.html: add
+ date range to page top
+
+2007-06-26 08:36 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/Cron/bill.pm, FS/FS/Cron/notify.pm,
+ httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/misc/cancel_pkg.html,
+ httemplate/misc/process/cancel_pkg.html,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/view/cust_main/packages.html: suspend later just like
+ expire (#1487)
+
+2007-06-25 19:31 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/view_usage_details.html: change
+ "====" to <HR> in selfservice usage stuff. welcome to this
+ millenium! :)
+
+2007-06-22 14:25 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/: selfservice.cgi,
+ view_usage_details.html: self-service usage report enhancements
+ (1495)
+
+2007-06-22 10:27 jeff
+
+ * httemplate/graph/elements/monthly.html: add csv and excel export
+ to sales reports (1426)
+
+2007-06-22 10:21 jeff
+
+ * FS/FS/part_export/www_shellcommands.pm: documentation improvement
+
+2007-06-20 21:02 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Misc.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pkg.pm, conf/welcome_letter: latex
+ welcome letters (1677)
+
+2007-06-20 15:58 ivan
+
+ * rt/: etc/RT_SiteConfig.pm, html/Elements/QuickCreate: add
+ QuickCreateLong option, part of merging spiritone RT changes
+
+2007-06-20 15:37 ivan
+
+ * rt/html/Elements/Tabs: s/Tickets/Search Tickets/ in menu for
+ clarity, part of merging spiritone RT changes (#1661)
+
+2007-06-20 15:33 ivan
+
+ * rt/: html/Elements/TicketList, etc/RT_SiteConfig.pm: add
+ $RT::MyTicketsLength patch from spiritone, part of merging RT
+ changes (#1661)
+
+2007-06-20 15:28 ivan
+
+ * CREDITS, rt/html/RTx/Statistics/DurationAsString,
+ rt/html/RTx/Statistics/index.html,
+ rt/html/RTx/Statistics/CallsMultiQueue/index.html,
+ rt/html/RTx/Statistics/CallsMultiQueue/Elements/Chart,
+ rt/html/RTx/Statistics/CallsQueueDay/Results.tsv,
+ rt/html/RTx/Statistics/CallsQueueDay/index.html,
+ rt/html/RTx/Statistics/CallsQueueDay/Elements/Chart,
+ rt/html/RTx/Statistics/DayOfWeek/index.html,
+ rt/lib/RT/Extension/ActivityReports.pm, rt/lib/RTx/Statistics.pm,
+ rt/html/RTx/Statistics/DayOfWeek/Elements/Chart,
+ rt/html/RTx/Statistics/Elements/DateSelectRow,
+ rt/html/RTx/Statistics/Elements/DurationAsString,
+ rt/html/RTx/Statistics/Elements/GraphBox,
+ rt/html/RTx/Statistics/Elements/SelectMultiQueue,
+ rt/html/RTx/Statistics/Elements/StatColumnMap,
+ rt/html/RTx/Statistics/Elements/Tabs,
+ rt/html/RTx/Statistics/Elements/CollectionAsTable/Header,
+ rt/html/RTx/Statistics/Elements/CollectionAsTable/ParseFormat,
+ rt/html/RTx/Statistics/Elements/CollectionAsTable/Row,
+ rt/html/RTx/Statistics/Elements/ControlsAsTable/ControlBox,
+ rt/html/RTx/Statistics/Elements/ControlsAsTable/UpdatePage,
+ rt/html/RTx/Statistics/FAQ/index.html,
+ rt/html/RTx/Statistics/OpenStalled/Results.tsv,
+ rt/html/RTx/Statistics/OpenStalled/index.html,
+ rt/html/RTx/Statistics/OpenStalled/Elements/Chart,
+ rt/html/RTx/Statistics/Resolution/index.html,
+ rt/html/RTx/Statistics/Resolution/Elements/Chart,
+ rt/html/Callbacks/ActivityReports/Elements/Tabs/Default,
+ rt/html/Callbacks/ActivityReports/NoAuth/webrt.css/Default,
+ rt/html/RTx/Statistics/TimeToResolve/index.html,
+ rt/html/RTx/Statistics/TimeToResolve/Elements/Chart,
+ rt/html/RTx/Statistics/UserTest/index.html,
+ rt/html/RTx/Statistics/UserTest/Elements/Chart,
+ rt/html/Callbacks/ActivityReports/Search/Results.html/SearchActions,
+ rt/html/Callbacks/RT-WebCronTool/Elements/Tabs/Default,
+ rt/html/Developer/CronTool/autohandler,
+ rt/html/Developer/CronTool/index.html,
+ rt/html/Reports/Activity/ActivityDetail.html,
+ rt/html/Reports/Activity/ActivitySummary.html,
+ rt/html/Reports/Activity/ResolutionComments.html,
+ rt/html/Reports/Activity/ResolutionStatistics.html,
+ rt/html/Reports/Activity/index.html,
+ rt/html/Reports/Activity/Elements/LimitReport,
+ rt/html/Reports/Activity/Elements/MiniPlot,
+ rt/html/Reports/Activity/Elements/PrintFooter,
+ rt/html/Reports/Activity/Elements/PrintHeader,
+ rt/html/Reports/Activity/Elements/ScreenFooter,
+ rt/html/Reports/Activity/Elements/ScreenHeader,
+ rt/html/Reports/Activity/Elements/Tabs,
+ rt/html/Reports/Activity/Elements/Wrapper: integrate
+ RTx::Statistics package, part of merging spiritone RT changes
+ (#1661)
+
+2007-06-18 09:45 jeff
+
+ * httemplate/edit/svc_www.cgi: must escape config data
+
+2007-06-15 11:44 jeff
+
+ * FS/FS/cust_main.pm, httemplate/edit/cust_refund.cgi,
+ httemplate/edit/process/cust_refund.cgi: paydate option for
+ realtime_refund_bop and UI entry for cust_pay records without it
+ (#1662 UI)
+
+2007-06-14 17:58 jeff
+
+ * FS/FS/: Schema.pm, cust_main.pm: store exp in cust_pay and pass
+ to B:OP during refunds with paynum (#1662)
+
+2007-06-13 09:56 jeff
+
+ * FS/FS/part_export/sqlradius.pm: additional debugging
+
+2007-06-08 17:53 ivan
+
+ * bin/: bill-for-nextmonth, bill-for-nextyear: adding
+ bill-for-next* hacks like bill-next* stuff but with -n flag, for
+ skycatcher
+
+2007-06-08 17:40 ivan
+
+ * FS/: FS/cust_main.pm, FS/Cron/bill.pm, bin/freeside-daily:
+ skycatcher modifications for pre-printing invoices, but with
+ today's date
+
+2007-06-08 16:21 ivan
+
+ * bin/all-postal-no-email: adding quick script to move all
+ customers to postal billing only for skycatcher
+
+2007-06-08 10:38 jeff
+
+ * FS/FS/part_export/sqlradius.pm: prevent multiple additions to
+ usergroup table (work around #1606)
+
+2007-06-08 07:40 jeff
+
+ * FS/FS/part_export/prizm.pm: queue suspend, unsuspend, and delete
+ (fixes #1657)
+
+2007-06-06 17:45 jeff
+
+ * FS/FS/cust_bill.pm: cruft removal
+
+2007-06-06 15:34 jeff
+
+ * FS/FS/: Conf.pm, cust_bill.pm: service dates on invoices optional
+ (#1658)
+
+2007-06-06 12:58 khoff
+
+ * FS/FS/: cust_main.pm, Conf.pm: Added 'disable_void_after' config
+ option to disable the VOID-before-credit behavior of
+ FS::cust_main::realtime_refund_bop after n seconds, if set. For
+ broken gateways like SkipJack that a pprove VOIDs for settled
+ transactions.
+
+2007-06-05 08:07 jeff
+
+ * FS/FS/svc_acct.pm: correct shorage of variables bound to prepared
+ statement
+
+2007-06-02 14:07 jeff
+
+ * httemplate/elements/header.html: drop ticket search form and
+ logic from ticketless installs
+
+2007-05-31 08:03 jeff
+
+ * httemplate/edit/payment_gateway.html: add TransFirst eLink
+ support
+
+2007-05-29 20:38 ivan
+
+ * FS/FS/svc_external.pm: should eliminiate error: Use of
+ uninitialized value in string eq at
+ /usr/local/share/perl/5.8.8/FS/svc_external.pm line 82.
+
+2007-05-29 20:05 ivan
+
+ * httemplate/view/svc_domain.cgi: fix javascript confirmation for
+ domain records with " in them...
+
+2007-05-21 17:34 ivan
+
+ * httemplate/search/report_tax.cgi: fix tax reports for some odd
+ upgrade edge cases: when you have both taxclass and non-taxclass
+ entries in cust_main_county for a single region (not correct
+ setup in the first place), and non-null but empty values in
+ taxname
+
+2007-05-20 19:18 ivan
+
+ * FS/FS/Schema.pm: haven't had anyone use this in years, and for
+ some reason DBIx::DBSchema can't reverse engineer the schema for
+ it, causing freeside-upgrade to error out trying to recreate it
+
+2007-05-18 16:44 ivan
+
+ * httemplate/edit/cust_main/billing.html: have "emailinvoiceonly"
+ hide postal/fax invoice options in backoffice as well as
+ self-service. closes: bug#1614
+
+2007-05-11 16:18 khoff
+
+ * httemplate/search/: report_cust_bill.html,
+ report_cust_credit.html, report_cust_main-zip.html,
+ report_cust_pay.html, report_cust_pay_batch.html,
+ report_cust_pkg.html: Fix (hopefully) all uses of
+ /elements/tr-select-agent.html where agentnum may be undefined.
+
+2007-05-11 12:03 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: logout seems not to return
+ an error status, so don't up the queue with "failed: Can't logout
+ of CGPro: No error"
+
+2007-05-11 11:14 khoff
+
+ * httemplate/elements/header.html: Use FS::TicketSystem to get RT
+ URL.
+
+2007-05-11 11:08 khoff
+
+ * FS/FS/XMLRPC.pm: Quiet debug output.
+
+2007-05-08 15:43 jeff
+
+ * FS/FS/part_pkg/: prorate.pm, subscription.pm: add formatting to
+ plan data
+
+2007-05-08 15:10 jeff
+
+ * FS/FS/part_pkg/flat.pm: charges and time are not measured in
+ megabytes
+
+2007-05-08 09:51 ivan
+
+ * bin/: bill-nextmonth, bill-nextyear: [no log message]
+
+2007-05-06 23:35 jeff
+
+ * FS/bin/: freeside-sqlradius-dedup-group,
+ freeside-sqlradius-reset: sqlradius usergroup tools
+
+2007-05-06 19:14 jeff
+
+ * httemplate/misc/download-batch.cgi: 1609 correct spiritone ACH
+
+2007-05-06 19:13 jeff
+
+ * FS/FS/cust_pkg.pm, FS/FS/svc_acct.pm,
+ httemplate/misc/process/link.cgi: 1606 correct bug in overlimit
+ groups handling
+
+2007-05-01 14:49 ivan
+
+ * fs_webdemo/: register.cgi, register.html, registerd,
+ registerd.Pg: removing 1.4-era web demo signup
+
+2007-05-01 14:47 ivan
+
+ * fs_radlog/fs_radlogd: removing decade-old fs_radlog (you want
+ freeside-sqlradius-radacctd now)
+
+2007-05-01 14:27 ivan
+
+ * install/: centos/3/INSTALL, centos/3/httpd-init,
+ debian/3.0/INSTALL, debian/3.1/INSTALL, fedora/fc1/INSTALL,
+ fedora/fc1/sources.list, fedora/fc2/INSTALL,
+ fedora/fc2/sources.list, fedora/fc3/INSTALL,
+ fedora/fc3/sources.list, freebsd/INSTALL, freebsd/ports,
+ openbsd/INSTALL, openbsd/cpan, openbsd/ports, redhat/7.3/INSTALL,
+ redhat/7.3/sources.list, redhat/8/INSTALL,
+ redhat/8/README.insecure, redhat/8/sources.list,
+ redhat/9/INSTALL, redhat/9/sources.list, redhat/es3/INSTALL,
+ redhat/es3/httpd-init, suse/9.0/INSTALL: remove obsolete install
+ notes
+
+2007-05-01 13:00 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: without debugging this time :)
+
+2007-05-01 12:57 ivan
+
+ * FS/: bin/freeside-selfservice-server, FS/ClientAPI/Signup.pm: use
+ FS::ClientAPI_SessionCache for signup info so it actually works -
+ speed up signups
+
+2007-04-29 15:55 jeff
+
+ * FS/FS/Conf.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/ach_payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/make_ach_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ httemplate/view/cust_main/billing.html: ticket 1568 config
+ options for new echeck fields and addition to selfservice
+ interface
+
+2007-04-27 15:54 jeff
+
+ * httemplate/edit/cust_main/contact.html: adjust default labelling
+
+2007-04-27 15:37 jeff
+
+ * httemplate/edit/cust_main/billing.html: SELECT doesn't accept a
+ value
+
+2007-04-25 21:46 jeff
+
+ * FS/FS/svc_acct.pm, FS/FS/ClientAPI/MyAccount.pm,
+ httemplate/misc/recharge_svc.html: more datavolume format
+
+2007-04-25 20:35 ivan
+
+ * FS/FS/UI/bytecount.pm: old Number::Format silently ignores
+ datavolume-forcemegabytes
+
+2007-04-25 20:09 jeff
+
+ * FS/FS/UI/bytecount.pm: improve configfile handling
+
+2007-04-25 18:50 jeff
+
+ * FS/FS/pay_batch.pm, httemplate/misc/download-batch.cgi: revert
+ dodgy ACH hack from ticket 1436
+
+2007-04-24 17:54 ivan
+
+ * FS/FS/: cust_bill.pm, Conf.pm: add lpr-postscript_prefix and
+ lpr-postscript_suffix config options for printer commands to
+ place printer in postscript mode
+
+2007-04-23 17:21 jeff
+
+ * FS/FS/svc_www.pm: untaint
+
+2007-04-23 17:04 jeff
+
+ * httemplate/view/svc_acct.cgi: missed a bytecount
+
+2007-04-23 16:34 ivan
+
+ * httemplate/search/cust_pkg.cgi: fix error: column reference
+ "fieldname" is ambiguous
+
+2007-04-22 20:41 jeff
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_bill.pm,
+ FS/FS/pay_batch.pm, httemplate/misc/download-batch.cgi,
+ httemplate/misc/payment.cgi, httemplate/misc/process/payment.cgi:
+ add to ACH batch feature from customer view page
+
+2007-04-20 21:44 ivan
+
+ * FS/FS/cust_svc.pm: bring POD documentation in line with reality
+ wrt where we're storing phone numbers
+
+2007-04-20 14:40 ivan
+
+ * conf/: invoice_html, invoice_latex: add customer # to default
+ invoice templates
+
+2007-04-20 14:31 ivan
+
+ * httemplate/view/cust_main/billing.html: don't put this
+ information way out on the right in its own columns.
+
+2007-04-19 16:34 ivan
+
+ * FS/FS/UI/Web.pm: not needed here anymore, bytecount stuff moved
+ to its own module
+
+2007-04-19 16:30 jeff
+
+ * FS/FS/svc_acct.pm, FS/FS/UI/Web.pm, FS/FS/UI/bytecount.pm,
+ FS/FS/part_pkg/flat.pm, FS/FS/ClientAPI/MyAccount.pm,
+ httemplate/edit/process/prepay_credit.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/search/prepay_credit.html, htetc/handler.pl: break
+ _bytecount subroutines out of FS::UI::Web
+
+2007-04-19 13:18 ivan
+
+ * htetc/handler.pl, httemplate/search/cust_svc.html,
+ httemplate/view/cust_main/packages.html, FS/FS/UI/Web.pm,
+ httemplate/browse/part_svc.cgi, httemplate/elements/menu.html:
+ fix very strange "Undefined subroutine &FS::UI::Web::rooturl"
+ with an explicit import. did i mention this was really really
+ weird?
+
+2007-04-18 20:15 ivan
+
+ * FS/FS/UID.pm: better error message about missing secrets file
+ errors. WTF is going on!
+
+2007-04-18 16:22 ivan
+
+ * FS/: FS/svc_acct.pm, FS/part_pkg/flat.pm, bin/freeside-queued:
+ fix use statements for FS::UI::Web. not "use"ing modules in the
+ actual modules you use them in is bad, mmmkay
+
+2007-04-18 13:01 ivan
+
+ * FS/FS/part_pkg.pm: praise the parser! amen! (fix a doc typo)
+
+2007-04-12 17:53 jeff
+
+ * FS/FS/svc_acct.pm: correct boneheaded afterthoughts
+
+2007-04-11 20:16 jeff
+
+ * FS/FS/Conf.pm, FS/FS/part_pkg.pm, FS/FS/part_svc.pm,
+ FS/FS/svc_acct.pm, FS/FS/UI/Web.pm, FS/FS/part_pkg/flat.pm,
+ FS/bin/freeside-queued, httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/view/svc_acct.cgi: input and output on data volume
+ fields specified with k,m,g,or t
+
+2007-04-11 19:42 ivan
+
+ * FS/FS/svc_Common.pm: quiet "Use of uninitialized value in string
+ eq at /usr/local/share/perl/5.8.4/FS/svc_Common.pm line 131". i
+ think.
+
+2007-04-11 19:27 ivan
+
+ * httemplate/misc/process/recharge_svc.html: remove
+ 'backend-realtime' flag required for recharges, want that just
+ for signups, running recharges right away by default is fine.
+ also fix the 'fatal error - unknown payby' error that'll probably
+ never be reached
+
+2007-04-10 21:28 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm,
+ FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ httemplate/view/cust_main/packages.html: usage suspend vs admin
+ suspend -- avoid actual cust_pkg::suspend except legacy cases
+
+2007-04-09 18:44 ivan
+
+ * FS/FS/Conf.pm: remove a ton of deprecated config options
+
+2007-04-09 18:29 ivan
+
+ * FS/FS/Conf.pm: add checkbox to payment_receipt_email config
+
+2007-04-09 16:38 jeff
+
+ * httemplate/misc/: recharge_svc.html, process/recharge_svc.html:
+ trigger recharge from the backend as in self-service
+
+2007-04-07 18:14 jeff
+
+ * FS/FS/: Conf.pm, svc_acct.pm: configuration option to have
+ generated passwords be all caps
+
+2007-04-07 17:41 jeff
+
+ * httemplate/edit/svc_acct.cgi: correct usage editing bug
+
+2007-04-07 17:22 jeff
+
+ * FS/FS/svc_acct.pm: threshold usage email should not be sent to
+ svc_acct->email
+
+2007-04-06 17:07 jeff
+
+ * httemplate/view/cust_main/billing.html: ommitted file
+
+2007-04-06 16:57 jeff
+
+ * FS/FS/cust_main.pm, httemplate/misc/payment.cgi,
+ httemplate/misc/process/payment.cgi: integrate new echeck fields
+ into freeside backend payment processing
+
+2007-04-06 12:38 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_main/select-state.html: ticket 1443 add
+ account type and bank state for echeck processing
+
+2007-04-05 17:37 ivan
+
+ * FS/FS/Conf.pm: slight update for batch-enable description & add
+ ach-spiritone format to batch-default and batch-fixed_format-CHEK
+ config items
+
+2007-04-05 17:34 ivan
+
+ * FS/FS/Conf.pm: slight better descriptions
+
+2007-04-05 17:01 khoff
+
+ * FS/FS/part_export/nas_wrapper.pm: Disable debug output by
+ default. Pass @_ along to new exports.
+
+2007-04-05 15:01 ivan
+
+ * httemplate/elements/menu.html: they're comments now
+
+2007-04-05 07:15 jeff
+
+ * httemplate/misc/process/cust_main_note-import.cgi: use comments
+ and not notes
+
+2007-04-04 19:04 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/view/cust_main/billing.html: per-customer invoice
+ terms override
+
+2007-04-04 18:45 ivan
+
+ * httemplate/pref/pref.html: finish moving vonage integration to a
+ user pref
+
+2007-04-04 18:38 ivan
+
+ * httemplate/pref/pref-process.html: finish moving the vonage
+ integration to per-user
+
+2007-04-04 17:01 ivan
+
+ * FS/bin/freeside-init-config: correct usage
+
+2007-04-04 15:42 ivan
+
+ * Makefile: yes virginia
+
+2007-04-04 13:04 jeff
+
+ * FS/bin/freeside-upgrade: correct a bootstrap issue
+
+2007-04-04 08:30 jeff
+
+ * FS/FS/cust_bill.pm: squash bug which causes re-email failed
+ events to fail
+
+2007-04-03 12:37 jeff
+
+ * httemplate/misc/cust_main_note-import.cgi: correct handling of
+ non-unix line termination
+
+2007-04-02 18:39 ivan
+
+ * bin/fs-migrate-cust_tax_exempt: [no log message]
+
+2007-04-02 08:49 jeff
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/Setup.pm,
+ FS/FS/cust_main.pm, httemplate/edit/cust_main/contact.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/view/cust_main/contacts.html: ticket 1528 add driver's
+ license field, mask it and ssn
+
+2007-03-31 19:45 jeff
+
+ * httemplate/view/svc_www.cgi, FS/FS/AccessRight.pm,
+ FS/FS/Schema.pm, bin/apache.export, httemplate/edit/svc_www.cgi:
+ quick hack to add extra 'config lines' to svc_www and otherwise
+ enhance svc_www
+
+2007-03-27 20:59 ivan
+
+ * FS/FS/svc_acct.pm: fix bug with RADIUS groups not available to
+ shellcommands delete export
+
+2007-03-21 16:07 ivan
+
+ * FS/FS/cust_main.pm: fix bug displaying additional debugging info
+ when process returns no error_message
+
+2007-03-21 15:09 ivan
+
+ * FS/FS/cust_main.pm: realtime_bop: if a transaction fails without
+ an error_message, output additional debugging information, if
+ available
+
+2007-03-20 21:01 jeff
+
+ * FS/FS/pay_batch.pm, httemplate/misc/download-batch.cgi,
+ httemplate/search/cust_pay_batch.cgi: ticket 1436, ACH export
+ format, return processing and autopost
+
+2007-03-20 18:21 jeff
+
+ * FS/bin/freeside-fetch, httemplate/pref/pref-process.html,
+ httemplate/pref/pref.html: ticket 1427, automatically email excel
+ a/r report
+
+2007-03-20 15:10 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: fix bug: usage of promo code broke
+ agent-specific advertising sources
+
+2007-03-20 13:11 jeff
+
+ * httemplate/misc/: cust_main_note-import.cgi,
+ cust_main_note-import.html, process/cust_main_note-import.cgi:
+ acls on new import
+
+2007-03-20 13:01 jeff
+
+ * httemplate/elements/menu.html: tie note import into menu
+
+2007-03-20 10:03 jeff
+
+ * FS/FS/cust_main.pm, httemplate/misc/cust_main_note-import.html,
+ httemplate/misc/cust_main_note-import.cgi,
+ httemplate/misc/process/cust_main_note-import.cgi: ticket 1418, a
+ tool for customer note importation
+
+2007-03-15 18:35 ivan
+
+ * FS/FS/Conf.pm, httemplate/elements/phonenumber.html,
+ httemplate/pref/pref.html: vonage click2call integration should
+ not be sitewide, especially now that we have user prefs
+
+2007-03-15 13:54 ivan
+
+ * FS/FS/part_pkg.pm: 13 months!
+
+2007-03-15 13:08 khoff
+
+ * httemplate/edit/part_virtual_field.cgi: Set input form MAXLENGTH
+ attributes to match actual field sizes.
+
+2007-03-15 13:08 khoff
+
+ * FS/FS/part_export/router.pm: Added configurable error checks
+ instead of stupid /^ERROR/ check. Commands can now be processed
+ with Text::Template using [@-- --@] delimeters, in addition to
+ evaling a double-quoted string. Cleaned up spurious debug
+ output.
+
+2007-03-15 13:07 khoff
+
+ * FS/FS/part_virtual_field.pm: Escape the values in virtual field
+ html form inputs.
+
+2007-03-15 13:07 khoff
+
+ * FS/FS/Schema.pm: part_virtual_field.vfieldpart should be a
+ serial.
+
+2007-03-14 16:30 jeff
+
+ * FS/FS/svc_acct.pm: turn debugging off
+
+2007-03-14 16:27 jeff
+
+ * FS/FS/svc_acct.pm: correcting ->replace on bill
+
+2007-03-13 02:21 ivan
+
+ * FS/FS/cust_pkg.pm: okay, so this should link to usernum now. but
+ until then, it should be ->username, not ->name, eek. causing
+ "Error: Error inserting cust_pkg_reason: ERROR: value to long for
+ type character varying(32)" errors and will be harder to
+ normalize back to usernum when we fix that
+
+2007-03-10 20:13 ivan
+
+ * httemplate/browse/svc_acct_pop.cgi: move POP to browse template;
+ whew, its paged
+
+2007-03-09 16:16 khoff
+
+ * FS/FS/Record.pm: Added $FS::Record::no_update_diff flag to update
+ "identical" records anyway.
+
+2007-03-09 16:11 khoff
+
+ * FS/FS/: Record.pm, svc_broadband.pm: Added ut_coord and ut_coordn
+ for FS::svc_broadband.
+
+2007-03-09 09:11 jeff
+
+ * bin/svc_acct_pop.import: pop import tool
+
+2007-03-09 00:58 ivan
+
+ * install/5.005/: DBD-Pg-1.22-fixvercmp/Changes,
+ DBD-Pg-1.22-fixvercmp/MANIFEST,
+ DBD-Pg-1.22-fixvercmp/Makefile.PL, DBD-Pg-1.22-fixvercmp/Pg.h,
+ DBD-Pg-1.22-fixvercmp/Pg.pm, DBD-Pg-1.22-fixvercmp/Pg.xs,
+ DBD-Pg-1.22-fixvercmp/README, DBD-Pg-1.22-fixvercmp/README.win32,
+ DBD-Pg-1.22-fixvercmp/dbd-pg.pod, DBD-Pg-1.22-fixvercmp/dbdimp.c,
+ DBD-Pg-1.22-fixvercmp/dbdimp.h,
+ DBD-Pg-1.22-fixvercmp/eg/ApacheDBI.pl,
+ DBD-Pg-1.22-fixvercmp/eg/lotest.pl,
+ DBD-Pg-1.22-fixvercmp/eg/notify_test.patch,
+ DBD-Pg-1.22-fixvercmp/t/00basic.t,
+ DBD-Pg-1.22-fixvercmp/t/01connect.t,
+ DBD-Pg-1.22-fixvercmp/t/01constants.t,
+ DBD-Pg-1.22-fixvercmp/t/01setup.t,
+ DBD-Pg-1.22-fixvercmp/t/02prepare.t,
+ DBD-Pg-1.22-fixvercmp/t/03bind.t,
+ DBD-Pg-1.22-fixvercmp/t/04execute.t,
+ DBD-Pg-1.22-fixvercmp/t/05fetch.t,
+ DBD-Pg-1.22-fixvercmp/t/06disconnect.t,
+ DBD-Pg-1.22-fixvercmp/t/07reuse.t,
+ DBD-Pg-1.22-fixvercmp/t/08txn.t,
+ DBD-Pg-1.22-fixvercmp/t/09autocommit.t,
+ DBD-Pg-1.22-fixvercmp/t/11quoting.t,
+ DBD-Pg-1.22-fixvercmp/t/12placeholders.t,
+ DBD-Pg-1.22-fixvercmp/t/13pgtype.t,
+ DBD-Pg-1.22-fixvercmp/t/15funct.t,
+ DBD-Pg-1.22-fixvercmp/t/99cleanup.t,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Handler.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/RDBMS.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Request.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Util.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Handler/Prompt.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/RDBMS/PostgreSQL.pm,
+ DBIx-DBSchema-0.23-5.005kludge/Changes,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema.pm,
+ DBIx-DBSchema-0.23-5.005kludge/MANIFEST,
+ DBIx-DBSchema-0.23-5.005kludge/MANIFEST.SKIP,
+ DBIx-DBSchema-0.23-5.005kludge/Makefile.PL,
+ DBIx-DBSchema-0.23-5.005kludge/README,
+ DBIx-DBSchema-0.23-5.005kludge/TODO,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/Column.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/Table.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup/Index.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup/Unique.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/Pg.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/Sybase.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/mysql.pm,
+ DBIx-DBSchema-0.23-5.005kludge/t/load-mysql.t,
+ DBIx-DBSchema-0.23-5.005kludge/t/load-pg.t,
+ DBIx-DBSchema-0.23-5.005kludge/t/load.t: removing old 5.005
+ install stuff
+
+2007-03-07 11:48 khoff
+
+ * FS/FS/: Conf.pm, cust_main.pm: Option to disable the charging of
+ the setup fee while a package is suspended.
+
+2007-03-06 11:56 ivan
+
+ * bin/slony-setup: slight update for slony setup script
+
+2007-03-05 17:59 ivan
+
+ * httemplate/search/cust_main.cgi: fix status colors in mozilla
+
+2007-03-05 15:01 jayce
+
+ * FS/FS/part_pkg/base_delayed.pm: Typo in the package name caused a
+ warning. Fixed.
+
+2007-03-05 11:48 khoff
+
+ * httemplate/search/report_cust_bill.html: Fixed a problem with the
+ %opts hash getting skewed (specifically $opt{'value'} == 'label')
+ when $cgi->param('agentnum') was unset.
+
+2007-03-02 17:29 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.cgi: pass the remote IP
+ address along with signup requests, for some gateways
+
+2007-03-02 15:48 ivan
+
+ * FS/FS/cust_main.pm: eProcessingNetwork returning an authorization
+ like "AUTH/TKT 123456"... will this make refunds work?
+
+2007-03-01 22:24 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: fix custom priority fields,
+ whew
+
+2007-03-01 12:56 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: better match for toll-free prefixes
+
+2007-03-01 12:12 ivan
+
+ * FS/FS/Misc/prune.pm: yeah, a typo
+
+2007-03-01 09:48 ivan
+
+ * FS/bin/: freeside-prune-applications, freeside-upgrade:
+ prune_applications moved to FS::Misc::prune
+
+2007-03-01 09:47 ivan
+
+ * FS/FS/Misc/prune.pm: adding FS::Misc::prune
+
+2007-03-01 09:44 ivan
+
+ * FS/FS/Misc.pm: fix weird compliation problem for quis, i hope
+
+2007-03-01 08:36 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm: turn off debugging
+
+2007-02-28 21:24 jeff
+
+ * FS/FS/cust_credit.pm: dangling cust_credit_refund not allowed
+
+2007-02-28 21:13 jeff
+
+ * FS/: FS/Misc.pm, bin/freeside-prune-applications,
+ bin/freeside-upgrade: dangling cust_credit_refund not allowed
+
+2007-02-28 17:26 ivan
+
+ * FS/FS/Conf.pm: this isn't necessary around a single db operation
+
+2007-02-28 11:14 jeff
+
+ * httemplate/: edit/cust_main/select-domain.html,
+ misc/svc_acct-domains.cgi: restore (none) choice to first package
+ select
+
+2007-02-27 16:16 jayce
+
+ * FS/MANIFEST: Added base_rate files
+
+2007-02-27 15:59 jayce
+
+ * FS/FS/part_pkg/base_delayed.pm: adaptation of flat_delayed to
+ work with base_rate billing
+
+2007-02-27 14:10 jeff
+
+ * httemplate/config/config-download.cgi: put the C in ACL here, too
+
+2007-02-27 13:24 jeff
+
+ * FS/bin/freeside-setup: oops - inappropriate localization was
+ committed
+
+2007-02-26 17:51 jeff
+
+ * httemplate/config/config.cgi: config goes in database
+
+2007-02-26 17:48 jeff
+
+ * FS/MANIFEST, FS/FS/Conf.pm, FS/FS/UID.pm, FS/FS/conf.pm,
+ FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ FS/bin/freeside-init-config, FS/bin/freeside-setup,
+ FS/bin/freeside-upgrade, FS/t/conf.t, conf/invoice_latex,
+ httemplate/config/config-download.cgi,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, FS/FS/Schema.pm: config goes
+ in database
+
+2007-02-26 09:54 jeff
+
+ * htetc/handler.pl, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi: agent_type selector on new
+ packages
+
+2007-02-24 19:08 ivan
+
+ * FS/: FS/Conf.pm, bin/freeside-selfservice-server: add
+ selfservice-ignore_quantity flag
+
+2007-02-22 23:47 ivan
+
+ * FS/FS/Cron/bill.pm: take the package-def defined action here,
+ like freeside-prepaidd
+
+2007-02-21 03:26 ivan
+
+ * FS/FS/: Schema.pm, svc_acct.pm, part_export/shellcommands.pm: add
+ a _password_encoding field
+
+2007-02-20 18:53 jeff
+
+ * FS/FS/part_export/prizm.pm: work around a claimed 50 char limit,
+ and correct a description handling bug
+
+2007-02-19 07:40 ivan
+
+ * FS/FS/cust_bill.pm: this should fix Can't call method "part_pkg"
+ on an undefined value at .../cust_bill.pm line 434
+
+2007-02-16 14:06 ivan
+
+ * bin/rotate-cdrs: commiting this quick tool, cvs is complaining
+
+2007-02-16 12:54 jeff
+
+ * httemplate/misc/svc_acct-domains.cgi: respect svc_acct-alldomains
+ setting
+
+2007-02-16 12:21 jeff
+
+ * FS/FS/: Record.pm, svc_broadband.pm: coordinates can be negative
+ (deja vu?)
+
+2007-02-16 11:46 jayce
+
+ * FS/FS/part_pkg/base_rate.pm: Added a new Plan type, base_rate,
+ which uses the cust_pkg->options to control pricing. You assign
+ a base rate for charging, and it is multiplied by the 'units'
+ ordered. Solves a need where a company wants to offer an ASP
+ style service, that charges per user, at a base cost, but doesn't
+ want a plan for every combination of user amounts.
+
+2007-02-15 12:18 khoff
+
+ * FS/FS/cust_main.pm: *** ERROR: unterminated L<...> at line 4716
+ in file FS/cust_main.pm
+
+2007-02-14 17:09 ivan
+
+ * httemplate/docs/billing.html: removing docs moved to wiki
+
+2007-02-14 16:49 ivan
+
+ * httemplate/edit/part_bill_event.cgi: add send_email event
+
+2007-02-14 16:48 ivan
+
+ * conf/invoice_html: remove commented-out example notes section
+
+2007-02-14 15:32 jeff
+
+ * httemplate/: edit/cust_main/select-domain.html,
+ edit/cust_main.cgi, misc/svc_acct-domains.cgi: selectable domain
+ on first package in edit/cust_main
+
+2007-02-14 14:43 ivan
+
+ * httemplate/search/report_receivables.cgi: fix alignment on
+ receivables report
+
+2007-02-14 13:23 ivan
+
+ * httemplate/search/report_cust_pkg.html: grey out disabled text
+ boxes for IE
+
+2007-02-14 00:48 ivan
+
+ * httemplate/elements/select-cust_pkg-status.html,
+ httemplate/elements/tr-input-beginning_ending.html,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/search/report_cust_pkg.html, FS/FS/UI/Web.pm,
+ httemplate/images/calendar-disabled.png: add more options to
+ advanced package reporting
+
+2007-02-13 19:12 jeff
+
+ * FS/FS/: Conf.pm, Cron/notify.pm: add simple scalars to
+ impending_recur_notification
+
+2007-02-13 17:43 ivan
+
+ * httemplate/search/svc_www.cgi: fix up svc_www searching
+
+2007-02-13 16:19 jeff
+
+ * FS/FS/Conf.pm: better docs for impending doom
+
+2007-02-13 14:24 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: accept domsvc in selfservice
+ orders, patch from Sean Hanson/S1
+
+2007-02-13 14:08 ivan
+
+ * httemplate/edit/process/cust_main.cgi: use a domsvc when passed
+ in, patch from Sean Hanson/S1
+
+2007-02-12 21:00 jayce
+
+ * httemplate/edit/payment_gateway.html: Small hint on how the
+ options field is used.
+
+2007-02-12 17:16 jeff
+
+ * httemplate/edit/cust_main.cgi: another place to alphabetize
+
+2007-02-12 16:45 jeff
+
+ * FS/bin/freeside-delete-addr_blocks: for dumping addr_blocks
+
+2007-02-12 09:56 jeff
+
+ * FS/FS/ClientAPI/Signup.pm,
+ httemplate/view/cust_main/order_pkg.html: alpha sort packages in
+ new package order SELECT (ticket 1446)
+
+2007-02-11 19:11 ivan
+
+ * FS/FS/Misc.pm: fix unterminated L<...> in POD docs
+
+2007-02-11 00:51 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/myaccount_menu.html: we're at
+ now now
+
+2007-02-10 23:04 ivan
+
+ * FS/FS/UI/Web.pm: fix bug with customer info not showing up if
+ "cust-fields" config value has been set
+
+2007-02-09 22:13 ivan
+
+ * FS/FS/svc_acct.pm, FS/FS/svc_phone.pm,
+ httemplate/edit/part_svc.cgi: reincorporate the changes from
+ http://www.sisd.com/cgi-bin/viewcvs.cgi/freeside/httemplate/edit/part_svc.cgi?r1=1.52&r2=1.53
+ that were lost due to the concurrent service-refactor merge
+
+2007-02-09 16:42 ivan
+
+ * httemplate/misc/change_pkg.cgi: REALLY fix the package changing
+ this time
+
+2007-02-09 15:29 ivan
+
+ * httemplate/misc/change_pkg.cgi: fix change package link
+
+2007-02-08 20:54 ivan
+
+ * bin/import-county-tax-rates: quick hack to import rates for
+ landel
+
+2007-02-08 20:37 jayce
+
+ * httemplate/view/cust_main/packages.html: Set the correct access
+ right for the cancel link to work
+
+2007-02-08 17:05 ivan
+
+ * conf/: invoice_html_statement, invoice_latex_statement,
+ invoice_latexnotes_statement, invoice_template_statement: add
+ default statement conf
+
+2007-02-08 14:54 ivan
+
+ * FS/FS/part_export/sqlradius.pm: slightly less cryptic docs for
+ groups_susp_reason option
+
+2007-02-08 14:19 ivan
+
+ * FS/FS/cust_pkg.pm: use a LIMIT to retreive the first record,
+ don't rely on qsearchs to trim it for you - it is inefficient and
+ outputs long verbose warnings
+
+2007-02-08 14:08 ivan
+
+ * httemplate/pref/pref-process.html: second "my" localizing the
+ variable and causing password changes to fail
+
+2007-02-08 09:00 jeff
+
+ * FS/FS/svc_acct.pm, httemplate/edit/part_svc.cgi: fix usergroup in
+ edit/part_svc.cgi
+
+2007-02-08 08:04 jeff
+
+ * httemplate/edit/part_pkg.cgi: gratuitous quote
+
+2007-02-08 01:13 jeff
+
+ * htetc/handler.pl, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi: hold off until 1.7.2
+
+2007-02-08 00:19 ivan
+
+ * FS/FS/CGI.pm: fix the popup progress bars, whew
+
+2007-02-07 17:46 jeff
+
+ * FS/FS/part_pkg.pm, htetc/handler.pl,
+ httemplate/elements/select-table.html,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi: agent type on package
+ add/edit (ticket 1446)
+
+2007-02-06 16:46 ivan
+
+ * FS/FS/: cust_bill.pm, cust_pay.pm: only use new statements as
+ payment receipts if the conf file is created
+
+2007-02-05 15:48 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm: fix payment/credit
+ line-item application erroring out on tax applications
+
+2007-02-05 14:12 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm: turn debugging on until we
+ catch the Cant call method "part_pkg" on an undefined value at
+ /usr/local/share/perl/5.8.4/FS/cust_bill_ApplicationCommon.pm
+ line 181" bug
+
+2007-02-05 09:21 ivan
+
+ * FS/FS/: cust_pay_batch.pm, pay_batch.pm: move the due_events
+ import too... whew! this should be it
+
+2007-02-05 08:01 ivan
+
+ * FS/FS/pay_batch.pm: fix param passing
+
+2007-02-05 07:49 ivan
+
+ * httemplate/misc/upload-batch.cgi: fix st00pid mistakes in batch
+ upload
+
+2007-02-05 07:48 ivan
+
+ * httemplate/misc/upload-batch.cgi: misterminated <%init>
+
+2007-02-05 07:02 ivan
+
+ * FS/FS/pay_batch.pm: remove refactored code
+
+2007-02-05 05:11 ivan
+
+ * httemplate/search/svc_Smart.html: remove unused svc_Smart
+
+2007-02-05 05:10 ivan
+
+ * httemplate/search/: report_receivables.cgi,
+ report_receivables.html: add "over X days" option to receivables
+ report
+
+2007-02-05 04:51 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/view/cust_bill-logo.cgi,
+ httemplate/view/cust_bill-pdf.cgi,
+ httemplate/view/cust_bill-ps.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_Common.html, httemplate/view/svc_acct.cgi,
+ httemplate/view/svc_broadband.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_external.cgi,
+ httemplate/view/svc_forward.cgi, httemplate/view/svc_www.cgi,
+ httemplate/view/cust_main/contacts.html,
+ httemplate/view/elements/svc_Common.html: C is for
+ Cookie^WControl
+
+2007-02-05 03:35 ivan
+
+ * FS/FS/CGI.pm: not supporting Apache::ASP anymore
+
+2007-02-05 03:12 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: show RADIUS usage from last bill to
+ NOW, instead of last bill to next bill
+
+2007-02-05 01:45 ivan
+
+ * httemplate/misc/download-batch.cgi: upon first download, have
+ batches auto-set amount to customer balance if it is smaller
+
+2007-02-05 01:44 ivan
+
+ * FS/FS/Record.pm, FS/FS/cust_main.pm, FS/FS/cust_pay_batch.pm,
+ FS/FS/pay_batch.pm, httemplate/misc/upload-batch.cgi: move
+ cust_pay_batch::upload results subroutine to an FS::pay_batch
+ method. upon first download, have batches auto-reset their
+ amounts to the customer balance upon if it is smaller.
+
+2007-02-03 17:47 ivan
+
+ * httemplate/: search/cust_pay_batch.cgi,
+ view/cust_main/payment_history.html: add link to some batched
+ payment info to customer view
+
+2007-02-03 16:01 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: quieter
+
+2007-02-03 05:05 ivan
+
+ * FS/FS/cust_pkg.pm: this should fix services with negative
+ num_avail showing up for provisioning
+
+2007-02-03 04:07 ivan
+
+ * FS/FS/cust_main_Mixin.pm: remove debugging left on
+
+2007-02-03 03:36 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/ConfDefaults.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_Mixin.pm, FS/FS/UI/Web.pm,
+ httemplate/elements/menu.html,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/money_time.cgi,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/graph/report_money_time.html,
+ httemplate/search/cdr.html, httemplate/search/cust_bill.html,
+ httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_bill_event.html,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_main-otaker.cgi,
+ httemplate/search/cust_main-zip.html,
+ httemplate/search/cust_main.cgi,
+ httemplate/search/cust_main.html, httemplate/search/cust_pay.cgi,
+ httemplate/search/cust_pay_batch.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/cust_svc.html,
+ httemplate/search/cust_tax_exempt_pkg.cgi,
+ httemplate/search/inventory_item.html,
+ httemplate/search/pay_batch.cgi,
+ httemplate/search/pay_batch.html, httemplate/search/queue.html,
+ httemplate/search/reg_code.html,
+ httemplate/search/report_cdr.html,
+ httemplate/search/report_cust_bill.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_main-zip.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_cust_pay_batch.html,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/search/report_prepaid_income.cgi,
+ httemplate/search/report_prepaid_income.html,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/report_receivables.html,
+ httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html, httemplate/search/sql.html,
+ httemplate/search/sqlradius.cgi,
+ httemplate/search/sqlradius.html, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_broadband.cgi,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_external.cgi,
+ httemplate/search/svc_forward.cgi,
+ httemplate/search/svc_phone.cgi, httemplate/search/svc_www.cgi:
+ add customer status column to customer & most other reports.
+ also put the C in ACL in the search/ and graph/ directories.
+
+2007-02-02 18:39 jeff
+
+ * FS/bin/freeside-reset-fixed: do a setfixed
+
+2007-02-01 22:29 ivan
+
+ * FS/FS/part_pkg/flat.pm: quiet a harmless but loud warning
+
+2007-02-01 20:39 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: set resellser-specific advertising
+ sources in signup
+
+2007-01-31 19:08 jeff
+
+ * httemplate/view/cust_main/packages.html: oops. perhaps it should
+
+2007-01-31 18:37 jeff
+
+ * FS/FS/svc_acct.pm: spurious line
+
+2007-01-31 18:35 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: fix up the info passing for optional
+ packages
+
+2007-01-31 18:13 jeff
+
+ * FS/FS/: svc_acct.pm, part_export/sqlradius.pm: better solution to
+ ticket 1455
+
+2007-01-31 17:57 ivan
+
+ * FS/FS/cust_bill.pm: eliminate \\* in the cheesy latex->html notes
+ thing
+
+2007-01-31 10:28 jeff
+
+ * FS/FS/part_export/sqlradius.pm: possible solution to ticket 1455
+
+2007-01-30 22:30 khoff
+
+ * FS/FS/part_export/snmp.pm: Don't break if we're missing
+ Net::SNMP. Apparenty "require" doesn't do the trick.
+
+2007-01-30 21:45 khoff
+
+ * FS/FS/part_export/nas_wrapper.pm: Meta-export to allow more
+ flexibilty until the export subsystem rewrite.
+
+2007-01-30 21:43 khoff
+
+ * FS/FS/part_export/: router.pm, snmp.pm, trango.pm:
+ FS::part_export::router - Refactored to be more easily
+ sub-classed. - Moved per-export options to FS:;router virtual
+ fields. - Fixed other general brokenness.
+
+ FS::part_export::snmp - SNMP export sub-classed from
+ FS::part_export::router
+
+ FS::part_export::trango - Export for Trango proprietary access
+ points. Sub-classed from FS::part_export::snmp.
+
+2007-01-30 21:23 jeff
+
+ * FS/FS/cust_main.pm: minor improvement
+
+2007-01-30 20:30 jeff
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/misc/process/payment.cgi: small change in payment
+ receipt handling (ticket 1422)
+
+2007-01-30 20:26 ivan
+
+ * httemplate/: edit/quick-charge.html,
+ elements/select-taxclass.html, elements/tr-select-taxclass.html,
+ view/cust_main/packages.html: minor UI work on one-time charges
+ w/taxclasses
+
+2007-01-30 19:42 jeff
+
+ * FS/: MANIFEST, t/cust_pkg_option.t: odds and ends
+
+2007-01-30 18:08 ivan
+
+ * httemplate/misc/change_pkg.cgi: this should be a popup too, but,
+ until then, it shouldn't be missing the standard header
+
+2007-01-30 15:50 ivan
+
+ * FS/FS/cust_bill.pm: fix agent-specific logos in emailed html
+ invoices
+
+2007-01-30 13:21 jeff
+
+ * FS/FS/svc_acct.pm: avoiding brane pane
+
+2007-01-30 12:59 ivan
+
+ * httemplate/: browse/access_group.html, browse/access_user.html,
+ browse/addr_block.cgi, browse/agent.cgi, browse/agent_type.cgi,
+ browse/cust_main_county.cgi, browse/inventory_class.html,
+ browse/msgcat.cgi, browse/part_bill_event.cgi,
+ browse/part_export.cgi, browse/part_pkg.cgi,
+ browse/part_referral.html, browse/part_svc.cgi,
+ browse/part_virtual_field.cgi, browse/payment_gateway.html,
+ browse/pkg_class.html, browse/rate.cgi, browse/reason.html,
+ browse/reason_type.html, browse/router.cgi,
+ browse/svc_acct_pop.cgi, edit/msgcat.cgi,
+ search/prepay_credit.html: its all about control
+
+2007-01-30 11:45 ivan
+
+ * FS/FS/option_Common.pm: fix old-record detection bug in
+ option_Common
+
+2007-01-30 11:40 jeff
+
+ * FS/FS/: Conf.pm, svc_acct.pm, cust_main.pm: only add first user
+ to invoicing_list (ticket 1424)
+
+2007-01-30 10:52 jeff
+
+ * fs_selfservice/FS-SelfService/cgi/success-delayed.html,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi: additional info
+ available for self-service success (ticket 1420)
+
+2007-01-29 15:16 ivan
+
+ * httemplate/config/: config-process.cgi, config-view.cgi,
+ config.cgi: putting the C in ACL
+
+2007-01-29 13:11 ivan
+
+ * httemplate/misc/process/cancel_pkg.html: correct a typo, and
+ <%init> helps alot
+
+2007-01-29 10:50 ivan
+
+ * httemplate/pref/: pref-process.html, pref.html: record resolution
+ & colro depth in user prefs
+
+2007-01-29 08:16 ivan
+
+ * FS/FS/: cust_main.pm, rate.pm: turn off debugging
+
+2007-01-29 08:01 ivan
+
+ * FS/FS/: cust_main.pm, cust_main_Mixin.pm, UI/Web.pm: fix invoice
+ email display bug on advanced package report, closes: Bug#1416
+
+2007-01-29 04:07 ivan
+
+ * htetc/handler.pl: warnings in <%once> sections should not be
+ fatal
+
+2007-01-29 03:55 ivan
+
+ * FS/FS/option_Common.pm: remove extraneous debugging
+
+2007-01-29 03:31 ivan
+
+ * Makefile: looks like a duck
+
+2007-01-27 18:21 ivan
+
+ * FS/FS/svc_domain.pm, httemplate/view/svc_domain.cgi: pretty up
+ domain zone viewing a little
+
+2007-01-26 00:18 ivan
+
+ * FS/FS/access_user.pm: out of scope bad
+
+2007-01-26 00:17 ivan
+
+ * FS/FS/access_user.pm: spurious password changes bad...
+
+2007-01-26 00:11 ivan
+
+ * FS/FS/: Record.pm, option_Common.pm: oops, debugging turned on
+
+2007-01-26 00:04 ivan
+
+ * FS/FS/access_user.pm, httemplate/elements/header.html,
+ httemplate/elements/menu.html, httemplate/elements/xmenu.css,
+ httemplate/elements/xmenu.top.css,
+ httemplate/elements/xmenu.top.js,
+ httemplate/images/arrow.down.png,
+ httemplate/images/menu-left-example.png,
+ httemplate/images/menu-top-example.png,
+ httemplate/pref/pref-process.html, httemplate/pref/pref.html,
+ FS/FS/Record.pm, FS/FS/m2m_Common.pm, FS/FS/option_Common.pm: top
+ bar option!
+
+2007-01-24 22:04 ivan
+
+ * httemplate/elements/xmenu.css: fuck. you. IE7.
+
+2007-01-24 22:00 ivan
+
+ * httemplate/elements/: menu.html, xmenu.css: fuck. you. IE7.
+
+2007-01-24 15:41 ivan
+
+ * httemplate/misc/download-batch.cgi: 00 = sale, 01 = pre-auth. we
+ need the former
+
+2007-01-23 21:33 jeff
+
+ * httemplate/edit/process/elements/process.html: squarely between
+ shame in you and so close
+
+2007-01-23 15:42 jeff
+
+ * FS/FS.pm, FS/bin/freeside-daily, conf/impending_recur_template,
+ FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/cust_pkg_option.pm,
+ FS/FS/Cron/notify.pm, FS/FS/part_pkg/flat_delayed.pm: notices
+ before first charge on flat_delayed
+
+2007-01-22 23:44 ivan
+
+ * FS/FS/cust_pay_batch.pm: even have 4 digit zips in there eek
+
+2007-01-22 22:51 ivan
+
+ * FS/FS/Record.pm: remove spurious duplicateion from lineitem patch
+
+2007-01-22 22:45 ivan
+
+ * FS/FS/payby.pm: fix PREP payby
+
+2007-01-22 22:41 ivan
+
+ * FS/FS/cust_pay.pm: have to use payinfo_Mixin if we're going to
+ ISA it
+
+2007-01-22 09:05 ivan
+
+ * Makefile, htetc/freeside-base1.99.conf: halfass v2 too
+
+2007-01-22 06:29 ivan
+
+ * FS/FS/CGI.pm: hopefully this should be the last bit of the
+ relative URL fixing
+
+2007-01-22 03:41 ivan
+
+ * httemplate/view/cust_main.cgi: closing tags helps alot
+
+2007-01-22 03:39 ivan
+
+ * httemplate/view/: cust_main.cgi, cust_main/notes.html: fix
+ elements/ links here too
+
+2007-01-22 03:36 ivan
+
+ * httemplate/elements/: phonenumber.html, progress-init.html,
+ progress-popup.html, tr-input-beginning_ending.html,
+ tr-input-date-field.html: interpolation helps alot
+
+2007-01-22 03:30 ivan
+
+ * httemplate/elements/: phonenumber.html, progress-init.html,
+ progress-popup.html, tr-input-beginning_ending.html,
+ tr-input-date-field.html: use $fsurl instead of relative ../
+ addressing
+
+2007-01-21 18:42 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html: accept CVV2
+ on self-service manual payment screen
+
+2007-01-21 13:45 ivan
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_ApplicationCommon.pm, FS/FS/cust_bill_pay.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_credit_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/part_bill_event.pm, FS/FS/part_pkg.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/ClientAPI/Signup.pm,
+ FS/FS/Cron/bill.pm, httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/cust_main.cgi, httemplate/misc/bill.cgi:
+ Have lineitem-specific applications happen in all cases; add
+ weightsto control
+
+2007-01-21 05:42 ivan
+
+ * rt/: FREESIDE_MODIFIED, lib/RT/SearchBuilder.pm: add dependancy
+ on DBIx::SB 1.36 for Pg 8.1+
+
+2007-01-21 05:26 ivan
+
+ * Makefile, htetc/freeside-base.conf, htetc/freeside-base1.conf,
+ htetc/freeside-base2.conf: mod_perl v2, it finally happened
+
+2007-01-21 01:13 ivan
+
+ * httemplate/search/cust_svc.html: trim leading & trailing
+ whitespace from service searches
+
+2007-01-21 01:10 ivan
+
+ * FS/FS/: CGI.pm, UI/Web.pm: fix svc_url to work no matter where we
+ are coming from in the tree - use rooturl() instead of popurl()
+
+2007-01-19 16:08 jeff
+
+ * httemplate/edit/process/quick-charge.cgi: strip all blank lines,
+ not just trailing ones
+
+2007-01-19 15:00 jeff
+
+ * httemplate/misc/download-batch.cgi: work around CSV brokenness
+
+2007-01-19 14:02 jeff
+
+ * httemplate/edit/process/: access_user.html,
+ elements/process.html: blank password on error
+
+2007-01-19 08:31 jeff
+
+ * httemplate/edit/: access_user.html, process/access_user.html,
+ process/elements/process.html: no password in html source on
+ employee edit
+
+2007-01-18 10:14 ivan
+
+ * FS/FS/cust_pay_batch.pm: fix zip parsing for batch results -
+ don't want to abort processing because of an old not-well-checked
+ zip
+
+2007-01-17 15:28 ivan
+
+ * FS/FS/part_export/shellcommands.pm: fix crypted password bug
+ cause by recent fix to not quote things on STDIN, yuck.
+
+2007-01-17 15:27 jeff
+
+ * httemplate/edit/svc_acct.cgi, httemplate/misc/change_pkg.cgi,
+ httemplate/misc/payment.cgi,
+ httemplate/view/elements/svc_Common.html, FS/FS/CGI.pm,
+ httemplate/misc/process/payment.cgi,
+ httemplate/view/svc_acct.cgi: link to customer from manual
+ payment screen (ticket 1414)
+
+2007-01-17 09:41 jeff
+
+ * FS/FS/: cust_pkg.pm, reason.pm: fix bug wrt suspend/cancel
+ reasons (suspends fail in freeside-daily)
+
+2007-01-17 08:41 jeff
+
+ * FS/FS/part_pkg/flat.pm: noise reduction
+
+2007-01-17 07:50 jeff
+
+ * httemplate/view/cust_main/packages.html: fix suspend link
+
+2007-01-16 16:40 jeff
+
+ * httemplate/edit/: access_user.html, process/access_user.html:
+ employee edit (ticket 1412)
+
+2007-01-16 13:36 jeff
+
+ * rt/: FREESIDE_MODIFIED, etc/schema.Pg: revert unnecessary changes
+ for ticket 1364
+
+2007-01-16 09:39 jeff
+
+ * rt/: FREESIDE_MODIFIED, etc/schema.Pg: RT vs Pg8 (ticket 1364)
+
+2007-01-16 01:11 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: have signup package list respect
+ agentnum sent from client
+
+2007-01-15 14:15 jeff
+
+ * httemplate/edit/process/quick-charge.cgi: that was DUM
+
+2007-01-14 23:53 ivan
+
+ * httemplate/misc/download-batch.cgi: add batch expiration date
+ incrementer for 295
+
+2007-01-14 23:22 ivan
+
+ * FS/FS/Conf.pm: add descriptions for batchconfig-PAP and
+ batchconfig-csv-chase_canada-E-xactBatch
+
+2007-01-12 15:27 jeff
+
+ * FS/FS/Schema.pm, FS/FS/svc_broadband.pm,
+ httemplate/view/svc_broadband.cgi, FS/FS/part_export/prizm.pm,
+ httemplate/edit/svc_broadband.cgi: added svc_broadband
+ description which is appended to Site Name in prizm export
+
+2007-01-11 18:04 jeff
+
+ * FS/FS/cust_main.pm, FS/FS/part_pkg/flat.pm,
+ httemplate/edit/quick-charge.html,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/view/cust_main/packages.html: one-time charge
+ enhancements
+
+2007-01-10 15:21 ivan
+
+ * httemplate/search/queue.html: add "select all" and "unselect" all
+ buttons to bulk queue operations
+
+2007-01-10 00:56 ivan
+
+ * FS/FS/payinfo_Mixin.pm: fix harmless warning: Use of
+ uninitialized value in string ne at
+ /usr/local/share/perl/5.8.4/FS/payinfo_Mixin.pm line 116
+
+2007-01-10 00:50 ivan
+
+ * httemplate/view/cust_main/contacts.html: you have got to be
+ kidding me.
+
+2007-01-10 00:48 ivan
+
+ * httemplate/view/cust_main/contacts.html: nothing could have ever
+ gone wrong with so simple a change. oh noooo
+
+2007-01-09 23:48 ivan
+
+ * httemplate/view/cust_main/contacts.html: fix ship_county display
+ bug
+
+2007-01-09 21:51 ivan
+
+ * FS/FS/cust_bill.pm: add custnum to invoice template vars
+
+2007-01-09 18:41 jeff
+
+ * FS/FS/cust_pay_batch.pm: E-xactBatch masks card numbers
+
+2007-01-09 16:42 jeff
+
+ * httemplate/: misc/upload-batch.cgi, search/cust_pay_batch.cgi:
+ ignore filenames and rely on selected batch number
+
+2007-01-09 16:41 jeff
+
+ * httemplate/misc/download-batch.cgi: permit batch redownloads
+
+2007-01-09 14:57 ivan
+
+ * FS/FS/Schema.pm: 2147483647 should be enough bytes for anyone!
+
+2007-01-08 09:36 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/cust_credit_refund.pm,
+ FS/FS/cust_pay_refund.pm, FS/FS/cust_refund.pm,
+ httemplate/misc/delete-cust_refund.cgi,
+ httemplate/view/cust_main/payment_history.html: refund deletion
+
+2007-01-05 16:47 jeff
+
+ * httemplate/edit/part_svc.cgi: fix UI funkiness
+
+2007-01-04 21:19 jeff
+
+ * fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/view_usage.html,
+ FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/change_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/provision_list.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_usage_details.html: more
+ self-servicey stuff (change package, detailed usage)
+
+2007-01-03 23:26 ivan
+
+ * conf/blank_logo.eps: adding a simple blank logo; people are
+ trying to comment out stuff in the template
+
+2007-01-03 21:49 ivan
+
+ * httemplate/edit/part_bill_event.cgi: invoice event to credit out
+ a customer's balance, presumably as bad debt
+
+2007-01-03 11:47 ivan
+
+ * httemplate/view/cust_main/packages.html: fix suspend link
+
+2007-01-02 13:46 ivan
+
+ * FS/FS/UI/Web.pm, httemplate/search/cust_svc.html: fix service
+ searching & links
+
+2007-01-02 13:44 ivan
+
+ * FS/FS/cust_main.pm: stupid semicolon!
+
+2007-01-02 13:06 ivan
+
+ * FS/FS/cust_main.pm: fix num_pkgs to accept empty $sql param, no
+ trailing AND
+
+2007-01-02 12:29 ivan
+
+ * httemplate/view/cust_main/packages.html: fix popup target links
+
+2007-01-02 12:25 ivan
+
+ * httemplate/view/svc_Common.html: missing from svc patch, oops!
+
+2007-01-02 10:38 jeff
+
+ * FS/FS/svc_acct.pm: omit spurious export triggering
+
+2006-12-29 13:48 jeff
+
+ * httemplate/: elements/select-agent.html,
+ graph/report_cust_bill_pkg.html: correct bad include, and improve
+ no agent selected condition
+
+2006-12-29 00:51 ivan
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm, FS/FS/part_svc.pm,
+ FS/FS/pkg_svc.pm, FS/FS/registrar.pm, FS/FS/svc_Common.pm,
+ FS/FS/svc_External_Common.pm, FS/FS/svc_Parent_Mixin.pm,
+ FS/FS/svc_acct.pm, FS/FS/svc_broadband.pm, FS/FS/svc_domain.pm,
+ FS/FS/svc_external.pm, FS/FS/svc_forward.pm, FS/FS/svc_phone.pm,
+ FS/FS/svc_www.pm, FS/FS/UI/Web.pm, FS/t/registrar.t,
+ FS/t/svc_External_Common.t, FS/t/svc_Parent_Mixin.t,
+ eg/table_template-svc.pm, httemplate/browse/part_svc.cgi,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_Common.html,
+ httemplate/edit/svc_acct.cgi, httemplate/edit/svc_broadband.cgi,
+ httemplate/edit/svc_domain.cgi, httemplate/edit/svc_external.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/edit/svc_www.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/elements/svc_Common.html,
+ httemplate/edit/process/elements/process.html, FS/MANIFEST,
+ httemplate/edit/process/svc_Common.html,
+ httemplate/elements/header.html, httemplate/elements/menu.html,
+ httemplate/misc/link.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_svc.html, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_broadband.cgi,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_external.cgi,
+ httemplate/search/svc_forward.cgi,
+ httemplate/search/svc_phone.cgi, httemplate/search/svc_www.cgi,
+ httemplate/view/elements/svc_Common.html,
+ rt/html/Elements/FreesideSearch,
+ rt/html/Elements/FreesideSvcSearch,
+ httemplate/view/cust_main/packages.html: service refactor!
+
+2006-12-29 00:41 ivan
+
+ * httemplate/edit/process/cust_main.cgi: slight pedanticism
+
+2006-12-29 00:39 ivan
+
+ * httemplate/edit/svc_broadband.cgi: svc broadband new arg parsing
+
+2006-12-29 00:35 ivan
+
+ * httemplate/misc/: payment.cgi, process/payment.cgi: just in case
+ it gets capitalized
+
+2006-12-29 00:34 ivan
+
+ * httemplate/edit/process/quick-charge.cgi: whitespace
+
+2006-12-29 00:34 ivan
+
+ * httemplate/edit/cust_main/billing.html: slight more space
+ necessary for ACH account numbers
+
+2006-12-29 00:31 ivan
+
+ * init.d/freeside-init: kill off all queued processes!
+
+2006-12-29 00:30 ivan
+
+ * httemplate/docs/index.html: link more docs to wiki
+
+2006-12-29 00:29 ivan
+
+ * httemplate/browse/pay_batch.cgi: this is unused, replaced by
+ search/pay_batch.cgi
+
+2006-12-29 00:25 ivan
+
+ * FS/FS/part_export/vpopmail.pm: didn't get checked in with
+ configurable target dirs, oops
+
+2006-12-29 00:25 ivan
+
+ * FS/FS/svc_Common.pm: doc
+
+2006-12-29 00:24 ivan
+
+ * FS/FS/part_pkg.pm: snot spacing
+
+2006-12-29 00:24 ivan
+
+ * FS/FS/part_export.pm: use FS::queue for exports, though they
+ should probably just use it themselves
+
+2006-12-29 00:21 ivan
+
+ * Changelog, Changes.1.5.7, Changes.1.5.8: removing old changelogs
+
+2006-12-29 00:20 ivan
+
+ * Changes.1.7.0: changelog now in the wiki
+
+2006-12-28 23:23 ivan
+
+ * httemplate/edit/elements/edit.html: document field types
+
+2006-12-28 16:30 jeff
+
+ * FS/FS/part_export/prizm.pm: minor fixups
+
+2006-12-28 12:52 jeff
+
+ * httemplate/elements/tr-select-reason.html: activate submit button
+ more readily
+
+2006-12-28 00:16 ivan
+
+ * FS/FS/payinfo_Mixin.pm: tyop
+
+2006-12-27 23:02 ivan
+
+ * bin/pg-version: adding pg-version
+
+2006-12-26 19:29 ivan
+
+ * httemplate/edit/cust_main_county-expand.cgi: fix sanity check on
+ taxclass expander
+
+2006-12-26 18:37 ivan
+
+ * FS/FS/Misc.pm, htetc/handler.pl,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/edit/cust_main/select-county.html,
+ httemplate/misc/counties.cgi: Add a (magically appearing and
+ disappearing) label on the county selector. confusing when
+ labeled "state"
+
+2006-12-26 17:35 ivan
+
+ * httemplate/view/cust_main/contacts.html: show county on customer
+ view
+
+2006-12-26 17:07 ivan
+
+ * httemplate/: edit/cust_main.cgi,
+ edit/cust_main/select-county.html, misc/counties.cgi: fix county
+ selector
+
+2006-12-26 11:53 ivan
+
+ * FS/FS/part_export/shellcommands.pm: do shell_quote-ing after
+ STDIN strings are evaluated
+
+2006-12-23 17:28 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/cust_pay.pm, FS/FS/cust_pay_void.pm,
+ FS/FS/cust_refund.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/view/cust_main/payment_history.html: fix more paymask
+ regressions: allow editing records with existing expired cards,
+ fix masking just-entered values when erroring out, fix echeck
+ entry inserting as empty routing code and "xxEK" account number,
+ remove old/deprecated/unused payinfo_maksed subs and calls
+
+2006-12-22 21:37 jeff
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/svc_broadband.pm,
+ FS/FS/part_export/prizm.pm, httemplate/edit/svc_broadband.cgi,
+ httemplate/view/svc_broadband.cgi: inital prizm support
+
+2006-12-21 22:18 ivan
+
+ * httemplate/search/: queue.html, elements/search.html: patch
+ fixing "retry selected" and "remove select" in queue view
+
+2006-12-20 19:05 ivan
+
+ * httemplate/misc/payment.cgi: fix on-demand payment form when
+ making payments from masked data
+
+2006-12-20 02:51 ivan
+
+ * FS/FS/: cust_main.pm, payinfo_Mixin.pm: fix "recurring_billing"
+ flag for the wonderful new world of paymasking
+
+2006-12-20 01:49 ivan
+
+ * FS/FS/Schema.pm, FS/FS/pkg_class.pm,
+ httemplate/browse/pkg_class.html, httemplate/edit/pkg_class.html,
+ httemplate/elements/select-part_referral.html,
+ httemplate/elements/select-pkg_class.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-pkg_class.html,
+ httemplate/search/elements/search.html: add ability to disable
+ package classes
+
+2006-12-19 17:20 jeff
+
+ * FS/FS/: part_pkg.pm, ClientAPI/MyAccount.pm: inappropriate
+ cluckage
+
+2006-12-19 02:02 ivan
+
+ * FS/FS/cust_pay_batch.pm, FS/FS/payby.pm, FS/FS/payinfo_Mixin.pm,
+ htetc/handler.pl, httemplate/edit/cust_main/billing.html,
+ httemplate/search/cust_pay.cgi: clean up payinfo_Mixin to use
+ payby.pm for payby info and have card masking full 6-digit BIN
+ prefix for card identification. have cust_pay_batch use
+ payinfo_Mixin. require B:CC 0.30 for mask-aware cardtype(). fix
+ payment reports to use mask too if available, so credit card type
+ selection still works with encryption.
+
+2006-12-18 03:01 ivan
+
+ * htetc/handler.pl, httemplate/edit/part_pkg.cgi: fix tax class not
+ adding when there is only one pkg_class choice (triggers
+ javascript error
+
+2006-12-18 00:08 ivan
+
+ * Makefile: fix MASONDATA include for dev target
+
+2006-12-15 12:55 ivan
+
+ * httemplate/elements/dashboard-toplist.html: add a new ticket link
+
+2006-12-15 05:09 ivan
+
+ * httemplate/elements/dashboard-toplist.html: add a quick start at
+ a "dashboard" customer list, mostly for internal use for starters
+
+2006-12-15 05:00 ivan
+
+ * httemplate/elements/dashboard-toplist.html: add a quick start at
+ a "dashboard" customer list, mostly for internal use for starters
+
+2006-12-15 04:43 ivan
+
+ * FS/FS/Conf.pm, httemplate/index.html,
+ httemplate/elements/dashboard-toplist.html: add a quick start at
+ a "dashboard" customer list, mostly for internal use for starters
+
+2006-12-15 00:37 ivan
+
+ * FS/FS/Setup.pm, bin/expand-country: add a quick tool for adding
+ states to old databases
+
+2006-12-15 00:25 ivan
+
+ * httemplate/edit/: cust_main.cgi, cust_main/billing.html:
+ eliminate funkiness with reappearing "Postal invoice" on errors
+
+2006-12-14 21:29 jeff
+
+ * htetc/handler.pl, httemplate/edit/process/cust_main.cgi,
+ httemplate/elements/tr-input-date-field.html,
+ httemplate/view/cust_main/misc.html: move use statements to
+ handler.pl, do not show 1/1/70 for new birthdates, and improve
+ error handling
+
+2006-12-14 16:56 ivan
+
+ * httemplate/edit/process/cust_main.cgi, htetc/handler.pl: add
+ DateTime as a proper rather than hidden dependency
+
+2006-12-14 16:28 ivan
+
+ * Makefile, FS/bin/freeside-addoutsource,
+ FS/bin/freeside-deloutsource, FS/bin/freeside-queued,
+ FS/bin/freeside-selfservice-server,
+ FS/bin/freeside-sqlradius-radacctd, htetc/handler.pl: tiny bit of
+ cleanup from the conf merge
+
+2006-12-14 01:27 ivan
+
+ * Makefile, FS/FS/Conf.pm, FS/FS/UID.pm, FS/FS/access_user.pm,
+ FS/FS/part_export/vpopmail.pm, FS/bin/freeside-addoutsource,
+ FS/bin/freeside-addoutsourceuser, FS/bin/freeside-adduser,
+ FS/bin/freeside-deloutsource, FS/bin/freeside-deloutsourceuser,
+ FS/bin/freeside-deluser, FS/bin/freeside-queued,
+ FS/bin/freeside-selfservice-server, FS/bin/freeside-setup,
+ FS/bin/freeside-sqlradius-radacctd, FS/bin/freeside-upgrade,
+ bin/dbdef-create, bin/mapsecrets2access_user, htetc/handler.pl:
+ make the config directory configurable
+
+2006-12-13 22:00 ivan
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pay_void.pm, FS/FS/cust_refund.pm,
+ FS/FS/payinfo_Mixin.pm, FS/FS/ClientAPI/MyAccount.pm,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/misc/payment.cgi, httemplate/misc/process/payment.cgi,
+ httemplate/search/cust_pay.cgi, FS/MANIFEST,
+ FS/t/payinfo_Mixin.t, httemplate/edit/cust_refund.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/view/cust_main/billing.html,
+ httemplate/view/cust_main/payment_history.html: encryption fixes
+ from huntsberg & jayce
+
+2006-12-08 07:11 jeff
+
+ * FS/FS/svc_acct.pm: stop unsuspending inappropriately
+
+2006-12-08 06:38 ivan
+
+ * rt/html/Elements/Header: have RT header link to supported
+ documentation link as well
+
+2006-12-08 05:36 ivan
+
+ * httemplate/: view/cust_main/quick-charge.html,
+ edit/process/quick-charge.cgi: some javascript validation magic
+ to give one-time charges better UI
+
+2006-12-07 08:46 ivan
+
+ * bin/pod2x: update pod2x for new self-service path
+
+2006-12-07 07:24 ivan
+
+ * FS/FS/Setup.pm: oops, fix additional US pseudo-states
+
+2006-12-06 18:40 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Record.pm, FS/FS/Schema.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/prepay_credit.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_broadband.pm, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/prorate.pm, FS/FS/part_pkg/subscription.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/process_order_recharge.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_usage.html,
+ httemplate/edit/prepay_credit.cgi,
+ httemplate/edit/process/prepay_credit.cgi,
+ httemplate/misc/process/recharge_svc.html,
+ httemplate/search/prepay_credit.html: retouch bandwidth countdown
+
+2006-12-05 07:53 jeff
+
+ * FS/FS/part_export/sqlmail.pm: correct longstanding oops
+
+2006-12-04 18:37 jeff
+
+ * httemplate/: edit/svc_acct.cgi, edit/process/svc_acct.cgi,
+ view/svc_acct.cgi: editable service usage
+
+2006-12-02 16:42 ivan
+
+ * FS/FS/cust_main.pm: clean up whitespace merge noise
+
+2006-12-02 14:04 ivan
+
+ * FS/FS/part_pkg/flat_comission.pm: fix for commission price plan
+
+2006-11-30 22:31 jeff
+
+ * FS/FS/Conf.pm, FS/FS/cust_pay_batch.pm,
+ httemplate/misc/download-batch.cgi,
+ httemplate/search/cust_pay_batch.cgi: chase canada E-xactBatch
+
+2006-11-30 17:41 ivan
+
+ * FS/bin/freeside-queued: remove unnecessary service use (in an
+ awfully odd place)
+
+2006-11-30 17:35 ivan
+
+ * FS/bin/freeside-expiration-alerter: go away and never come back,
+ $Id$
+
+2006-11-30 17:34 ivan
+
+ * FS/bin/freeside-email: begone $Id$ and your diff noise!
+
+2006-11-29 18:27 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/UI/Web.pm,
+ FS/FS/part_export/sqlradius.pm,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_usage.html,
+ httemplate/edit/prepay_credit.cgi,
+ httemplate/edit/process/prepay_credit.cgi,
+ httemplate/misc/recharge_svc.html,
+ httemplate/misc/process/recharge_svc.html,
+ httemplate/search/prepay_credit.html,
+ httemplate/view/cust_main/packages.html: prepaid download/upload
+ tracking
+
+2006-11-28 01:38 ivan
+
+ * FS/FS/access_user.pm: usernames should be alphanumeric only
+
+2006-11-26 23:11 jeff
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/process_order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: order package
+ from self-service
+
+2006-11-26 17:08 ivan
+
+ * FS/FS/svc_acct.pm: some svc_acct.pm fixes for s1
+
+2006-11-26 15:09 jeff
+
+ * httemplate/elements/menu.html: minor tyop
+
+2006-11-26 15:06 jeff
+
+ * httemplate/: edit/process/cust_main_note.cgi, view/cust_main.cgi,
+ view/cust_main/notes.html: more ajaxy customer notes
+
+2006-11-25 13:04 jeff
+
+ * httemplate/view/cust_main.cgi: chill FF wrt POSTDATA
+
+2006-11-24 02:34 ivan
+
+ * httemplate/browse/part_pkg.cgi: link to and label one-time
+ charges correctly
+
+2006-11-24 00:48 ivan
+
+ * httemplate/elements/tr-input-beginning_ending.html,
+ httemplate/elements/tr-input-lessthan_greaterthan.html,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_pay.html, FS/FS/UI/Web.pm: add less
+ than and greater than amounts to credit and payment searches
+
+2006-11-20 02:34 ivan
+
+ * httemplate/browse/agent.cgi: remove annoying black box around
+ override info
+
+2006-11-19 19:05 ivan
+
+ * httemplate/autohandler: bug fix for open transactions
+
+2006-11-17 18:19 jeff
+
+ * FS/FS/part_export/www_plesk.pm: add templating and web hosting
+ optional on domain addition
+
+2006-11-17 02:16 ivan
+
+ * FS/bin/freeside-prepaidd: initial fix for prepaid renewal
+ problem; attempt to use an existing credit/payment before
+ suspending
+
+2006-11-16 07:37 jeff
+
+ * httemplate/edit/process/part_bill_event.cgi: bug squishing
+
+2006-11-15 22:20 jeff
+
+ * httemplate/: elements/tr-input-date-field.html,
+ edit/cust_main.cgi, edit/process/cust_main.cgi,
+ view/cust_main/misc.html: switch birthdate to DateTime
+
+2006-11-14 04:22 ivan
+
+ * httemplate/misc/cust_main-import.cgi: add some docs on required
+ fields to page
+
+2006-11-13 20:04 ivan
+
+ * httemplate/: browse/agent.cgi,
+ misc/delete-agent_payment_gateway.cgi: working agent gateway
+ override delete link
+
+2006-11-13 19:30 ivan
+
+ * FS/FS/Misc.pm: Tie::IxHash data disappears when sent with
+ Storable
+
+2006-11-13 19:16 ivan
+
+ * FS/FS/Misc.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.html: have signup page
+ use card-types config too
+
+2006-11-13 18:54 ivan
+
+ * FS/FS/: Conf.pm, ClientAPI/MyAccount.pm: add card-types
+ configuration value for self-service
+
+2006-11-12 17:09 ivan
+
+ * FS/FS/CGI.pm, httemplate/elements/error.html,
+ httemplate/elements/header.html,
+ httemplate/pref/pref-process.html, httemplate/pref/pref.html: add
+ preference page, start with just a password changer
+
+2006-11-08 18:52 jeff
+
+ * FS/FS/TicketSystem/RT_External.pm: recorrect ticket order
+
+2006-11-08 18:28 jeff
+
+ * FS/FS/TicketSystem/RT_External.pm: correct ticket order
+
+2006-11-05 14:39 ivan
+
+ * Makefile: call it 1.7.1 to avoid confusion
+
+2006-11-05 14:28 ivan
+
+ * bin/: customer-faker, payment-faker: some sample data creators
+
+2006-11-05 11:34 ivan
+
+ * FS/FS/cust_main.pm: fix empty invoice number omitting in
+ realtime_bop, oops
+
+2006-11-05 11:22 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm: turn off debugging
+
+2006-11-05 10:06 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: for want of a
+ paren
+
+2006-11-05 10:03 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/selfservice.cgi: have card_type
+ be an optional param anyway
+
+2006-11-05 10:03 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix auto-population of card_type
+ SELECT in self-service payment form
+
+2006-11-05 09:36 ivan
+
+ * fs_selfservice/FS-SelfService/: SelfService.pm,
+ cgi/selfservice.cgi: add some self-service debugging
+
+2006-11-05 08:58 ivan
+
+ * FS/bin/freeside-selfservice-server: fix spurious disconnection
+ errors in selfservice server log
+
+2006-11-05 07:55 ivan
+
+ * httemplate/view/cust_main/payment_history.html: fix but with no
+ "show prior history" showing up when everything is hidden
+
+2006-11-03 14:02 ivan
+
+ * FS/FS/part_pkg.pm: add every 45 day option to available
+ frequencies
+
+2006-10-31 10:56 jeff
+
+ * FS/FS/part_export/sqlradius.pm: do not require a reason to have
+ been suspended
+
+2006-10-31 08:57 jeff
+
+ * httemplate/edit/process/cust_main_note.cgi: ugh, too restrictive
+
+2006-10-30 04:39 ivan
+
+ * FS/FS/cust_main.pm: realtime_bop: don't pass an empty
+ invoice_number to B:OP, omit the field entirely
+
+2006-10-29 17:28 ivan
+
+ * FS/MANIFEST: removing freeside-daily
+
+2006-10-29 16:26 ivan
+
+ * FS/bin/freeside-bill: removing pre-1.4 freeside-bill
+
+2006-10-27 12:10 ivan
+
+ * FS/FS/: Conf.pm, cust_pkg.pm: add
+ unsuspend-always_adjust_next_bill_date config option for qis
+
+2006-10-27 10:01 jeff
+
+ * FS/FS/AccessRight.pm, httemplate/edit/cust_main_note.cgi,
+ httemplate/edit/process/cust_main_note.cgi,
+ httemplate/elements/overlibmws_crossframe.js,
+ httemplate/view/cust_main/notes.html: editable notes
+
+2006-10-26 19:12 jeff
+
+ * FS/FS/part_export/: shellcommands.pm, sqlradius.pm: export
+ enhancements for suspend reasons
+
+2006-10-26 01:35 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.html: don't display a
+ (none) package selection if there's a default
+
+2006-10-25 11:10 jeff
+
+ * httemplate/view/cust_main/packages.html: show reasons
+
+2006-10-25 10:36 ivan
+
+ * httemplate/: elements/pager.html, search/cust_main.cgi,
+ search/elements/search.html: pagination patch from UNTD - limit
+ the number of page links displayed and have a drop-down option
+ for selecting number of entries per page
+
+2006-10-25 05:04 ivan
+
+ * conf/ticket_system: default to RT_Internal ticketing
+
+2006-10-24 21:51 jeff
+
+ * httemplate/elements/tr-selectmultiple-part_pkg.html: heh
+
+2006-10-24 21:44 jeff
+
+ * httemplate/: elements/tr-selectmultiple-part_pkg.html,
+ search/cust_pkg.cgi, search/report_cust_pkg.html: select multiple
+ pkgparts on advanced package report
+
+2006-10-24 20:12 jeff
+
+ * httemplate/: edit/svc_www.cgi, view/svc_www.cgi: no usersvc
+ svc_www tweak
+
+2006-10-24 19:22 jeff
+
+ * FS/FS/part_svc.pm, FS/FS/part_svc_column.pm,
+ httemplate/browse/part_svc.cgi, httemplate/edit/part_svc.cgi,
+ httemplate/edit/svc_acct.cgi: limited domain select
+
+2006-10-24 11:26 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ httemplate/view/cust_main/misc.html: add customer signup date
+
+2006-10-23 02:44 ivan
+
+ * httemplate/elements/menu.html: have the unlinked account search
+ go to UN_username so it doesn't miss accounts with no UID
+
+2006-10-23 02:35 ivan
+
+ * httemplate/elements/header.html: eek, VALIGN=top for the page
+
+2006-10-23 02:24 ivan
+
+ * FS/FS/cust_main.pm: always do substring & fuzzy, getting
+ complains searches are not returning enough
+
+2006-10-23 01:47 ivan
+
+ * httemplate/misc/process/cancel_pkg.html: better error message if
+ you don't enter a reason. FS::reason::check can untaint its
+ data, and will allow punctuation in reasons
+
+2006-10-23 01:30 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/: agent.cgi,
+ cust_bill-logo.cgi, passwd.cgi, selfservice.cgi, signup.html:
+ remove -w to prevent warnings from messing up otherwise working
+ CGIs
+
+2006-10-22 23:38 ivan
+
+ * FS/FS/Record.pm: add AU to list of zip-requiring countries
+
+2006-10-22 21:21 jeff
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ FS/FS/part_bill_event.pm, httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/reason.html,
+ httemplate/edit/process/part_bill_event.cgi,
+ httemplate/elements/tr-select-reason.html,
+ httemplate/misc/cancel_pkg.html,
+ httemplate/misc/process/cancel_pkg.html: events should attach
+ reasons
+
+2006-10-22 18:47 ivan
+
+ * httemplate/view/cust_main/packages.html: fix regression from
+ table re-layout: don't display provision links for cancelled
+ packages
+
+2006-10-22 04:42 ivan
+
+ * FS/FS/Conf.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi: add signup server
+ default package
+
+2006-10-21 22:22 ivan
+
+ * FS/FS/part_pkg/prepaid.pm: doh, forgot fieldorder. should just
+ use Tie::IxHash here too
+
+2006-10-21 22:18 ivan
+
+ * FS/: FS/part_pkg/prepaid.pm, bin/freeside-prepaidd: add price
+ plan option for prepaid packages to cancel instead of suspend
+
+2006-10-21 17:35 ivan
+
+ * httemplate/elements/menu.html: link to wrong place
+
+2006-10-20 15:49 ivan
+
+ * FS/FS/part_pkg.pm: add 48-hour billing
+
+2006-10-19 07:32 jeff
+
+ * FS/FS/Conf.pm: [no log message]
+
+2006-10-19 07:29 jeff
+
+ * FS/FS/cust_pkg_reason.pm: suspension and cancellation reasons
+
+2006-10-19 07:26 jeff
+
+ * httemplate/elements/tr-select-reason.html,
+ httemplate/misc/cancel_pkg.cgi, httemplate/misc/cancel_pkg.html,
+ httemplate/misc/expire_pkg.cgi,
+ httemplate/misc/process/cancel_pkg.html,
+ httemplate/misc/process/expire_pkg.cgi,
+ httemplate/misc/susp_pkg.cgi, FS/t/cust_pkg_reason.t: suspension
+ and cancellation reasons
+
+2006-10-19 07:23 jeff
+
+ * FS/FS/cancel_reason.pm, FS/FS/reason.pm, FS/FS/reason_type.pm,
+ FS/t/cancel_reason.t, FS/t/reason.t, FS/t/reason_type.t,
+ httemplate/browse/reason.html,
+ httemplate/browse/reason_type.html,
+ httemplate/edit/process/reason.html,
+ httemplate/edit/process/reason_type.html,
+ httemplate/edit/reason.html, httemplate/edit/reason_type.html:
+ suspension and cancellation reasons
+
+2006-10-18 21:41 jeff
+
+ * FS/FS/part_export/acct_plesk.pm: wrong method
+
+2006-10-18 16:07 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Schema.pm, FS/FS/part_bill_event.pm,
+ FS/MANIFEST, htetc/handler.pl,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/process/part_bill_event.cgi,
+ httemplate/elements/menu.html,
+ httemplate/view/cust_main/packages.html: suspension and
+ cancellation reasons
+
+2006-10-18 02:30 ivan
+
+ * httemplate/docs/: config.html, export.html: removing obsolete
+ config.html, moving info from export.html into wiki
+
+2006-10-17 17:05 jeff
+
+ * httemplate/elements/tr-input-date-field.html: fix ugly null dates
+
+2006-10-17 02:03 ivan
+
+ * rt/: html/Elements/Header, html/Elements/CollectionAsTable/Row,
+ html/NoAuth/webrt.css, sbin/rt-setup-database.in: commiting rt
+ 3.4.5 to HEAD
+
+2006-10-17 01:49 ivan
+
+ * rt/: html/NoAuth/printrt.css, lib/t/regression/14linking.t,
+ lib/t/regression/22search_tix_by_watcher.t: Initial revision
+
+2006-10-16 22:49 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: fix signup problem
+ on IE, whew!
+
+2006-10-16 10:59 ivan
+
+ * FS/FS/Record.pm: fix for agent_custid unique bs ('violates unique
+ constraint cust_main18'), hope this doesn't break anything else
+
+2006-10-16 10:13 ivan
+
+ * httemplate/: edit/cust_main.cgi, view/cust_main/misc.html: its
+ not my monday morning
+
+2006-10-16 10:11 ivan
+
+ * FS/FS/Conf.pm: closing bracket helps
+
+2006-10-16 10:10 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi,
+ httemplate/view/cust_main/misc.html: add a conf checkbox to turn
+ DOB on
+
+2006-10-16 09:56 ivan
+
+ * httemplate/edit/cust_main.cgi: fix stickiness bug when editing
+ advertising sources
+
+2006-10-15 19:21 ivan
+
+ * FS/FS/part_export/: acct_plesk.pm, www_plesk.pm: fix typo
+ switching Net::Plesk to a run-time dependency
+
+2006-10-14 16:53 ivan
+
+ * FS/FS/part_export/: acct_plesk.pm, www_plesk.pm: don't load
+ Net::Plesk until its needed, to prevent every install from
+ depending on it
+
+2006-10-14 13:47 jeff
+
+ * FS/FS/part_export/: acct_plesk.pm, www_plesk.pm: preliminary
+ plesk support
+
+2006-10-14 03:09 ivan
+
+ * httemplate/search/report_receivables.cgi: that should fix
+ statuses on receivables report
+
+2006-10-14 02:55 ivan
+
+ * httemplate/docs/: index.html, selfservice.html: move
+ signup/self-service install to wiki
+
+2006-10-12 02:42 ivan
+
+ * FS/FS/cust_main.pm: fix "amatch: $_ is undefined: what are you
+ matching" error when there are no companies in the fuzzy cache
+ yet
+
+2006-10-08 22:05 ivan
+
+ * FS/FS/Conf.pm: date selektah
+
+2006-10-08 21:27 jeff
+
+ * httemplate/edit/process/cust_main.cgi: more BoD
+
+2006-10-08 18:05 ivan
+
+ * FS/bin/: freeside-addoutsource, freeside-addoutsourceuser,
+ freeside-adduser: update the tools for dev installs
+
+2006-10-08 17:30 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main.cgi: have the new style
+ notes be the default
+
+2006-10-08 17:26 ivan
+
+ * httemplate/view/: cust_main.cgi, cust_main/tickets.html: clean up
+ the customer view a tiny bit
+
+2006-10-08 17:13 ivan
+
+ * htetc/handler.pl: add cust_main_note to handler.pl
+
+2006-10-08 01:17 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/Schema.pm,
+ FS/FS/Setup.pm, FS/FS/cust_bill.pm, FS/FS/pay_batch.pm,
+ FS/FS/payby.pm, bin/customer-faker, htetc/handler.pl,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/elements/menu.html,
+ httemplate/search/cust_pay_batch.cgi,
+ httemplate/search/pay_batch.cgi,
+ httemplate/search/elements/search.html: add menu items for credit
+ card batching, debug last-minute changes to payby.pm, add ACL for
+ re-processing batches, separate CARD and CHEK batches, fixed
+ defaults for batch formats
+
+2006-10-07 16:40 ivan
+
+ * FS/FS/cust_bill.pm: remove a spurious commit from batch_card and
+ document realtime option
+
+2006-10-07 14:40 ivan
+
+ * FS/FS/cust_main.pm: better error msg on CSV import with bad
+ pkgpart
+
+2006-10-04 14:22 jeff
+
+ * FS/FS/Schema.pm, FS/FS/cust_main.pm, FS/FS/Conf.pm,
+ FS/FS/Record.pm, httemplate/edit/cust_main.cgi,
+ httemplate/elements/tr-input-date-field.html,
+ httemplate/view/cust_main/misc.html: DoB
+
+2006-10-03 15:44 jeff
+
+ * FS/FS/AccessRight.pm, FS/FS/Conf.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_note.pm, FS/MANIFEST, FS/FS/Schema.pm,
+ FS/t/cust_main_note.t, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_note.cgi,
+ httemplate/edit/process/cust_main_note.cgi,
+ httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/notes.html: Enhanced customer notes
+
+2006-10-03 08:59 ivan
+
+ * FS/FS/: cust_main_invoice.pm, cust_pay_batch.pm, svc_external.pm,
+ svc_www.pm: s/repalce/replace/ in POD doc
+
+2006-09-29 10:22 ivan
+
+ * FS/FS/access_user.pm: fix problem with viewing unlinked services
+
+2006-09-29 09:18 ivan
+
+ * FS/FS/part_export/domain_sql.pm: precedence error causing schema
+ mapped values to disappear
+
+2006-09-29 08:36 ivan
+
+ * FS/FS/part_export/domain_sql.pm: fix mapping problem in
+ domain_sql export
+
+2006-09-28 10:45 ivan
+
+ * FS/FS/svc_acct.pm: missing $ in ldap_password
+
+2006-09-26 11:55 ivan
+
+ * httemplate/search/: svc_Smart.html, svc_acct.cgi: fix
+ username@domain search
+
+2006-09-23 11:33 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/acct_sql.pm: update to
+ mailserver integration
+
+2006-09-20 21:41 ivan
+
+ * FS/FS/part_export/acct_sql.pm: support static values in acct_sql
+ as well
+
+2006-09-20 09:00 ivan
+
+ * FS/FS/part_export/acct_sql.pm: eek, terminate the javascript
+
+2006-09-20 08:20 ivan
+
+ * FS/FS/part_export/acct_sql.pm: finish correcting the naming
+
+2006-09-20 08:19 ivan
+
+ * FS/FS/part_export/domain_sql.pm: tie correctly!
+
+2006-09-19 09:49 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/acct_sql.pm,
+ part_export/domain_sql.pm: add domain_sql export for new
+ mailserver config and modify acct_sql export for same
+
+2006-09-17 19:21 ivan
+
+ * httemplate/elements/menu.html: ticket system disableability for
+ rainbowshops
+
+2006-09-16 13:07 ivan
+
+ * bin/customer-faker: bulk fake customer insert
+
+2006-09-15 12:15 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/search/cust_tax_exempt_pkg.cgi,
+ httemplate/view/cust_main/payment_history.html: add link to
+ customer tax exemptions to customer view page
+
+2006-09-14 22:10 ivan
+
+ * FS/FS/: Schema.pm, cust_bill_ApplicationCommon.pm,
+ cust_bill_pay_pkg.pm, cust_credit_bill_pkg.pm: add sdate and
+ edate to cust_bill_pay_pkg and cust_credit_bill_pkg tables
+
+2006-09-14 12:33 ivan
+
+ * httemplate/edit/part_virtual_field.cgi: don't promise virtual
+ fields on tables we can't deliver them on. virtual fields suck
+ anyway, they should be real database fields
+
+2006-09-14 12:30 ivan
+
+ * httemplate/edit/process/generic.cgi: pointer to
+ elements/process.html, fwiw
+
+2006-09-13 09:01 ivan
+
+ * httemplate/search/report_cust_pay.html: add check # search, here
+ for now...
+
+2006-09-13 07:57 ivan
+
+ * FS/FS/cust_bill_ApplicationCommon.pm: yes, that does appear to be
+ the fix for all this trouble. s/qsearchs/qsearch/
+
+2006-09-13 07:53 ivan
+
+ * FS/FS/: cust_credit.pm, cust_pay.pm: some cleanup while i'm here
+
+2006-09-12 19:14 ivan
+
+ * FS/FS/Record.pm: encryption-on-insert bugfix from untd
+
+2006-09-12 19:11 ivan
+
+ * FS/FS/svc_Common.pm: in-place replace bugfix from untd &
+ debugging cleanup
+
+2006-09-12 14:27 ivan
+
+ * httemplate/search/cust_main.cgi: no need to log this
+
+2006-09-05 18:20 ivan
+
+ * bin/breakdown-bill-applications: not done yet
+
+2006-09-05 18:08 ivan
+
+ * fs_selfservice/DEPLOY: this was supposed to just be a local hack,
+ how did it wind up in CVS?
+
+2006-09-05 18:08 ivan
+
+ * FS/bin/freeside-setup: new world ACLs
+
+2006-09-05 18:07 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: less cut and paste
+
+2006-09-05 18:07 ivan
+
+ * FS/FS/payby.pm: ugh DCLN :/
+
+2006-09-05 18:06 ivan
+
+ * FS/FS/cust_svc.pm: add some debugging
+
+2006-09-05 18:06 ivan
+
+ * FS/FS/cdr.pm: add missing =back
+
+2006-09-05 09:44 ivan
+
+ * httemplate/edit/process/cust_refund.cgi: fix refunds, really
+
+2006-09-05 09:27 ivan
+
+ * httemplate/edit/process/cust_refund.cgi: fix FS::payby::payby2bop
+ usage
+
+2006-09-04 13:31 ivan
+
+ * httemplate/search/sqlradius.cgi: really fix the embedded duration
+ table
+
+2006-09-04 13:22 ivan
+
+ * httemplate/search/sqlradius.cgi: use the exact provided time
+
+2006-09-04 13:15 ivan
+
+ * httemplate/search/sqlradius.cgi: fix the date/time parsing
+
+2006-09-04 13:12 ivan
+
+ * httemplate/search/sqlradius.cgi: fix the embedded duration table
+
+2006-09-04 13:10 ivan
+
+ * httemplate/search/sqlradius.cgi: fix the gridding colors
+
+2006-09-04 13:05 ivan
+
+ * httemplate/: elements/tr-input-beginning_ending.html,
+ search/sqlradius.cgi, search/sqlradius.html: allow time selection
+ in RADIUS searches and grid-ize the resulting table
+
+2006-09-04 09:24 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/elements/menu.html: add RADIUS
+ session search back to main menu
+
+2006-09-02 20:14 ivan
+
+ * bin/dbdef-create: REALLY don't error out trying to create a dbdef
+ file from scratch
+
+2006-09-02 20:12 ivan
+
+ * bin/dbdef-create: don't error out trying to create a dbdef file
+ from scratch
+
+2006-09-02 13:38 ivan
+
+ * httemplate/search/: cust_bill_event.cgi, cust_bill_event.html:
+ agent-virtualize invoice event reports
+
+2006-09-01 00:52 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.html: pretty this up a
+ little
+
+2006-08-31 18:51 lawrence
+
+ * FS/FS/Conf.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.html: Progress
+ checkpoint on improved signup stuff for additional services
+
+2006-08-31 14:26 lawrence
+
+ * httemplate/config/config-process.cgi: make select-sub parameters
+ work
+
+2006-08-31 13:47 ivan
+
+ * eg/TEMPLATE_cust_main.import, etc/megapop.pl: BEGONE $Id
+
+2006-08-31 13:44 ivan
+
+ * bin/: svc_acct.import, svc_domain.erase: BEGONE $Id$
+
+2006-08-31 13:44 ivan
+
+ * bin/svc_acct.export: removing obsolete file
+
+2006-08-31 12:59 ivan
+
+ * bin/fs-migrate-svc_acct_sm: BEGONE $Id$
+
+2006-08-31 12:25 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.cgi: BEGONE $Id$
+
+2006-08-30 09:24 ivan
+
+ * bin/mapsecrets2access_user: need a username arg for now... this
+ should make the error message less confusing
+
+2006-08-30 08:41 ivan
+
+ * FS/bin/freeside-adduser: get rid of all the htpasswd stuff in
+ freeside-adduser
+
+2006-08-29 11:04 khoff
+
+ * FS/FS/part_pkg/flat_introrate.pm: Introductory rates...just what
+ we always wanted. Requires Date::Manip.
+
+2006-08-29 10:50 lawrence
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html: Signup
+ Enhancements
+
+2006-08-28 06:52 ivan
+
+ * httemplate/edit/process/cust_main.cgi: parameters to method calls
+ require ( ), arrgh
+
+2006-08-27 17:52 jeff
+
+ * FS/FS/cust_bill.pm: protect against a race
+
+2006-08-27 15:55 jeff
+
+ * Makefile: more clean
+
+2006-08-27 14:50 jeff
+
+ * FS/FS/cust_bill.pm, FS/FS/payby.pm,
+ httemplate/misc/process/payment.cgi: fix payby2bop brokenness
+
+2006-08-27 13:10 jeff
+
+ * FS/FS/cust_pay_batch.pm: no comment
+
+2006-08-27 13:09 jeff
+
+ * FS/FS/payby.pm: oops
+
+2006-08-27 12:33 ivan
+
+ * FS/FS/AccessRight.pm, httemplate/elements/menu.html: add back
+ invoice event reports
+
+2006-08-27 12:30 jeff
+
+ * httemplate/: edit/cust_bill_pay.cgi, edit/cust_credit.cgi,
+ edit/cust_credit_bill.cgi, misc/download-batch.cgi: correct bad
+ conflict resolution
+
+2006-08-26 16:15 jeff
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/Setup.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_event.pm, FS/FS/cust_bill_pay_batch.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pay_batch.pm,
+ FS/FS/part_bill_event.pm, FS/FS/payby.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/ClientAPI/Signup.pm,
+ FS/t/cust_bill_pay_batch.t, httemplate/browse/cust_pay_batch.cgi,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/cust_refund.cgi,
+ httemplate/misc/bill.cgi, httemplate/misc/download-batch.cgi,
+ httemplate/misc/process/payment.cgi,
+ httemplate/search/cust_pay_batch.cgi,
+ httemplate/search/pay_batch.cgi,
+ httemplate/search/pay_batch.html,
+ httemplate/search/report_cust_pay_batch.html: batch refactor
+ continued
+
+2006-08-26 07:44 ivan
+
+ * FS/FS/Schema.pm: better error reporting for schema load failures
+ (w/DBIx::DBSchema 0.32+), hopefully...
+
+2006-08-26 07:39 ivan
+
+ * FS/FS/Schema.pm: better error reporting for schema load failures
+ (w/DBIx::DBSchema 0.32+), hopefully...
+
+2006-08-26 05:57 ivan
+
+ * httemplate/edit/: cust_bill_pay.cgi, cust_credit_bill.cgi: fix
+ javascript for auto-setting application amount
+
+2006-08-25 19:20 ivan
+
+ * httemplate/edit/cust_bill_pay.cgi: fix javascript for
+ auto-setting application amount
+
+2006-08-25 19:20 ivan
+
+ * htetc/handler.pl: i want max and min!
+
+2006-08-25 19:12 ivan
+
+ * FS/FS/: Record.pm: foiled by autovivification!
+
+2006-08-25 12:30 ivan
+
+ * FS/FS/Misc.pm, FS/FS/Record.pm,
+ httemplate/edit/cust_main/select-country.html,
+ httemplate/edit/cust_main/select-county.html,
+ httemplate/edit/cust_main/select-state.html: use GROUP BY instead
+ of DISTINCT ON in the state and country queries for better
+ cross-database compatibility, based on a preliminary patch from
+ Jason Thomas
+
+2006-08-23 18:37 ivan
+
+ * httemplate/edit/: cust_credit.cgi, cust_pay.cgi: oops,
+ "Auto-apply to invoices" dropdown disappeared
+
+2006-08-23 15:25 ivan
+
+ * Makefile, httemplate/index.html,
+ httemplate/browse/access_group.html,
+ httemplate/browse/access_user.html,
+ httemplate/browse/addr_block.cgi, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/cust_pay_batch.cgi,
+ httemplate/browse/inventory_class.html,
+ httemplate/browse/msgcat.cgi, httemplate/browse/nas.cgi,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/browse/part_export.cgi,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.html,
+ httemplate/browse/part_svc.cgi,
+ httemplate/browse/part_virtual_field.cgi,
+ httemplate/browse/payment_gateway.html,
+ httemplate/browse/pkg_class.html, httemplate/browse/rate.cgi,
+ httemplate/browse/router.cgi, httemplate/browse/svc_acct_pop.cgi,
+ httemplate/browse/elements/browse.html,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/docs/trouble.html, httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/access_group.html,
+ httemplate/edit/access_user.html, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_payment_gateway.html,
+ httemplate/edit/agent_type.cgi,
+ httemplate/edit/bulk-cust_svc.html,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/cust_refund.cgi,
+ httemplate/edit/inventory_class.html, httemplate/edit/msgcat.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_export.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_referral.html, httemplate/edit/part_svc.cgi,
+ httemplate/edit/part_virtual_field.cgi,
+ httemplate/edit/payment_gateway.html,
+ httemplate/edit/pkg_class.html,
+ httemplate/edit/prepay_credit.cgi, httemplate/edit/rate.cgi,
+ httemplate/edit/rate_region.cgi, httemplate/edit/reg_code.cgi,
+ httemplate/edit/router.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_broadband.cgi,
+ httemplate/edit/svc_domain.cgi, httemplate/edit/svc_external.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/edit/svc_phone.cgi,
+ httemplate/edit/svc_www.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/edit/cust_main/select-country.html,
+ httemplate/edit/cust_main/select-county.html,
+ httemplate/edit/cust_main/select-state.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/elements/svc_Common.html,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/edit/process/access_group.html,
+ httemplate/edit/process/access_user.html,
+ httemplate/edit/process/agent.cgi,
+ httemplate/edit/process/agent_payment_gateway.html,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/bulk-cust_svc.cgi,
+ httemplate/edit/process/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/cust_main_county-collapse.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/edit/process/cust_refund.cgi,
+ httemplate/edit/process/cust_svc.cgi,
+ httemplate/edit/process/domain_record.cgi,
+ httemplate/edit/process/generic.cgi,
+ httemplate/edit/process/inventory_class.html,
+ httemplate/edit/process/msgcat.cgi,
+ httemplate/edit/process/part_bill_event.cgi,
+ httemplate/edit/process/part_export.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/part_referral.html,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/edit/process/payment_gateway.html,
+ httemplate/edit/process/pkg_class.html,
+ httemplate/edit/process/prepay_credit.cgi,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/edit/process/rate.cgi,
+ httemplate/edit/process/rate_region.cgi,
+ httemplate/edit/process/reg_code.cgi,
+ httemplate/edit/process/router.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/svc_broadband.cgi,
+ httemplate/edit/process/svc_domain.cgi,
+ httemplate/edit/process/svc_external.cgi,
+ httemplate/edit/process/svc_forward.cgi,
+ httemplate/edit/process/svc_phone.html,
+ httemplate/edit/process/svc_www.cgi,
+ httemplate/edit/process/addr_block/add.cgi,
+ httemplate/edit/process/addr_block/allocate.cgi,
+ httemplate/edit/process/addr_block/deallocate.cgi,
+ httemplate/edit/process/addr_block/split.cgi,
+ httemplate/edit/process/elements/process.html,
+ httemplate/edit/process/elements/svc_Common.html,
+ httemplate/elements/checkboxes-table-name.html,
+ httemplate/elements/checkboxes-table.html,
+ httemplate/elements/header-popup.html,
+ httemplate/elements/header.html,
+ httemplate/elements/jsrsServer.html,
+ httemplate/elements/menu.html, httemplate/elements/menubar.html,
+ httemplate/elements/pager.html,
+ httemplate/elements/phonenumber.html,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/progress-popup.html,
+ httemplate/elements/search-cust_main.html,
+ httemplate/elements/select-access_group.html,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-cust-fields.html,
+ httemplate/elements/select-cust_pkg-status.html,
+ httemplate/elements/select-month_year.html,
+ httemplate/elements/select-part_referral.html,
+ httemplate/elements/select-pkg_class.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/select-taxclass.html,
+ httemplate/elements/small_custview.html,
+ httemplate/elements/table-grid.html,
+ httemplate/elements/table.html,
+ httemplate/elements/tr-select-access_group.html,
+ httemplate/elements/tr-select-agent.html,
+ httemplate/elements/tr-select-cust-fields.html,
+ httemplate/elements/tr-select-cust_pkg-status.html,
+ httemplate/elements/tr-select-from_to.html,
+ httemplate/elements/tr-select-part_referral.html,
+ httemplate/elements/tr-select-pkg_class.html,
+ httemplate/elements/xmlhttp.html,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/money_time.cgi,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/graph/report_money_time.html,
+ httemplate/graph/elements/monthly.html,
+ httemplate/misc/batch-cust_pay.html, httemplate/misc/bill.cgi,
+ httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/cancel_pkg.cgi, httemplate/misc/catchall.cgi,
+ httemplate/misc/cdr-import.html, httemplate/misc/change_pkg.cgi,
+ httemplate/misc/counties.cgi,
+ httemplate/misc/cust_main-cancel.cgi,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/cust_main-import_charges.cgi,
+ httemplate/misc/delete-cust_credit.cgi,
+ httemplate/misc/delete-cust_pay.cgi,
+ httemplate/misc/delete-customer.cgi,
+ httemplate/misc/delete-domain_record.cgi,
+ httemplate/misc/delete-part_export.cgi,
+ httemplate/misc/download-batch.cgi, httemplate/misc/dump.cgi,
+ httemplate/misc/email-invoice.cgi,
+ httemplate/misc/email_invoice_events.cgi,
+ httemplate/misc/email_invoices.cgi,
+ httemplate/misc/expire_pkg.cgi, httemplate/misc/fax-invoice.cgi,
+ httemplate/misc/fax_invoice_events.cgi,
+ httemplate/misc/fax_invoices.cgi,
+ httemplate/misc/inventory_item-import.html,
+ httemplate/misc/link.cgi, httemplate/misc/meta-import.cgi,
+ httemplate/misc/payment.cgi, httemplate/misc/print-invoice.cgi,
+ httemplate/misc/print_invoice_events.cgi,
+ httemplate/misc/print_invoices.cgi, httemplate/misc/queue.cgi,
+ httemplate/misc/states.cgi, httemplate/misc/susp_pkg.cgi,
+ httemplate/misc/unapply-cust_credit.cgi,
+ httemplate/misc/unapply-cust_pay.cgi,
+ httemplate/misc/unprovision.cgi, httemplate/misc/unsusp_pkg.cgi,
+ httemplate/misc/unvoid-cust_pay_void.cgi,
+ httemplate/misc/upload-batch.cgi,
+ httemplate/misc/void-cust_pay.cgi, httemplate/misc/whois.cgi,
+ httemplate/misc/xmlhttp-cust_main-search.cgi,
+ httemplate/misc/xmlrpc.cgi,
+ httemplate/misc/process/batch-cust_pay.cgi,
+ httemplate/misc/process/catchall.cgi,
+ httemplate/misc/process/cdr-import.html,
+ httemplate/misc/process/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import_charges.cgi,
+ httemplate/misc/process/delete-customer.cgi,
+ httemplate/misc/process/expire_pkg.cgi,
+ httemplate/misc/process/inventory_item-import.html,
+ httemplate/misc/process/link.cgi,
+ httemplate/misc/process/meta-import.cgi,
+ httemplate/misc/process/payment.cgi, httemplate/search/cdr.html,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_bill_event.html,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_main-otaker.cgi,
+ httemplate/search/cust_main-zip.html,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pay.cgi,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/search/cust_tax_exempt_pkg.cgi,
+ httemplate/search/inventory_item.html,
+ httemplate/search/prepay_credit.html,
+ httemplate/search/queue.html, httemplate/search/reg_code.html,
+ httemplate/search/report_cdr.html,
+ httemplate/search/report_cust_bill.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_main-zip.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/search/report_prepaid_income.cgi,
+ httemplate/search/report_prepaid_income.html,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/report_receivables.html,
+ httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html, httemplate/search/sql.html,
+ httemplate/search/sqlradius.cgi,
+ httemplate/search/sqlradius.html,
+ httemplate/search/svc_Smart.html, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_broadband.cgi,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_external.cgi,
+ httemplate/search/svc_forward.cgi,
+ httemplate/search/svc_phone.cgi, httemplate/search/svc_www.cgi,
+ httemplate/search/elements/search.html,
+ httemplate/view/cust_bill-logo.cgi,
+ httemplate/view/cust_bill-pdf.cgi,
+ httemplate/view/cust_bill-ps.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_broadband.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_external.cgi,
+ httemplate/view/svc_forward.cgi, httemplate/view/svc_phone.cgi,
+ httemplate/view/svc_www.cgi,
+ httemplate/view/cust_main/billing.html,
+ httemplate/view/cust_main/contacts.html,
+ httemplate/view/cust_main/misc.html,
+ httemplate/view/cust_main/order_pkg.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/quick-charge.html,
+ httemplate/view/cust_main/tickets.html,
+ httemplate/view/elements/svc_Common.html: Will things ever be the
+ same again? It's the final masonize
+
+2006-08-23 14:53 ivan
+
+ * httemplate/misc/batch-cust_pay.html: remove extraneous "
+
+2006-08-23 05:13 ivan
+
+ * FS/FS/Schema.pm: removing already commented-out code
+
+2006-08-23 05:06 ivan
+
+ * Makefile, FS/FS/CGI.pm: don't use FREESIDE_URL for this, it
+ didn't work out...
+
+2006-08-22 05:23 ivan
+
+ * httemplate/docs/: index.html, upgrade-1.4.2.html, upgrade10.html,
+ upgrade9.html: get rid of old upgrade instructions
+
+2006-08-22 05:20 ivan
+
+ * README.1.7.0: wiki!
+
+2006-08-22 05:09 ivan
+
+ * README.1.5.0pre6, README.1.5.7, README.1.5.7.lastbit,
+ README.1.5.8: removing old upgrade instructions... can always
+ get the out of the Attic
+
+2006-08-21 16:01 ivan
+
+ * FS/: MANIFEST, FS/Schema.pm, FS/cust_bill.pm,
+ FS/cust_bill_ApplicationCommon.pm, FS/cust_bill_pay.pm,
+ FS/cust_bill_pay_pkg.pm, FS/cust_bill_pkg.pm,
+ FS/cust_credit_bill.pm, FS/cust_credit_bill_pkg.pm,
+ t/cust_bill_ApplicationCommon.t, t/cust_bill_pay_pkg.t,
+ t/cust_credit_bill_pkg.t: add cust_bill_pay_pkg and
+ cust_credit_bill_pkg - applying credits and payments against
+ specific line items
+
+2006-08-21 10:45 ivan
+
+ * FS/FS/: cust_main.pm: search for existing advertising sources
+ before adding a new one
+
+2006-08-21 05:38 ivan
+
+ * rt/html/Ticket/Elements/EditCustomers: better RT hint for smarter
+ smart search
+
+2006-08-21 02:46 ivan
+
+ * httemplate/docs/: install-rt.html, install.html, index.html:
+ we're off to see the wiki, the wonderful wiki of oz
+
+2006-08-18 05:18 ivan
+
+ * FS/FS/cust_main.pm: and a slight fix to the CSV import
+
+2006-08-18 04:56 ivan
+
+ * FS/FS/cust_main.pm: pass through the explicitly specified pkeys
+
+2006-08-18 04:52 ivan
+
+ * FS/FS/cust_main.pm: alas, now try with recursion
+
+2006-08-18 04:40 ivan
+
+ * FS/FS/cust_main.pm: fix the explicitly specified primary keys
+
+2006-08-18 04:36 ivan
+
+ * FS/FS/cust_main.pm: allow explicitly specified primary keys (to
+ get around big 8.1 Pg changes wrt reverse engineering
+
+2006-08-18 03:34 ivan
+
+ * FS/FS/cust_main.pm: suggestion to run dbdef-create here, yes...
+
+2006-08-18 03:31 ivan
+
+ * FS/FS/cust_main.pm: want ALL of cust_main-skeleton tables config,
+ not just the first line
+
+2006-08-18 03:27 ivan
+
+ * FS/FS/cust_main.pm: that was it, the sql had to be fixed...
+
+2006-08-18 03:26 ivan
+
+ * FS/FS/cust_main.pm: W T F
+
+2006-08-18 03:18 ivan
+
+ * FS/FS/cust_main.pm: even more skeleton debugging, ugh
+
+2006-08-18 03:10 ivan
+
+ * FS/FS/cust_main.pm: what's going on with the parameters for
+ skeleton inserts??
+
+2006-08-18 03:00 ivan
+
+ * FS/FS/cust_main.pm: skeleton typo
+
+2006-08-18 02:58 ivan
+
+ * FS/FS/cust_main.pm: oops, want CHILD table for skeleton inserts,
+ not parent
+
+2006-08-18 02:50 ivan
+
+ * FS/FS/cust_main.pm: add debugging to _copy_skel to get some idea
+ what's going on
+
+2006-08-18 01:33 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: first try at skeleton feature for
+ mg
+
+2006-08-16 01:19 ivan
+
+ * FS/bin/freeside-adduser: get rid of too-verbose debugging
+
+2006-08-15 07:20 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import.cgi: add a new, extended
+ CSV import format
+
+2006-08-14 06:28 ivan
+
+ * FS/FS/cust_main.pm: pass email, phone and ip adderss to B:OP when
+ doing refunds, hopefully this will fix OpenECHO refunds
+
+2006-08-14 05:24 ivan
+
+ * Changes.1.7.0: there's more, but this will have to do
+
+2006-08-14 05:13 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/cust_main.cgi,
+ httemplate/elements/header.html,
+ httemplate/elements/search-cust_main.html,
+ rt/html/Elements/FreesideInvoiceSearch,
+ rt/html/Elements/FreesideNewCust,
+ rt/html/Elements/FreesideSearch,
+ rt/html/Elements/FreesideSvcSearch, rt/html/Elements/PageLayout,
+ rt/html/Elements/SimpleSearch, rt/html/Elements/Tabs,
+ rt/html/NoAuth/webrt.css: sprinkle some magic ajax fairy dust on
+ referring customer SELEKTAH. rewind! make smart search smarter,
+ re-layout the top search bars and add an invoice one
+
+2006-08-14 01:38 ivan
+
+ * FS/FS/access_user.pm: bugfix for agentless access users,
+ triggered by part_referral (advertising source) agent
+ virtualization
+
+2006-08-13 03:25 ivan
+
+ * FS/FS/Conf.pm, FS/FS/TicketSystem/RT_External.pm,
+ httemplate/edit/cust_pay.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/billing.html,
+ httemplate/view/cust_main/misc.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/tickets.html: customer view work:
+
+ DONE 1. add status and balance to top
+
+ DONE 2. add some sort of oldest date thing so the history
+ doesn't get too big (# years and a link to "show older")
+
+ 3. make the rest of the action links into js popups? maybe
+ later,
+ weird IENess when closing em
+ DONE (finished) - so revert out or finish/commit the Enter
+ check payment one - Process page can wait until another day..
+ it should be more of an *action*
+
+ DONE 4. Ticket list config knobs for wtxs (grid it too)
+
+ DONE 5. grid the package list
+
+2006-08-12 04:01 ivan
+
+ * httemplate/edit/cust_credit.cgi: s/Post/Enter/;
+
+2006-08-12 03:47 ivan
+
+ * FS/FS/Conf.pm, FS/FS/AccessRight.pm,
+ httemplate/view/cust_main/payment_history.html: fix acl rewrite
+ causing problems: void now shows up properly, deprecate all the
+ redundant config values
+
+2006-08-11 23:45 ivan
+
+ * FS/FS/cust_pkg.pm: don't adjust next bill date on unsuspension!
+ causes undesirable effects with prorate/subscription packages and
+ undesirably rewards customers for non-payment, closes: Bug#1325
+
+2006-08-11 01:02 ivan
+
+ * FS/FS/access_user.pm, FS/FS/part_referral.pm,
+ httemplate/browse/part_referral.html,
+ httemplate/edit/cust_main.cgi,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-part_referral.html,
+ httemplate/elements/tr-select-agent.html,
+ httemplate/elements/tr-select-part_referral.html: virtualize
+ referrals on customer addition
+
+2006-08-10 15:18 ivan
+
+ * httemplate/config/config.cgi: bugfix for selects that don't have
+ select_enum
+
+2006-08-10 06:50 ivan
+
+ * README.1.7.0, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/part_referral.pm, httemplate/browse/part_referral.html,
+ httemplate/view/cust_main/misc.html: add cust_main.agent_custid
+ (at least to schema and customer view, no manual editing yet)
+
+2006-08-10 05:01 ivan
+
+ * httemplate/browse/part_referral.html: bold the total footer
+
+2006-08-10 04:55 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/Record.pm, FS/FS/Schema.pm,
+ FS/FS/access_user.pm, FS/FS/part_referral.pm,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_referral.html,
+ httemplate/edit/part_referral.cgi,
+ httemplate/edit/part_referral.html,
+ httemplate/edit/process/part_referral.cgi,
+ httemplate/edit/process/part_referral.html,
+ httemplate/elements/menu.html: agent-virtualize advertising
+ sources
+
+2006-08-09 20:10 ivan
+
+ * FS/FS/Schema.pm: don't set the default to NULL the string!
+ besides, that's already the default value of any nullable column,
+ which @date_type is...
+
+2006-08-09 19:27 ivan
+
+ * FS/FS/part_pkg.pm: better debugging for missing recur_fee so its
+ easier to check the db
+
+2006-08-09 14:46 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/myaccount_menu.html: take
+ "coming soon" options off the menu, its been Soon for too long -
+ they'll get here when they do
+
+2006-08-09 03:47 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm, FS/FS/svc_acct.pm,
+ fs_selfservice/FS-SelfService/cgi/change_password.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/process_change_password.html,
+ fs_selfservice/FS-SelfService/cgi/provision_list.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: self-service
+ interface: add proper password changer and prevent "Setup my
+ services" provisioner from showing broken links for services not
+ handled yet
+
+2006-08-09 00:46 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi: and the
+ days go by...
+
+2006-08-09 00:03 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi: this is not
+ my beautiful magic template! (water flowing underground)
+
+2006-08-08 23:43 jeff
+
+ * README.1.7.0, FS/FS/Schema.pm, FS/FS/Setup.pm,
+ FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/cust_pay_batch.pm,
+ FS/FS/part_bill_event.pm, FS/FS/pay_batch.pm, FS/FS/payby.pm,
+ httemplate/browse/cust_pay_batch.cgi,
+ httemplate/browse/pay_batch.cgi, httemplate/docs/schema.html,
+ httemplate/misc/download-batch.cgi: batch refactor
+
+2006-08-08 23:34 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_invoice.html: self-service
+ interface: move from text to html invoices
+
+2006-08-08 20:45 ivan
+
+ * fs_selfservice/FS-SelfService/Makefile.PL: please bleeding-edge
+ debian perl, would you put it in /usr/local/sbin? thanks.
+
+2006-08-06 19:44 ivan
+
+ * FS/FS/CurrentUser.pm, FS/FS/Schema.pm, FS/FS/access_user.pm,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/access_user.html,
+ httemplate/edit/access_user.html,
+ httemplate/edit/elements/edit.html: add internal user disable-ing
+
+2006-08-06 19:19 ivan
+
+ * httemplate/search/elements/search.html: get rid of the extra
+ border in nested tables
+
+2006-08-06 16:39 ivan
+
+ * FS/: FS/access_user.pm, bin/freeside-adduser: slightly better
+ bootstrapping for htpasswd kludge... hopefully that will go away
+ in 1.7.1
+
+2006-08-06 14:37 ivan
+
+ * FS/FS/svc_Common.pm: make sure default RADIUS groups don't
+ override ones for existing records
+
+2006-08-06 13:23 ivan
+
+ * httemplate/edit/svc_acct.cgi: silly closing }
+
+2006-08-06 13:21 ivan
+
+ * FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/svc_acct.cgi: yow. fix up group handling
+
+2006-08-06 13:07 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/edit/process/cust_main.cgi: this
+ should fix the barfing about default radius groups on the new
+ customer screen...
+
+2006-08-06 02:14 ivan
+
+ * FS/FS/svc_acct.pm: this just needs to be a hashref and we should
+ be all set with radius groups then
+
+2006-08-06 02:10 ivan
+
+ * FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/svc_acct.cgi: this should process default
+ usergroup as well as fixed now
+
+2006-08-06 01:43 ivan
+
+ * FS/FS/svc_acct.pm: add debugging to track down RADIUS group
+ problem
+
+2006-08-06 01:10 ivan
+
+ * FS/FS/: svc_acct.pm: add confession here to diagnose etxrn's
+ problem better
+
+2006-07-27 17:33 ivan
+
+ * FS/FS/access_user.pm: htpasswd workaround no longer necessary -
+ closes: #1351
+
+2006-07-27 01:08 ivan
+
+ * FS/t/svc_phone.t: svc_phone.t
+
+2006-07-25 21:18 ivan
+
+ * FS/FS/UID.pm: ugh, fixup bootstrapping
+
+2006-07-25 01:39 ivan
+
+ * httemplate/search/cust_main.cgi: oops, extra else
+
+2006-07-25 01:33 ivan
+
+ * FS/FS/agent.pm, httemplate/browse/agent.cgi,
+ httemplate/elements/table-grid.html,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pkg.cgi:
+ this should finish adding the "inactive" status, i think?
+
+2006-07-25 00:27 ivan
+
+ * bin/rt-update-links: quick script to convert rt links from one
+ database name to another
+
+2006-07-24 15:40 ivan
+
+ * FS/FS/cust_main.pm: fix up smart searching to make the quick
+ payment entry behave better
+
+2006-07-23 07:23 ivan
+
+ * httemplate/search/report_receivables.cgi: sql num_pkgs
+ conflicting with method...
+
+2006-07-23 07:21 ivan
+
+ * httemplate/search/report_receivables.cgi: ugh, really fix the
+ statuses here
+
+2006-07-23 07:20 ivan
+
+ * httemplate/search/report_receivables.cgi: hopefully fix the
+ statuses here
+
+2006-07-23 07:17 ivan
+
+ * httemplate/search/report_receivables.cgi: i should REALLY go to
+ sleep
+
+2006-07-23 07:16 ivan
+
+ * httemplate/search/report_receivables.cgi: i should go to sleep
+
+2006-07-23 07:07 ivan
+
+ * FS/FS/cust_main.pm, httemplate/search/report_receivables.cgi:
+ more work towards adding an "inactive" status - add it to the A/R
+ report
+
+2006-07-15 17:55 ivan
+
+ * SCHEMA_CHANGE, FS/FS/Conf.pm, FS/FS/agent.pm, FS/FS/cust_bill.pm,
+ FS/FS/inventory_item.pm,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd,
+ httemplate/autohandler, httemplate/browse/cust_pay_batch.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/elements/overlibmws.js,
+ httemplate/elements/overlibmws_draggable.js,
+ httemplate/elements/phonenumber.html,
+ httemplate/search/cust_bill.html, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_forward.cgi, httemplate/search/svc_www.cgi,
+ httemplate/view/svc_external.cgi: odds and ends
+
+2006-07-13 21:20 ivan
+
+ * FS/FS/cust_pkg.pm: don't send cancellation emails on package
+ changes
+
+2006-07-13 20:27 ivan
+
+ * FS/FS/svc_Common.pm: this should fix radius group editing and the
+ "Reference found where even-sized list expected at
+ /usr/local/share/perl/5.8.4/FS/svc_Common.pm line 473" error
+
+2006-07-13 20:17 ivan
+
+ * FS/FS/CurrentUser.pm: this should fix the bootstrapping
+
+2006-07-13 18:42 ivan
+
+ * FS/FS/: CurrentUser.pm, UID.pm: add the small
+ FS::CurrentUser::BootstrapUser class for... surprise...
+ bootstrapping
+
+2006-07-13 17:42 ivan
+
+ * FS/FS/Setup.pm: fix acl bootstrapping
+
+2006-07-13 17:32 ivan
+
+ * FS/: FS/UID.pm, bin/freeside-setup: should be able to
+ freeside-setup without a username now
+
+2006-07-13 16:45 ivan
+
+ * FS/FS/UID.pm: mapsecrets file shouldn't be necessary at all...
+
+2006-07-12 20:54 ivan
+
+ * FS/FS/Report/Table/Monthly.pm,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_receivables.cgi: fix multiple-agent
+ virtualization properly for these reports
+
+2006-07-12 16:33 ivan
+
+ * FS/: bin/freeside-setup, FS/Setup.pm: add acl bootstrapping -
+ should be installable again now
+
+2006-07-11 17:20 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/Record.pm, FS/FS/Schema.pm,
+ FS/FS/cdr.pm, FS/FS/cust_svc.pm, FS/FS/h_svc_phone.pm,
+ FS/FS/part_svc.pm, FS/FS/svc_phone.pm,
+ httemplate/elements/menu.html, httemplate/misc/cdr-import.html,
+ FS/MANIFEST, htetc/handler.pl, httemplate/edit/part_svc.cgi,
+ httemplate/edit/svc_phone.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/elements/svc_Common.html,
+ httemplate/edit/process/svc_phone.html,
+ httemplate/edit/process/elements/process.html,
+ httemplate/edit/process/elements/svc_Common.html,
+ httemplate/search/cdr.html, httemplate/search/report_cdr.html,
+ httemplate/search/svc_phone.cgi, httemplate/view/svc_phone.cgi,
+ httemplate/view/elements/svc_Common.html,
+ FS/FS/part_pkg/voip_cdr.pm: svc_phone service and CDR billing
+ from imported CDRs
+
+2006-07-09 07:35 ivan
+
+ * rt/html/Elements/: Header, PageLayout: fix the image path in the
+ kludged looknfeel integration
+
+2006-07-05 07:55 ivan
+
+ * FS/FS/cust_main.pm: patch to fix fuzzy searching from Ryan Gunn
+
+2006-07-05 04:23 ivan
+
+ * README.1.7.0: hint about permissions and users
+
+2006-07-04 05:01 ivan
+
+ * FS/: bin/freeside-addgroup, bin/freeside-adduser, MANIFEST:
+ adding freeside-addgroup
+
+2006-07-01 04:26 ivan
+
+ * FS/FS/Record.pm: another Pg 8.1 fix? noticed by Damon Vincent
+
+2006-06-30 07:30 ivan
+
+ * FS/bin/freeside-adduser: checkin freeside-adduser with the -g
+ flag! sheesh
+
+2006-06-29 08:45 ivan
+
+ * FS/FS/part_export/shellcommands.pm: small patch to set
+ $new_finger from Tim Yardley
+
+2006-06-29 08:19 ivan
+
+ * httemplate/edit/part_bill_event.cgi: percentage late fees too
+
+2006-06-29 06:47 ivan
+
+ * FS/FS/inventory_class.pm, FS/FS/svc_Common.pm,
+ httemplate/browse/inventory_class.html,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_broadband.cgi,
+ httemplate/edit/svc_domain.cgi, httemplate/edit/svc_external.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/edit/svc_www.cgi,
+ httemplate/search/inventory_item.html: finish at least the
+ automatic provisioning part
+
+2006-06-27 07:19 ivan
+
+ * httemplate/docs/index.html: going to wikiland
+
+2006-06-24 09:41 ivan
+
+ * FS/FS/part_svc.pm, FS/FS/part_svc_column.pm,
+ httemplate/edit/part_svc.cgi, httemplate/browse/part_svc.cgi,
+ httemplate/elements/select-table.html,
+ httemplate/elements/table-grid.html: Add the ability to link
+ customer service definition fields to inventory classes, with
+ an "automatic/manual" flag. Add the ability for the web
+ interface to maintain these links. Start prettying up the
+ service def. edit in preparation for Bigger Changes.
+
+2006-06-21 09:26 ivan
+
+ * httemplate/browse/part_pkg.cgi: fix show/hide disabled link
+ interaction w/pager
+
+2006-06-21 06:00 ivan
+
+ * httemplate/elements/iframecontentmws.js: oops, don't want this
+ debugging in here
+
+2006-06-21 06:00 ivan
+
+ * httemplate/view/cust_main/payment_history.html:
+ http://www.macridesweb.com/oltest/ONCLICK.html !!!!!
+
+2006-06-21 05:58 ivan
+
+ * httemplate/view/cust_main.cgi: need the OLiframecontent sub
+
+2006-06-21 05:57 ivan
+
+ * httemplate/elements/header-popup.html: adding a header element
+ for popups to replace CGI::header
+
+2006-06-21 05:56 ivan
+
+ * httemplate/elements/iframecontentmws.js: add overlib iframe
+ function
+
+2006-06-21 01:42 ivan
+
+ * FS/FS/agent_type.pm, httemplate/browse/agent_type.cgi: speed up
+ the agent type report when there are lots of package definitions
+
+2006-06-19 06:09 ivan
+
+ * httemplate/view/cust_main/packages.html: fix ACL name for service
+ provisioning and prevent disabled service provisioning from
+ messing up table formatting
+
+2006-06-19 05:47 ivan
+
+ * bin/mapsecrets2access_user: better error checking for this
+ thrown-together bootstrapping script
+
+2006-06-19 05:22 ivan
+
+ * bin/mapsecrets2access_user: ACL bootstrapping
+
+2006-06-19 05:15 ivan
+
+ * FS/: FS/CurrentUser.pm, bin/freeside-upgrade: ACL bootstrapping
+
+2006-06-19 05:09 ivan
+
+ * FS/t/ConfDefaults.t: forgot to commit this test
+
+2006-06-19 04:57 ivan
+
+ * Changes.1.7.0, README.1.7.0, bin/mapsecrets2access_user: ACL
+ bootstrapping/upgrade
+
+2006-06-19 04:25 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/access_user.pm, FS/FS/cust_main.pm,
+ httemplate/elements/menu.html, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html: ACLs, take three
+ or four or something
+
+2006-06-19 01:05 ivan
+
+ * FS/FS/Conf.pm, FS/FS/ConfDefaults.pm, FS/FS/cust_main_Mixin.pm,
+ FS/FS/cust_pkg.pm, FS/FS/UI/Web.pm, httemplate/config/config.cgi,
+ httemplate/elements/menu.html,
+ httemplate/elements/select-cust-fields.html,
+ httemplate/elements/select-cust_pkg-status.html,
+ httemplate/elements/tr-select-cust-fields.html,
+ httemplate/elements/tr-select-cust_pkg-status.html,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/search/cust_pkg_report.cgi,
+ httemplate/search/report_cust_pkg.html,
+ httemplate/view/cust_main/contacts.html: add ability to select
+ specific package defs. and package status to package report for
+ qis
+
+2006-06-18 23:03 ivan
+
+ * httemplate/search/cust_main.cgi: fix up the alternating colors on
+ the customer search results
+
+2006-06-18 19:33 ivan
+
+ * FS/MANIFEST, FS/FS/CurrentUser.pm, FS/FS/Record.pm,
+ FS/FS/Schema.pm, FS/FS/UID.pm, FS/FS/access_user.pm,
+ FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-agent.html,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/search/svc_acct.cgi, httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_forward.cgi: agent virtualization, take one
+ (stuff from "inactive" changeset snuck into cust_main.pm and the
+ package reporting changeset in search/cust_pkg.cgi here too)
+
+2006-06-18 05:56 ivan
+
+ * httemplate/edit/elements/edit.html: well, it isn't broken...
+
+2006-06-18 05:54 ivan
+
+ * FS/FS/AccessRight.pm, FS/FS/access_group.pm,
+ FS/FS/access_groupagent.pm, FS/FS/m2name_Common.pm,
+ FS/FS/part_pkg.pm, httemplate/edit/access_group.html,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/elements/edit.html,
+ httemplate/edit/process/access_group.html,
+ httemplate/elements/checkboxes-table-name.html,
+ httemplate/elements/checkboxes-table.html, FS/MANIFEST,
+ htetc/handler.pl, httemplate/browse/access_group.html,
+ httemplate/browse/access_user.html,
+ httemplate/edit/process/elements/process.html: ACLs: finish group
+ edit (agents + rights) & browse
+
+2006-06-15 18:23 jeff
+
+ * FS/FS/cust_bill.pm, FS/FS/pay_batch.pm,
+ httemplate/misc/download-batch.cgi: value issues and many bits
+ remain
+
+2006-06-15 17:47 ivan
+
+ * httemplate/misc/download-batch.cgi: and fix the name for TD
+ Canada Trust. and that's it for now. really.
+
+2006-06-15 17:33 ivan
+
+ * httemplate/misc/download-batch.cgi: oops i'm gonna do that too,
+ now that the batch format file is not the same as the batch
+ params files
+
+2006-06-15 17:27 ivan
+
+ * httemplate/misc/download-batch.cgi: s/printf/sprintf/ and make
+ the config a little less strange
+
+2006-06-08 03:32 ivan
+
+ * httemplate/elements/menu.html: fix link to prepaid card setup
+
+2006-06-06 04:16 ivan
+
+ * rt/html/NoAuth/webrt.css: whew, this can go back
+
+2006-06-06 04:08 ivan
+
+ * rt/html/NoAuth/webrt.css: yay this should finally fix the weird
+ black navigation links; hide the Mason stuff from browsers when
+ it doesn't get processed for some reason
+
+2006-06-06 03:57 ivan
+
+ * rt/html/NoAuth/webrt.css: yet another attempt to fix weird black
+ RT navigation links
+
+2006-06-06 03:54 ivan
+
+ * rt/html/NoAuth/webrt.css: another attempt to fix weird black RT
+ navigation links
+
+2006-06-06 03:46 ivan
+
+ * rt/html/NoAuth/webrt.css: attempt to fix weird black RT
+ navigation links
+
+2006-06-06 03:30 ivan
+
+ * FS/FS/cdr.pm: fix unmatched =back somehow futzing things up with
+ automated install. wtf?!
+
+2006-06-02 06:20 ivan
+
+ * httemplate/elements/header.html,
+ httemplate/search/svc_Smart.html, rt/FREESIDE_MODIFIED,
+ rt/html/Elements/FreesideSvcSearch, rt/html/Elements/PageLayout,
+ rt/html/Elements/Tabs: add a service search
+
+2006-05-24 03:22 ivan
+
+ * FS/MANIFEST: removing duplicate entries
+
+2006-05-23 08:54 ivan
+
+ * README.1.7.0: adding batch upgrade instructions to 1.7.0
+ instructions too
+
+2006-05-22 13:38 ivan
+
+ * rt/html/Elements/FreesideNewCust: missing > tag on INPUT
+
+2006-05-22 11:27 ivan
+
+ * FS/FS/cust_main.pm: better error message for banned cards
+
+2006-05-22 11:05 ivan
+
+ * Changes.1.5.8: justification
+
+2006-05-21 19:06 ivan
+
+ * Makefile: docs are going in the wiki Real Soon Now anyway
+
+2006-05-21 19:04 ivan
+
+ * Changes.1.5.8: 1.5.8!
+
+2006-05-21 17:50 ivan
+
+ * Makefile: 1.7.0? why not?
+
+2006-05-21 17:44 ivan
+
+ * httemplate/: index.html, elements/menu.html: 1.7.0? why not!
+
+2006-05-21 11:40 ivan
+
+ * FS/FS/part_export/communigate_pro_singledomain.pm: tyop
+
+2006-05-20 13:06 jeff
+
+ * README.1.5.7.lastbit, README.1.5.8, FS/FS.pm, FS/MANIFEST,
+ FS/FS/Schema.pm, FS/FS/cust_bill.pm, FS/FS/cust_pay_batch.pm,
+ FS/FS/pay_batch.pm, FS/t/pay_batch.t, htetc/handler.pl,
+ httemplate/browse/cust_pay_batch.cgi,
+ httemplate/docs/schema.html, httemplate/docs/upgrade10.html,
+ httemplate/misc/download-batch.cgi: first stab at BoM download
+
+2006-05-15 06:57 ivan
+
+ * httemplate/: index.html, elements/freeside.css,
+ elements/header.html, elements/menu.html: move most of the crap
+ on the "main menu" to the sidebar
+
+2006-05-15 04:05 ivan
+
+ * rt/html/NoAuth/webrt.css, httemplate/elements/freeside.css,
+ httemplate/elements/header.html, httemplate/elements/xmenu.css,
+ httemplate/search/cust_main.cgi, rt/FREESIDE_MODIFIED,
+ rt/html/Elements/FreesideNewCust,
+ rt/html/Elements/FreesideSearch, rt/html/Elements/Header,
+ rt/html/Elements/PageLayout, rt/html/Elements/SimpleSearch,
+ rt/html/Elements/Tabs, rt/html/Elements/TitleBoxStart,
+ rt/html/Search/Bulk.html: more ACL and re-skinning work, now with
+ RT!
+
+2006-05-14 09:47 ivan
+
+ * CREDITS, Changes.1.7.0, htetc/handler.pl, httemplate/autohandler,
+ httemplate/index.html, httemplate/browse/access_group.html,
+ httemplate/browse/access_user.html,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/msgcat.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/edit/access_group.html,
+ httemplate/edit/access_user.html, httemplate/edit/agent_type.cgi,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_referral.cgi,
+ httemplate/edit/part_virtual_field.cgi,
+ httemplate/edit/svc_domain.cgi,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/access_group.html,
+ httemplate/edit/process/access_user.html,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/edit/process/elements/process.html,
+ httemplate/elements/checkboxes-table.html,
+ httemplate/elements/cssexpr.js, httemplate/elements/footer.html,
+ httemplate/elements/header.html,
+ httemplate/elements/menubar.html,
+ httemplate/elements/select-access_group.html,
+ httemplate/elements/tr-select-access_group.html,
+ httemplate/elements/xmenu.css, httemplate/elements/xmenu.js,
+ httemplate/misc/batch-cust_pay.html, httemplate/misc/payment.cgi,
+ httemplate/search/cust_bill.cgi,
+ httemplate/search/cust_main-otaker.cgi,
+ httemplate/search/cust_main-payinfo.html,
+ httemplate/search/cust_main-quickpay.html,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pay.html,
+ httemplate/search/cust_pkg_report.cgi,
+ httemplate/search/report_cust_bill.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_prepaid_income.html,
+ httemplate/search/report_tax.html,
+ httemplate/search/sqlradius.html,
+ httemplate/search/svc_acct.html,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_domain.html,
+ httemplate/search/svc_external.cgi, FS/MANIFEST,
+ FS/FS/AccessRight.pm, FS/FS/CGI.pm, FS/FS/Schema.pm,
+ FS/FS/access_group.pm, FS/FS/access_groupagent.pm,
+ FS/FS/access_right.pm, FS/FS/access_user.pm,
+ FS/FS/access_user_pref.pm, FS/FS/access_usergroup.pm,
+ FS/FS/agent_type.pm, FS/FS/cust_bill.pm, FS/FS/m2m_Common.pm,
+ FS/FS/payby.pm, FS/FS/svc_domain.pm, FS/FS/UI/Web.pm,
+ FS/FS/part_pkg/billoneday.pm, FS/bin/freeside-addoutsourceuser,
+ FS/t/AccessRight.t, FS/t/access_group.t,
+ FS/t/access_groupagent.t, FS/t/access_right.t,
+ FS/t/access_user.t, FS/t/access_user_pref.t,
+ FS/t/access_usergroup.t, httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html: first part of ACL
+ and re-skinning work and some other small stuff
+
+2006-05-13 11:34 ivan
+
+ * httemplate/images/background-cheat.png: yay for cheating
+
+2006-05-13 08:31 ivan
+
+ * httemplate/images/: 32clear.gif, arrow.down.png,
+ arrow.right.black.png, arrow.right.png, black-gradient.png,
+ black-gray-corner.png, black-gray-gradient.png,
+ black-gray-side.png, black-gray-top.png: adding new images
+
+2006-05-12 06:57 ivan
+
+ * httemplate/search/report_receivables.cgi: Pg 8.1 fix was
+ incorrect and broke things, this should actually work
+
+2006-05-08 04:48 ivan
+
+ * README.1.5.8, README.1.7.0: suggest "make clean" on upgrade -
+ something is not quite right with perl Makefile hoohaw
+
+2006-05-08 04:28 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm,
+ httemplate/search/report_tax.cgi: add config switch to base tax
+ off shipping address if present
+
+2006-05-08 03:01 ivan
+
+ * FS/FS/Report/Table/Monthly.pm, httemplate/index.html,
+ httemplate/graph/cust_bill_pkg-graph.cgi,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/elements/monthly.html,
+ httemplate/search/cust_bill_pkg.cgi: sales report per agent and
+ package class looks good
+
+2006-05-07 13:27 ivan
+
+ * README.1.7.0, htetc/handler.pl, httemplate/docs/upgrade10.html,
+ httemplate/elements/select-month_year.html,
+ httemplate/elements/select-pkg_class.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-from_to.html,
+ httemplate/elements/tr-select-pkg_class.html,
+ httemplate/graph/cust_bill_pkg-graph.cgi,
+ httemplate/graph/cust_bill_pkg.cgi,
+ httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi,
+ httemplate/graph/report_cust_bill_pkg.html,
+ httemplate/graph/report_money_time.html,
+ httemplate/graph/elements/monthly.html: first pass at sales
+ reports per agent and package class
+
+2006-05-03 02:47 ivan
+
+ * httemplate/search/report_receivables.cgi: pg 8.1 fix from Chris
+ Cappuccio
+
+2006-05-02 08:23 ivan
+
+ * FS/: MANIFEST, FS/Pony.pm: yours!
+
+2006-05-02 08:03 ivan
+
+ * httemplate/: index.html, search/report_receivables.html: add an
+ agent pre-selection page to receivables report
+
+2006-05-02 06:29 ivan
+
+ * SCHEMA_CHANGE: need to install the new Schema.pm before you can
+ autogenerate off it
+
+2006-05-02 04:59 ivan
+
+ * httemplate/index.html, FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi,
+ httemplate/graph/report_money_time.html: add a "pre-report" page
+ to this report/graph as requested by lewis/wtxs, also add 12mo
+ total option
+
+2006-05-01 06:09 ivan
+
+ * FS/FS/part_pkg/prorate.pm: small fix to make prorate behave on
+ the 1st as it did before
+
+2006-05-01 05:38 ivan
+
+ * FS/FS/part_pkg/: prorate.pm, subscription.pm: fix some very
+ annoying clucks (warnings with backtraces) when cutoff day isn't
+ found in old packages
+
+2006-05-01 04:45 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: column reference "disabled" is
+ ambiguous
+
+2006-05-01 04:43 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: fix bug with duplicate tickets
+ showing up on customer view listing when the custom priority
+ field was edited
+
+2006-04-26 06:16 ivan
+
+ * Makefile: apache reload doesn't work when server isn't running
+ already
+
+2006-04-21 17:58 ivan
+
+ * httemplate/browse/generic.cgi,
+ httemplate/browse/inventory_class.html,
+ httemplate/browse/part_pkg.cgi, httemplate/browse/pkg_class.html,
+ httemplate/browse/rate.cgi,
+ httemplate/browse/elements/browse.html, htetc/handler.pl,
+ httemplate/index.html, httemplate/edit/inventory_class.html,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/pkg_class.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/inventory_class.html,
+ httemplate/edit/process/pkg_class.html,
+ httemplate/edit/process/elements/process.html,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/select-pkg_class.html,
+ httemplate/elements/select-table.html,
+ httemplate/elements/tr-select-pkg_class.html,
+ httemplate/search/cust_pkg.cgi,
+ httemplate/search/inventory_class.html, FS/FS/part_pkg.pm,
+ httemplate/search/elements/search.html: start of package class
+ web UI (add/edit package classes, package class selection in
+ package def edit)
+
+2006-04-21 07:21 ivan
+
+ * FS/FS/part_pkg/incomplete/billoneday.pm: throw this in here for
+ now
+
+2006-04-21 07:20 ivan
+
+ * FS/FS/part_pkg/: flat.pm, prorate.pm, subscription.pm: fix some
+ indentation and the default cutoff day
+
+2006-04-21 05:45 ivan
+
+ * httemplate/: index.html, browse/queue.cgi, misc/queue.cgi,
+ search/queue.html: s(browse/queue.cgi)(search/queue.html)
+
+2006-04-18 23:37 ivan
+
+ * FS/FS/cust_main.pm: DOH! perlvar: not counting patterns matched
+ in nested blocks that have been exited already.
+
+2006-04-18 12:33 ivan
+
+ * httemplate/docs/install.html: add JSON to initial install
+ instructions
+
+2006-04-18 12:24 ivan
+
+ * install/debian/3.1/INSTALL: dev install notes patch from liran
+ tal
+
+2006-04-15 06:32 ivan
+
+ * httemplate/graph/money_time.cgi: REALLY correct the period for
+ the total column this time
+
+2006-04-15 06:28 ivan
+
+ * httemplate/graph/money_time.cgi: correct period & use a yellow
+ color for the total column
+
+2006-04-15 06:25 ivan
+
+ * httemplate/graph/money_time.cgi: format & link the total column
+
+2006-04-14 17:21 ivan
+
+ * httemplate/graph/money_time.cgi: and </TD> the total column
+
+2006-04-14 17:16 ivan
+
+ * httemplate/graph/money_time.cgi: add a total column
+
+2006-04-14 04:55 ivan
+
+ * FS/FS/: Conf.pm, svc_forward.pm: add the
+ svc_forward-arbitrary_dst flag to enable arbitrary svc_forward
+ destinations
+
+2006-04-13 14:29 ivan
+
+ * FS/bin/freeside-adduser: don't do the duplicate check unless
+ there's a file already; fixes problem with first use of
+ freeside-adduser
+
+2006-04-12 05:36 ivan
+
+ * httemplate/index.html, FS/FS/cust_main.pm,
+ httemplate/search/cust_main-zip.html,
+ httemplate/search/cust_main.cgi,
+ httemplate/search/report_cust_main-zip.html,
+ httemplate/search/elements/search.html: zip code report
+
+2006-04-09 16:41 ivan
+
+ * httemplate/view/: cust_main.cgi, cust_main/payment_history.html,
+ cust_main/tickets.html: a few more fixups for our favorite
+ include(...) from Scott Edwards
+
+2006-04-09 16:39 ivan
+
+ * httemplate/edit/cust_main.cgi: add "spool_cdr" to cust_main
+ fields
+
+2006-04-09 16:24 ivan
+
+ * FS/FS/part_export/domain_shellcommands.pm: should fix "Can't use
+ string ("old_uid") as a SCALAR ref while "strict refs" in use"
+ error
+
+2006-04-09 13:36 ivan
+
+ * FS/bin/freeside-adduser: error out if you try to add duplicates;
+ this should lower my annoyance-level
+
+2006-04-03 16:26 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: option to disable global uniqueness
+ checking
+
+2006-04-03 13:49 ivan
+
+ * FS/FS/svc_domain.pm: add PTR to sort order for DNS entries
+
+2006-04-03 04:36 ivan
+
+ * FS/FS/Record.pm: and also allow [ and ] in ut_textn
+
+2006-04-03 03:11 ivan
+
+ * FS/FS/Record.pm: allow [ and ] in ut_text
+
+2006-04-03 02:46 ivan
+
+ * htetc/handler.pl, FS/FS/Misc.pm,
+ httemplate/edit/cust_main/contact.html,
+ httemplate/edit/cust_main/select-country.html,
+ httemplate/edit/cust_main/select-state.html,
+ httemplate/misc/states.cgi,
+ httemplate/view/cust_main/contacts.html: have the UI use full
+ country names, and state names outside the US...
+
+2006-04-02 15:13 ivan
+
+ * FS/FS/: cust_main.pm, cust_pay_batch.pm: typo
+
+2006-03-31 15:22 ivan
+
+ * httemplate/browse/part_bill_event.cgi: quick sort fix for billing
+ events
+
+2006-03-31 01:20 lsc
+
+ * FS/FS/part_pkg/: prorate.pm, subscription.pm: fixed the errors
+ pointed out by Ivan in the following email:
+
+ ---- before and after now? I gave subscription and prorate a
+ try. Subscription came out as:
+
+ subscription 27th (03/25/06 - 04/27/06) $10.00
+ subscription 23rd (03/25/06 - 04/23/06) $10.00
+
+ the "23rd" one is right, but the "27th" one should have only
+ advanced the date two days to 3/27/06.
+
+ Prorate came out as:
+
+ prorate 23rd (03/25/06 - 04/23/06) $9.20
+ prorate 27th (03/25/06 - 04/27/06) $10.49
+
+ The "23rd" one is right, but the "27th" one should have only
+ advanced the date two days to 4/27/06.
+
+ lsc@prgmr.com
+
+2006-03-30 06:22 ivan
+
+ * README.1.7.0, FS/bin/freeside-upgrade: move all the
+ schema-updating magic into DBIx::DBSchema
+
+2006-03-24 18:23 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/queue_depend.pm, FS/FS/svc_acct.pm,
+ FS/bin/freeside-setup,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_external.html,
+ fs_selfservice/FS-SelfService/cgi/recharge_results.html,
+ httemplate/misc/upload-batch.cgi,
+ httemplate/misc/process/cdr-import.html,
+ httemplate/misc/process/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import_charges.cgi,
+ httemplate/misc/process/inventory_item-import.html: successfully
+ correct the spelling of sucessful
+
+2006-03-24 11:49 ivan
+
+ * httemplate/misc/process/payment.cgi: fix spelling
+
+2006-03-23 04:00 lsc
+
+ * FS/FS/part_pkg/: billoneday.pm, prorate.pm, subscription.pm: for
+ subscription.pm and prorate.pm:
+
+ -modify the subscription and prorate price plans
+ (FS/FS/part_pkg/subscription.pm and prorate.pm) to have a
+ configurable (add a field to the %info hash) billing day instead
+ of "1st of the month" only. subscription will be easy, prorate
+ will be a little trickier.
+
+ essentially, I replaced the '1' in the 'day' field of the
+ timelocal that generates $$date with the value I added to the
+ %info hash, 'cutoff_day'
+
+ -implement a price plan (new file in FS/FS/part_pkg/ - probably
+ @ISA FS::part_pkg::subscription) that charges the first full
+ month if the customer signs up between the 1st and the
+ configurable billing day, and gives them the remainder of the
+ month free if they sign up between the configurable billing day
+ and the end of the month.
+
+ if this is the first time the customer is billed, and if the date
+ is greater than the cutoff date, advance $ssdate to cutoff_day of
+ next month, else $$date is cutoff_date of this month. Either
+ way, charge them for a month.
+
+ ----------------------------------------------------------------------
+
+2006-03-20 11:13 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/cdr.pm,
+ FS/FS/cdr_upstream_rate.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_svc.pm, FS/FS/rate_detail.pm, FS/FS/svc_acct.pm,
+ FS/FS/part_pkg/voip_cdr.pm, httemplate/edit/part_pkg.cgi,
+ FS/MANIFEST, FS/t/cdr_upstream_rate.t,
+ bin/cdr_upstream_rate.import, httemplate/edit/rate.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/search/cdr.html, httemplate/search/report_cdr.html,
+ httemplate/view/cust_main/billing.html: add price plan to bill on
+ internal or external CDRs directly, add option to export CDRs to
+ a per-customer downstream file
+
+2006-03-17 06:56 ivan
+
+ * FS/FS/Daemon.pm: use IO::File, lucky this never threw an error...
+
+2006-03-14 23:34 ivan
+
+ * FS/FS/part_pkg/voip_cdr.pm: initial commit of this just cause i
+ want a revision history
+
+2006-03-14 20:17 ivan
+
+ * FS/FS/Record.pm: handle BIGSERIAL like SERIAL for the cdr table,
+ and normalize canadian zip codes as well as us ones
+
+2006-03-13 14:32 ivan
+
+ * httemplate/elements/: progress-init.html, progress-popup.html:
+ fix progress hoohaw for internet exploder again, whew. also make
+ sure error/finish messages are centered, looks better
+
+2006-03-10 23:27 ivan
+
+ * httemplate/elements/footer.html: some pages from ui hoohaw have
+ leaked footer include, need something here for now
+
+2006-03-10 21:21 ivan
+
+ * httemplate/: elements/progress-init.html, elements/xmlhttp.html,
+ misc/email_invoice_events.cgi, misc/email_invoices.cgi,
+ misc/fax_invoice_events.cgi, misc/fax_invoices.cgi,
+ misc/print_invoice_events.cgi, misc/print_invoices.cgi: fix the
+ progressbar bug with multiple progressbar forms on a page
+
+2006-03-10 14:30 ivan
+
+ * httemplate/: elements/progress-init.html,
+ misc/email_invoice_events.cgi, misc/email_invoices.cgi,
+ misc/fax_invoice_events.cgi, misc/fax_invoices.cgi,
+ misc/print_invoice_events.cgi, misc/print_invoices.cgi: fix to
+ (hopefully) allow multiple progress-init's in a page, also add
+ second $cgi arg to all these progressbar calls...
+
+2006-03-10 14:28 ivan
+
+ * FS/FS/UI/Web.pm: want to know who *called* this without the
+ required second arg
+
+2006-03-09 05:42 ivan
+
+ * htetc/handler.pl: fix that
+ blank-page-instead-of-profiling-redirect-when-called-from-an-include
+ bug triggered by mason 1.32 :)
+
+2006-03-09 03:48 ivan
+
+ * httemplate/view/cust_main.cgi: don't use a table with
+ WIDTH="100%", it shoves the custnum and "billing information"
+ boxes way out to the right
+
+2006-03-08 04:14 ivan
+
+ * FS/FS/inventory_item.pm,
+ httemplate/misc/inventory_item-import.html,
+ httemplate/misc/process/inventory_item-import.html,
+ httemplate/search/inventory_class.html,
+ httemplate/search/inventory_item.html: Add an option to the web
+ interface to batch upload new entries to the
+ inventory_item table.
+
+2006-03-08 02:05 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/inventory_class.pm,
+ FS/FS/inventory_item.pm, FS/t/inventory_class.t,
+ FS/t/inventory_item.t, httemplate/search/inventory_class.html,
+ httemplate/search/inventory_item.html, bin/generate-table-module,
+ htetc/handler.pl, httemplate/edit/inventory_class.html,
+ httemplate/edit/elements/edit.html,
+ httemplate/edit/process/inventory_class.html,
+ httemplate/edit/process/elements/process.html,
+ httemplate/search/elements/search.html: Add a new table for
+ inventory with for DIDs/serials/etc., and an additional new table
+ for inventory category (i.e. to distinguish DIDs, serials, MACs,
+ etc.)
+
+2006-03-08 00:21 ivan
+
+ * FS/FS/agent.pm: add space in error msg
+
+2006-03-03 07:02 ivan
+
+ * FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi: agent-specific
+ sales/credit/receipts summary
+
+2006-02-28 11:34 ivan
+
+ * FS/FS/part_pkg.pm: update POD docs regarding new price plans
+
+2006-02-22 05:07 ivan
+
+ * FS/FS/Conf.pm, httemplate/elements/phonenumber.html,
+ httemplate/images/red_telephone_mimooh_01.png,
+ httemplate/view/cust_main/contacts.html: add vonage click2call
+ feature
+
+2006-02-21 23:12 ivan
+
+ * FS/FS/CGI.pm: a better CGI::rooturl(), will have to do for now
+
+2006-02-18 03:14 ivan
+
+ * FS/FS/Schema.pm, FS/FS/cdr.pm, FS/FS/cdr_calltype.pm,
+ FS/FS/cdr_carrier.pm, FS/FS/cdr_type.pm, FS/FS/cust_main.pm,
+ README.1.7.0, README.2.0.0, FS/MANIFEST,
+ FS/FS/part_pkg/voip_sqlradacct.pm, FS/t/cdr.t,
+ FS/t/cdr_calltype.t, FS/t/cdr_carrier.t, FS/t/cdr_type.t,
+ FS/t/part_pkg-voip_cdr.t, htetc/handler.pl,
+ httemplate/misc/cdr-import.html,
+ httemplate/misc/process/cdr-import.html,
+ httemplate/search/cdr.html, httemplate/search/report_cdr.html,
+ bin/cdr_calltype.import: CDR schema and class
+
+2006-02-17 20:32 ivan
+
+ * htetc/global.asa, httemplate/docs/install.html: Mason it is
+
+2006-02-17 18:11 ivan
+
+ * FS/FS/: cust_tax_exempt_pkg.pm, domain_record.pm, msgcat.pm,
+ nas.pm, part_bill_event.pm, port.pm, prepay_credit.pm, queue.pm,
+ queue_arg.pm, rate_detail.pm, reg_code_pkg.pm: update POD
+ documentation left behind from example template
+
+2006-02-16 13:43 ivan
+
+ * FS/FS/Setup.pm, FS/bin/freeside-setup, bin/populate-msgcat,
+ httemplate/docs/admin.html, httemplate/docs/install.html:
+ automate more of the initial data adding...
+
+2006-02-08 23:18 ivan
+
+ * httemplate/elements/: calendar-en.js, calendar-setup.js,
+ calendar-win2k-2.css, calendar.js, calendar_stripped.js: update
+ jscalendar
+
+2006-02-08 14:53 ivan
+
+ * FS/bin/freeside-selfservice-server: don't leave ssh zombies
+ around either
+
+2006-02-07 19:50 ivan
+
+ * httemplate/docs/: upgrade7.html, upgrade8.html: remove ancient
+ upgrade instructions
+
+2006-02-07 19:49 ivan
+
+ * httemplate/docs/: upgrade10.html, index.html: slightly html-ize
+ the 1.5.8 upgrade instructions
+
+2006-02-07 18:26 ivan
+
+ * FS/FS/UID.pm: update error message when secrets file cannot be
+ found
+
+2006-02-07 05:49 ivan
+
+ * FS/FS/svc_acct.pm: well, it was already fatal. at least now the
+ error message is better.
+
+2006-02-07 03:12 ivan
+
+ * httemplate/edit/cust_pay.cgi: remove inadvertant extra table
+ statement preventing page from showing up in konq
+
+2006-02-05 04:27 ivan
+
+ * FS/FS/option_Common.pm, httemplate/browse/payment_gateway.html,
+ httemplate/edit/payment_gateway.html,
+ httemplate/edit/process/payment_gateway.html: payment gateway
+ editing
+
+2006-02-01 15:13 ivan
+
+ * FS/MANIFEST, FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ FS/FS/Cron/backup.pm, FS/FS/Cron/bill.pm, FS/FS/Cron/vacuum.pm,
+ FS/bin/freeside-daily, FS/bin/freeside-monthly,
+ FS/t/Cron-backup.t, FS/t/Cron-bill.t, FS/t/Cron-vacuum.t,
+ httemplate/browse/part_bill_event.cgi: finish adding
+ freeside-monthly and monthly events
+
+2006-01-31 23:58 ivan
+
+ * Makefile: HEAD isn't 1.5.8 anymore
+
+2006-01-31 07:01 ivan
+
+ * FS/FS/payby.pm: oops, forgot $
+
+2006-01-31 03:02 ivan
+
+ * FS/FS/Schema.pm, FS/FS/payby.pm, FS/MANIFEST, FS/t/payby.t,
+ htetc/handler.pl, httemplate/browse/part_bill_event.cgi,
+ httemplate/edit/part_bill_event.cgi: [no log message]
+
+2006-01-30 20:26 ivan
+
+ * httemplate/: browse/addr_block.cgi, browse/agent.cgi,
+ browse/agent_type.cgi, browse/cust_pay_batch.cgi,
+ browse/part_bill_event.cgi, browse/part_export.cgi,
+ browse/part_pkg.cgi, browse/part_referral.cgi,
+ browse/part_svc.cgi, browse/part_virtual_field.cgi,
+ browse/payment_gateway.html, browse/queue.cgi, browse/rate.cgi,
+ browse/router.cgi, browse/svc_acct_pop.cgi,
+ config/config-view.cgi, config/config.cgi,
+ edit/REAL_cust_pkg.cgi, edit/agent.cgi,
+ edit/agent_payment_gateway.html, edit/agent_type.cgi,
+ edit/bulk-cust_svc.html, edit/cust_pay.cgi, edit/part_export.cgi,
+ edit/part_pkg.cgi, edit/part_svc.cgi, edit/payment_gateway.html,
+ edit/prepay_credit.cgi, edit/rate.cgi, edit/rate_region.cgi,
+ edit/reg_code.cgi, edit/svc_acct.cgi, edit/svc_broadband.cgi,
+ edit/svc_forward.cgi, edit/process/prepay_credit.cgi,
+ edit/process/reg_code.cgi, misc/batch-cust_pay.html,
+ misc/cust_main-import.cgi, misc/cust_main-import_charges.cgi,
+ misc/expire_pkg.cgi, misc/link.cgi, misc/meta-import.cgi,
+ misc/upload-batch.cgi, misc/whois.cgi,
+ misc/process/cust_main-import.cgi,
+ misc/process/cust_main-import_charges.cgi,
+ misc/process/meta-import.cgi, search/report_prepaid_income.cgi,
+ search/report_tax.cgi, search/svc_external.cgi,
+ view/cust_bill.cgi, view/cust_main.cgi, view/svc_acct.cgi,
+ view/svc_broadband.cgi, view/svc_domain.cgi,
+ view/svc_external.cgi: move header() to
+ include(/elements/header.html) so it can be changed in one place,
+ thanks to Scott Edwards
+
+2006-01-30 18:59 ivan
+
+ * FS/FS/Record.pm: fix "table not found" dbdef error message to
+ recommend freeside-upgrade instead create + dbdef-create
+
+2006-01-26 23:34 ivan
+
+ * httemplate/search/report_tax.cgi: small visual fix to alternating
+ row colors when show_taxclasses is on
+
+2006-01-26 17:33 ivan
+
+ * httemplate/search/cust_tax_exempt_pkg.cgi: on tax exemption
+ report, show more info on the specific line item and invoice
+
+2006-01-26 07:27 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/cust_tax_exempt_pkg.pm,
+ FS/FS/part_pkg.pm, FS/FS/pkg_class.pm, FS/t/pkg_class.t,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/cust_tax_exempt_pkg.cgi,
+ httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html: whew, FINALLY can fix monthly
+ exemption columns to work correctly. also make them
+ agent-specific. also fix package exemption columns, they were
+ bunk too, sheesh. start adding package classes for package class
+ tax reporting.
+
+2006-01-25 04:34 ivan
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_tax_exempt.pm,
+ FS/FS/cust_tax_exempt_pkg.pm, FS/FS/h_cust_bill.pm,
+ FS/FS/h_cust_tax_exempt.pm, FS/t/cust_tax_exempt_pkg.t,
+ FS/t/h_cust_bill.t, FS/t/h_cust_tax_exempt.t, README.2.0.0,
+ FS/MANIFEST: change texas-style tax exemptions to be against a
+ specific line item rather than just general per-customer, for
+ later tracking and tax reporting. fix 1969/1970 exemptions for
+ one-off charges
+
+2006-01-05 01:34 ivan
+
+ * httemplate/docs/upgrade10.html: my last 1.4 -> 1.5 upgrade...
+
+2006-01-04 18:03 ivan
+
+ * FS/FS/Schema.pm: remove redundant indices on cust_main ship_
+ columns
+
+2006-01-03 00:45 ivan
+
+ * bin/billco-upload: agentnums 1-3
+
+2005-12-29 18:41 rsiddall
+
+ * FS/FS/Conf.pm, FS/FS/ConfItem.pm, FS/FS/cust_pkg.pm,
+ FS/FS/cust_svc.pm, FS/FS/part_export/artera_turbo.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/provision_list.html,
+ httemplate/view/cust_main.cgi: Fixing a few typos.
+
+2005-12-24 19:41 ivan
+
+ * httemplate/search/report_tax.cgi: add switch to enable taxclass
+ breakdown, report invoiced tax separately in that case
+
+2005-12-24 19:38 ivan
+
+ * httemplate/edit/part_bill_event.cgi: make sure to specify a
+ money_char default
+
+2005-12-24 19:18 ivan
+
+ * httemplate/search/: report_tax.cgi, report_tax.html: add switch
+ to enable taxclass breakdown, report invoiced tax separately in
+ that case
+
+2005-12-24 19:07 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: correct "out of taxable
+ region" flag on new line item report - NULLs need to be compared
+ explicitly. apparantly NULL != NULL. bah SQL
+
+2005-12-24 19:00 ivan
+
+ * README.1.5.8, FS/FS/Schema.pm: update indices for better tax
+ report performance
+
+2005-12-24 18:31 ivan
+
+ * httemplate/search/cust_bill_pkg.cgi: fixup new line item report
+ brainfart
+
+2005-12-24 17:57 ivan
+
+ * httemplate/search/report_tax.cgi: correct end date display for
+ "now"
+
+2005-12-24 16:52 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/part_bill_event.pm,
+ httemplate/edit/part_bill_event.cgi: add invoice event to suspend
+ only when greater than N amount
+
+2005-12-24 16:36 ivan
+
+ * httemplate/edit/cust_main/billing.html: don't reenable postal
+ billing for existing customers just cause its blank...
+
+2005-12-21 20:24 ivan
+
+ * httemplate/search/report_tax.cgi: and s/$taxable/$tot_taxable/ in
+ the declaration too
+
+2005-12-21 20:22 ivan
+
+ * httemplate/search/report_tax.cgi: fix some ambiguous var names
+ causing " "my" variable $t masks earlier declaration in same
+ scope" errors
+
+2005-12-21 20:02 ivan
+
+ * Changes.1.5.8: more accurate description of tax report changes
+
+2005-12-21 20:01 ivan
+
+ * httemplate/search/cust_bill_event.html,
+ httemplate/search/cust_bill_pkg.cgi,
+ httemplate/search/cust_pkg_report.cgi,
+ httemplate/search/report_cust_bill.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html, FS/FS/cust_bill_pkg.pm,
+ httemplate/elements/select-agent.html,
+ httemplate/elements/table-grid.html,
+ httemplate/elements/tr-input-beginning_ending.html,
+ httemplate/elements/tr-select-agent.html,
+ httemplate/search/elements/search.html: tax report update, link
+ to new line item report, per-agent tax reporting
+
+2005-12-18 20:18 ivan
+
+ * FS/FS/part_pkg/: sesmon_hour.pm, sesmon_minute.pm,
+ sql_external.pm, sql_generic.pm, voip_sqlradacct.pm: correct
+ field labeling - not always monthly
+
+2005-12-18 20:18 ivan
+
+ * Changes.1.5.8, FS/FS/part_pkg/sqlradacct_hour.pm: add maximum
+ "caps" to RADIUS usage charges
+
+2005-12-16 14:47 ivan
+
+ * FS/FS/raddb.pm, bin/generate-raddb: add motorola canopy
+ attributes from wtxs, neaten up raddb.pm generation
+
+2005-12-15 17:49 ivan
+
+ * httemplate/edit/payment_gateway.html: add TransactionCentral
+
+2005-12-15 11:36 ivan
+
+ * httemplate/edit/: agent.cgi, agent_type.cgi: fix bug when adding
+ new agent types, noticed by Julius Igugu
+
+2005-12-15 10:45 ivan
+
+ * bin/print-schema: adding print-schema
+
+2005-12-14 20:04 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_pay_void.pm, FS/FS/Record.pm,
+ httemplate/misc/unvoid-cust_pay_void.cgi: payment "un-void"ing
+
+2005-12-14 12:57 ivan
+
+ * FS/FS/svc_acct.pm: allow a dir field to be set (or
+ auto-generated) even if uid is fixed
+
+2005-12-14 10:52 ivan
+
+ * FS/FS/part_export/radiator.pm: add 'STATE' field for suspensions
+ to Radiator export
+
+2005-12-12 19:13 ivan
+
+ * httemplate/edit/process/payment_gateway.html: fix options in
+ gateway adding
+
+2005-12-12 13:39 ivan
+
+ * FS/FS/part_export/radiator.pm: use crypt password for radiator
+ export
+
+2005-12-09 08:58 ivan
+
+ * httemplate/: edit/process/cust_credit_bill.cgi,
+ view/cust_main/payment_history.html: fill in reason if empty when
+ applying a credit to a refund
+
+2005-12-09 08:56 ivan
+
+ * httemplate/edit/: cust_main.cgi, cust_main/billing.html: fix
+ postal mail checkbox misbehaving (isn't sticky on errors -
+ reverts back to on)
+
+2005-12-07 15:48 ivan
+
+ * FS/: FS/Record.pm, bin/freeside-setup: for fetching inserted keys
+ without pg_oid_status, look up the actual sequence name from
+ dbdef rather than assuming ${table}_${column}_seq
+
+2005-12-06 14:25 ivan
+
+ * FS/FS/Record.pm: make sure zip is required for canada, also use
+ CURRVAL() function instead of pg_oid_status DBD attribute because
+ Pg 8.1 doesn't have oids by default anymore
+
+2005-12-05 11:01 ivan
+
+ * FS/FS/svc_Common.pm: avoid uninitialized value errors
+
+2005-12-05 09:19 ivan
+
+ * httemplate/edit/process/cust_main.cgi: eek, don't log all this
+ debugging info by default
+
+2005-12-02 23:26 ivan
+
+ * htetc/handler.pl: this should be the last of
+ s/RT::TicketCustomFieldValues/RT::ObjectCustomFieldValues/
+
+2005-12-02 23:12 ivan
+
+ * Makefile: those semicolons can't possibly have belonged there
+
+2005-12-02 23:02 ivan
+
+ * FS/bin/freeside-upgrade: force a dbdef reload. no wonder this
+ had to be run multiple times before
+
+2005-12-02 22:49 ivan
+
+ * README.1.5.8, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: add Term::ReadKey to install &
+ upgrade docs and README.1.5.8
+
+2005-12-01 18:30 ivan
+
+ * httemplate/docs/upgrade10.html: and Net::Whois::Raw
+
+2005-12-01 17:52 ivan
+
+ * README.1.5.8, httemplate/docs/upgrade10.html: note DBIx::DBSchema
+ 0.29 is required for Pg 7.2.x and earlier
+
+2005-12-01 17:22 ivan
+
+ * httemplate/docs/upgrade10.html: apache instructions already up
+ top
+
+2005-12-01 11:17 ivan
+
+ * httemplate/edit/agent_type.cgi: list disabled packages on agent
+ type edit if they are still associated with the type
+
+2005-12-01 09:36 ivan
+
+ * FS/FS/part_export/shellcommands.pm: shellcommands usermod_pwonly
+ shouldn't apply to RADIUS groups, this is messing up unrelated
+ RADIUS exports
+
+2005-11-30 09:48 ivan
+
+ * README.1.5.8: later versions are okay too
+
+2005-11-28 09:16 ivan
+
+ * FS/FS/cust_main.pm: turn off debugging
+
+2005-11-28 09:13 ivan
+
+ * FS/bin/freeside-sqlradius-radacctd: in POD example, remove extra
+ SQL that Pg doesn't need and MySQL doesn't like
+
+2005-11-28 09:12 ivan
+
+ * FS/bin/freeside-sqlradius-radacctd: update docs and error message
+ for all three supporte exports
+
+2005-11-28 09:07 ivan
+
+ * FS/bin/freeside-sqlradius-radacctd: startup
+ freeside-sqlradius-radacctd for radiator export too
+
+2005-11-28 08:59 ivan
+
+ * FS/FS/svc_Common.pm: allow defaults to override empty values for
+ new objects
+
+2005-11-28 08:38 ivan
+
+ * FS/FS/cust_svc.pm: better error msg
+
+2005-11-28 08:34 ivan
+
+ * FS/FS/cust_svc.pm: update cust_svc::seconds_since_sqlradacct to
+ deal with any usage-capable export
+
+2005-11-28 08:21 ivan
+
+ * FS/FS/cust_svc.pm: update cust_svc::seconds_since_sqlradacct to
+ deal with any usage-capable export
+
+2005-11-28 08:14 ivan
+
+ * FS/FS/Record.pm: okay, its been tested
+
+2005-11-28 08:07 ivan
+
+ * FS/FS/part_export/radiator.pm: fix small bug in radiator export
+
+2005-11-28 07:41 ivan
+
+ * FS/FS/cust_main.pm: add debugging info to cust_main to figure out
+ where the freeze is coming from
+
+2005-11-27 13:59 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/edit/part_bill_event.cgi:
+ per-agent billco spools
+
+2005-11-22 10:29 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/process/cust_main.cgi: add
+ backend-realtime config flag, should be more intuitive for
+ guyananet
+
+2005-11-22 08:41 ivan
+
+ * FS/FS/svc_Common.pm: oops, supposed to commit this one
+
+2005-11-22 08:39 ivan
+
+ * FS/FS/svc_Common.pm: set default fields in new method, mostly for
+ svc_acct.seconds
+
+2005-11-22 05:26 ivan
+
+ * FS/FS/part_export/radiator.pm: update radiator export to deal
+ with prepaid and some other random stuff
+
+2005-11-22 01:13 ivan
+
+ * httemplate/docs/install.html: correct common misconception RIGHT
+ THERE in the docs
+
+2005-11-21 07:24 ivan
+
+ * FS/FS/: export_svc.pm, part_svc.pm, rate.pm: when editing exports
+ and there's a duplicate error, show all conflicting accounts not
+ just the ones for different customers
+
+2005-11-21 06:25 ivan
+
+ * FS/FS/part_export/: shellcommands.pm,
+ shellcommands_withdomain.pm: add usermod_nousername flag to just
+ prohibit username changes
+
+2005-11-21 04:41 ivan
+
+ * httemplate/: edit/cust_main/billing.html, view/cust_bill.cgi,
+ view/cust_main/payment_history.html: ignore blank lines in payby
+ config
+
+2005-11-21 03:04 ivan
+
+ * README: slight update to README
+
+2005-11-21 02:47 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_pay_void.pm, FS/FS/cust_refund.pm,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_pay.cgi, httemplate/search/cust_pay.cgi,
+ httemplate/search/report_cust_pay.html,
+ httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main/payment_history.html: add MCRD payment
+ type for manually processed ccards
+
+2005-11-20 22:46 ivan
+
+ * httemplate/docs/schema.dia: load schema in current dia and save,
+ should load up for people now?
+
+2005-11-20 21:18 ivan
+
+ * FS/FS/Conf.pm: add config values used by external RT integration
+
+2005-11-18 07:08 ivan
+
+ * httemplate/search/report_receivables.cgi: fix link glitch in
+ receivables reports
+
+2005-11-18 06:59 ivan
+
+ * httemplate/edit/agent_type.cgi: template-ize agent type edit and
+ add comment to package listing
+
+2005-11-18 02:58 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: update custom priorioty field
+ BS for RT 3.4.4
+
+2005-11-18 02:53 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: update custom priorioty field
+ BS for RT 3.4.4
+
+2005-11-18 01:44 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: update custom priorioty field
+ BS for RT 3.4.4
+
+2005-11-17 23:05 ivan
+
+ * README.1.5.8: slightly more info in 1.5.8 upgrade instructions
+
+2005-11-17 19:48 ivan
+
+ * FS/FS/cust_main.pm: allow expired cards to remain on file; only
+ check edits for an expired card when the # has changed
+
+2005-11-17 07:56 ivan
+
+ * FS/FS/part_export/: shellcommands.pm,
+ shellcommands_withdomain.pm: make variable description more
+ consistant wrt vars that are already shell-quoted
+
+2005-11-17 04:53 ivan
+
+ * FS/FS/: UI/Web.pm, part_svc.pm: turn off debugging
+
+2005-11-17 04:27 ivan
+
+ * README.1.5.8, FS/FS/Schema.pm: add cust_pkg2 index on
+ cust_pkg.pkgpart
+
+2005-11-17 03:15 ivan
+
+ * FS/FS/svc_acct.pm: update debuggging information for replace
+ group info with user@domain
+
+2005-11-17 03:04 ivan
+
+ * httemplate/view/svc_acct.cgi: fix service change!
+
+2005-11-17 02:14 ivan
+
+ * FS/FS/UI/Web.pm: fix konqueror bug appending nulls to XMLHTTP
+ requests!
+
+2005-11-16 05:14 ivan
+
+ * FS/FS/part_svc.pm, httemplate/index.html,
+ httemplate/browse/part_svc.cgi, Changes.1.5.8, FS/FS/UI/Web.pm,
+ httemplate/edit/bulk-cust_svc.html,
+ httemplate/edit/process/bulk-cust_svc.cgi: bulk svcpart change
+
+2005-11-12 04:19 ivan
+
+ * README.1.5.8: one last bit for 1.5.7->1.5.8 RT upgrade
+ instructions
+
+2005-11-11 17:24 ivan
+
+ * httemplate/view/cust_main/tickets.html: huh seem to have
+ overlooked this
+
+2005-11-11 17:22 ivan
+
+ * FS/FS/cust_main.pm: set payip for all payment types
+
+2005-11-11 16:44 ivan
+
+ * FS/FS/part_export/cpanel.pm: interpolation helps alot
+
+2005-11-11 16:17 ivan
+
+ * FS/FS/part_export/cpanel.pm: try using web interface scrape
+ bullshit for adding pops instead of API, as per cpanel support
+ [cPanel tickets ID# 116044]
+
+2005-11-11 06:06 ivan
+
+ * FS/FS/: cust_pkg.pm, svc_acct.pm: for prepaid packages, trigger
+ export update of RADIUS Expiration attribute when cust_pkg.bill
+ changes
+
+2005-11-10 04:47 ivan
+
+ * httemplate/search/: cust_bill_event.cgi, cust_bill_event.html:
+ add part_bill_event.payby selection to failed invoice event
+ search
+
+2005-11-10 03:36 ivan
+
+ * FS/FS/part_export/everyone_net.pm: fix password changes with
+ everyone.net
+
+2005-11-09 16:00 ivan
+
+ * httemplate/view/svc_domain.cgi: add javascript confirmation to
+ unaudited domain deletion, add record being deleted to record
+ deletion popup
+
+2005-11-09 12:48 ivan
+
+ * httemplate/docs/install.html: closing paren
+
+2005-11-07 18:16 ivan
+
+ * httemplate/docs/admin.html: bah
+
+2005-11-07 14:07 ivan
+
+ * httemplate/search/cust_pay.cgi: fix Discover card report, closes:
+ Bug#1270
+
+2005-11-04 03:43 ivan
+
+ * httemplate/elements/xmlhttp.html: oops, typo applying patch
+
+2005-11-04 03:31 ivan
+
+ * CREDITS, httemplate/elements/xmlhttp.html: apply patch from Scott
+ Edwards to show mason errors received from XMLHTTP requests
+
+2005-11-02 13:18 ivan
+
+ * FS/FS/cust_bill.pm: spool invoice to billco if no other
+ destinations are set!
+
+2005-10-31 21:32 ivan
+
+ * FS/FS/: cust_bill.pm: yarg
+
+2005-10-31 21:27 ivan
+
+ * FS/FS/cust_bill.pm: only send to specific destinations, oops!
+
+2005-10-31 21:21 ivan
+
+ * bin/billco-upload: do the zip
+
+2005-10-31 21:14 ivan
+
+ * httemplate/edit/part_bill_event.cgi: add option for spool_csv
+ events to apply only to a specific destination type (i.e. postal
+ only)
+
+2005-10-31 19:16 ivan
+
+ * bin/billco-upload: good nuff for 11/1
+
+2005-10-31 19:15 ivan
+
+ * httemplate/edit/part_bill_event.cgi, FS/FS/cust_bill.pm: add
+ billco format option to FTP invoice send, add invoice event to
+ spool one giant (pair of) CSV files in addition to FTPing them
+ individually
+
+2005-10-28 10:10 ivan
+
+ * bin/billco-upload: beginning of quick billco zip & upload tool
+
+2005-10-28 04:56 ivan
+
+ * httemplate/search/cust_bill_event.cgi: don't show 'N/A'
+ statustext as a failed billing event
+
+2005-10-27 10:04 ivan
+
+ * httemplate/elements/select-taxclass.html: extraneous '; noticed
+ by joe@surferz
+
+2005-10-27 08:48 ivan
+
+ * httemplate/search/cust_pay.cgi: fix from joe @ surferz: lines 59
+ and 60 had the wrote quote. they had single quote where double
+ was needed...
+
+2005-10-24 04:59 ivan
+
+ * httemplate/edit/rate.cgi: optimize SQL on rate edit screen
+
+2005-10-24 04:56 ivan
+
+ * README.1.5.8, FS/FS/Schema.pm, httemplate/edit/process/rate.cgi,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/xmlhttp.html: fix rate plan editing with new
+ xmlhttp progressbar - use POST instead of GET. also optimize SQL
+ on rate search screen
+
+2005-10-21 08:21 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_pay_void.pm, FS/FS/cust_refund.pm,
+ httemplate/edit/cust_main.cgi, httemplate/edit/cust_pay.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_cust_pay.html,
+ httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main/payment_history.html: add CASH and WEST
+ payment types (payments only, not cust_main.payby)
+
+2005-10-21 06:15 ivan
+
+ * conf/invoice_html: brainfart
+
+2005-10-21 05:50 ivan
+
+ * conf/invoice_html: i thought i fixed this already
+
+2005-10-20 05:30 ivan
+
+ * FS/FS/: cust_pkg.pm, part_pkg/flat.pm: fix credit for remaining
+ service. fuck Date::Manip
+
+2005-10-16 23:46 ivan
+
+ * FS/bin/freeside-sqlradius-reset: set any fixed usergroup before
+ exporting so it'll export even if all svc_acct records don't have
+ the group yet
+
+2005-10-16 23:03 ivan
+
+ * FS/FS/part_svc.pm, httemplate/edit/part_svc.cgi: fix RADIUS
+ usergroup editing
+
+2005-10-16 08:02 ivan
+
+ * bin/bind.export: and make .HEADER optional for slaves too
+
+2005-10-16 07:59 ivan
+
+ * bin/bind.export: don't error out if there's no HEADER file, just
+ produce a useable snippet anyway
+
+2005-10-16 07:04 ivan
+
+ * FS/FS/Conf.pm, FS/FS/domain_record.pm, bin/bind.import: add
+ zone-underscore config file, update bind.import to use
+ command-line options instead of ask for input
+
+2005-10-15 06:48 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: don't error out when
+ ticket_system-default_queueid hasn't been set yet
+
+2005-10-15 06:40 ivan
+
+ * FS/FS/Conf.pm: make sure config still works if no ticket system
+ is configured...
+
+2005-10-15 06:37 ivan
+
+ * FS/FS/Conf.pm: make sure config still works if no ticket system
+ is configured...
+
+2005-10-15 05:58 ivan
+
+ * bin/backup-dvd: adding quick backup-to-dvd script
+
+2005-10-15 04:29 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Schema.pm, FS/FS/TicketSystem.pm,
+ FS/FS/agent.pm, FS/FS/TicketSystem/RT_External.pm,
+ FS/FS/TicketSystem/RT_Internal.pm, httemplate/browse/agent.cgi,
+ httemplate/edit/agent.cgi, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi: agent option to select RT queue
+
+2005-10-15 04:25 ivan
+
+ * README.1.5.8: upgrade instructions for new RT verison
+
+2005-10-15 04:13 ivan
+
+ * README.1.5.8, rt/html/Elements/Header, rt/html/NoAuth/webrt.css:
+ land RT 3.4.4 on HEAD
+
+2005-10-15 02:33 ivan
+
+ * rt/: HOWTO/README, HOWTO/change.txt, HOWTO/release.txt,
+ HOWTO/version-control.txt, etc/RT_SiteConfig.pm,
+ html/Admin/Global/CustomField.html,
+ html/Admin/Global/CustomFields.html, html/Elements/Footer,
+ html/Elements/Header, html/Elements/Menu,
+ html/Elements/PageLayout, html/Elements/SimpleSearch,
+ html/Elements/Tabs, html/Elements/CollectionAsTable/Row,
+ html/NoAuth/webrt.css, html/NoAuth/images/back_home.gif,
+ html/NoAuth/images/head_requestracker.gif,
+ html/NoAuth/images/rt.jpg, html/NoAuth/images/spacer.gif,
+ html/NoAuth/images/squares_blue.gif,
+ html/Ticket/Elements/ShowSummary, html/Ticket/Elements/Tabs,
+ lib/RT/TicketCustomFieldValue.pm,
+ lib/RT/TicketCustomFieldValue_Overlay.pm,
+ lib/RT/TicketCustomFieldValues.pm,
+ lib/RT/TicketCustomFieldValues_Overlay.pm,
+ lib/RT/I18N/en_malkovich.po, lib/t/00smoke.t.in,
+ lib/t/01harness.t.in, lib/t/02regression.t.in, lib/t/03web.pl.in,
+ lib/t/04_send_email.pl.in, lib/t/05cronsupport.pl.in,
+ lib/t/regression/00placeholder, sbin/rt-setup-database.in:
+ landing rt 3.4.4 on HEAD
+
+2005-10-15 02:09 ivan
+
+ * rt/: docs/design_docs/realflow.txt,
+ docs/design_docs/3.3-schema-redesign.txt,
+ docs/design_docs/rt-mvc, sbin/rt-dump-database.in,
+ html/Search/Elements/SelectGroup, html/Admin/autohandler,
+ html/Download/CustomFieldValue/dhandler,
+ html/Download/Tabular/dhandler, html/Search/Elements/EditQuery,
+ html/Admin/CustomFields/GroupRights.html,
+ html/Admin/Global/CustomFields/Groups.html,
+ html/Admin/Global/CustomFields/Queue-Tickets.html,
+ html/Admin/Global/CustomFields/Queue-Transactions.html,
+ html/Admin/Global/CustomFields/Users.html,
+ html/Admin/Global/CustomFields/index.html,
+ html/Admin/Groups/CustomFields.html,
+ html/Admin/Groups/History.html,
+ html/Admin/CustomFields/Modify.html,
+ html/Admin/CustomFields/Objects.html,
+ html/Admin/CustomFields/UserRights.html,
+ html/Admin/CustomFields/index.html,
+ html/Admin/Users/CustomFields.html,
+ html/Admin/Users/History.html, html/Admin/Users/Memberships.html,
+ html/Admin/Elements/CustomFieldTabs,
+ html/Admin/Elements/SelectCustomFieldLookupType,
+ html/Admin/Elements/GlobalCustomFieldTabs,
+ html/Admin/Elements/ObjectCustomFields,
+ html/Admin/Elements/PickCustomFields,
+ html/Admin/Elements/PickObjects,
+ html/SelfService/CreateTicketInQueue.html,
+ html/Elements/EditCustomField,
+ html/Elements/EditCustomFieldImage,
+ html/Elements/EditCustomFieldBinary,
+ html/Elements/EditCustomFieldSelect,
+ html/Elements/ShowCustomFieldBinary,
+ html/Elements/ShowCustomFieldImage,
+ html/Elements/ShowCustomFieldWikitext,
+ html/Elements/ShowCustomFields,
+ html/Elements/EditCustomFieldFreeform,
+ html/Elements/EditCustomFieldText,
+ html/Elements/EditCustomFieldWikitext,
+ html/Elements/ShowMemberships, lib/t/setup_regression.t,
+ lib/t/create_data.pl, lib/t/regression/01ticket_link_searching.t,
+ lib/t/regression/02basic_web.t,
+ lib/t/regression/03web_compiliation_errors.t,
+ lib/t/regression/05cronsupport.t, lib/t/regression/07acl.t,
+ lib/t/regression/08web_cf_access.t,
+ lib/t/regression/09record_cf_api.t, lib/t/regression/10merge.t,
+ lib/t/regression/11-template-insert.t,
+ lib/t/regression/12-search.t,
+ lib/t/regression/13-attribute-tests.t,
+ lib/t/regression/14merge.t,
+ lib/t/regression/16-transaction_cf_tests.t,
+ lib/t/regression/17multiple_deleg_revocation.t,
+ lib/t/regression/19-rtname.t, lib/t/regression/20savedsearch.t,
+ lib/t/regression/21query-builder.t,
+ lib/t/regression/22search_tix_by_txn.t,
+ lib/t/regression/04send_email.t,
+ lib/t/regression/06mailgateway.t, lib/t/regression/07rights.t,
+ lib/t/regression/15cf_single_values_are_single.t,
+ lib/t/regression/18stale_delegations_cleanup.t,
+ lib/RT/SavedSearch.pm, lib/RT/ObjectCustomFields.pm,
+ lib/RT/CustomFieldValue_Overlay.pm, lib/RT/ObjectCustomField.pm,
+ lib/RT/ObjectCustomFields_Overlay.pm, lib/RT/SavedSearches.pm,
+ lib/RT/ObjectCustomFieldValues.pm,
+ lib/RT/ObjectCustomFieldValue.pm,
+ lib/RT/ObjectCustomField_Overlay.pm,
+ lib/RT/ObjectCustomFieldValues_Overlay.pm,
+ lib/RT/ObjectCustomFieldValue_Overlay.pm, lib/RT/I18N/pl.po,
+ lib/RT/I18N/id.po, lib/RT/URI/t.pm,
+ lib/RT/Interface/Web/QueryBuilder.pm,
+ lib/RT/Interface/Web/Standalone.pm,
+ lib/RT/Interface/Web/QueryBuilder/Tree.pm,
+ etc/upgrade/3.3.0/acl.Informix, etc/upgrade/3.3.0/acl.Oracle,
+ etc/upgrade/3.3.0/acl.Pg, etc/upgrade/3.3.0/acl.SQLite,
+ etc/upgrade/3.3.0/acl.mysql, etc/upgrade/3.3.0/content,
+ etc/upgrade/3.3.0/schema.Oracle, etc/upgrade/3.3.0/schema.Pg,
+ etc/upgrade/3.3.0/schema.mysql, etc/upgrade/3.3.11/acl.Oracle,
+ etc/upgrade/3.3.11/acl.Pg, etc/upgrade/3.3.11/acl.SQLite,
+ etc/upgrade/3.3.11/acl.mysql, etc/upgrade/3.3.11/content,
+ etc/upgrade/3.3.11/schema.Oracle, etc/upgrade/3.3.11/schema.Pg,
+ etc/upgrade/3.3.11/schema.SQLite,
+ etc/upgrade/3.3.11/schema.mysql: Initial revision
+
+2005-10-13 14:16 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/edit/svc_acct.cgi: Fix 'can't
+ change uid' error when the account *has* a uid but
+ svc_acct-edit_uid isn't turned on
+
+2005-10-12 05:02 ivan
+
+ * httemplate/misc/: batch-cust_pay.html,
+ process/batch-cust_pay.cgi: change button to say "post payment
+ batch" and main error message to indicate the whole batch should
+ be resubmitted, as per feedback from lewis
+
+2005-10-12 02:51 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix package customize losing
+ services
+
+2005-10-12 01:57 ivan
+
+ * FS/FS/part_export/cpanel.pm: add debugging to cpanel export
+
+2005-10-10 09:06 ivan
+
+ * FS/FS/part_export/everyone_net.pm: oops, that should fix
+ suspension problem
+
+2005-10-10 05:20 ivan
+
+ * Changes.1.5.8, README.1.5.8, FS/FS/cust_pay.pm, htetc/global.asa,
+ htetc/handler.pl, httemplate/index.html,
+ httemplate/docs/upgrade10.html,
+ httemplate/misc/batch-cust_pay.html,
+ httemplate/misc/xmlhttp-cust_main-search.cgi,
+ httemplate/misc/process/batch-cust_pay.cgi,
+ httemplate/search/cust_pay.cgi: updated quick payment entry
+
+2005-10-08 06:45 ivan
+
+ * httemplate/misc/batch-cust_pay.html: quick payment entry
+ javascript tested & working IE/firefix/konq
+
+2005-10-07 17:47 ivan
+
+ * httemplate/: edit/part_pkg.cgi, edit/process/part_pkg.cgi,
+ edit/process/quick-charge.cgi, elements/select-taxclass.html,
+ view/cust_main/quick-charge.html: fix tax class selection in
+ package add/edit too
+
+2005-10-07 16:28 ivan
+
+ * conf/invoice_latex: allow more width for return address, stuff is
+ wrapping
+
+2005-10-06 22:03 ivan
+
+ * README.1.5.8: need new B:CC
+
+2005-10-06 21:50 ivan
+
+ * httemplate/view/cust_main/billing.html: mask out echeck account
+ #s too
+
+2005-10-06 21:48 ivan
+
+ * FS/FS/cust_main.pm: fix on-demand credit cards not being masked
+ in UI. i believe huntsburg is in the doghouse for this one :)
+
+2005-10-06 19:25 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_pkg.pm,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/view/cust_main/quick-charge.html: add
+ require_taxclasses config flag
+
+2005-10-06 16:09 ivan
+
+ * httemplate/view/cust_bill-logo.cgi: really use default logo if
+ the agent-specific one isn't found
+
+2005-10-06 16:07 ivan
+
+ * httemplate/view/cust_bill-logo.cgi: use default logo if the
+ agent-specific one isn't found
+
+2005-10-06 16:03 ivan
+
+ * httemplate/view/cust_bill-logo.cgi: use default logo if the
+ agent-specific one isn't found
+
+2005-10-06 13:35 ivan
+
+ * FS/FS/part_export/everyone_net.pm: add debugging option to
+ everyone_net export
+
+2005-10-06 00:34 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_pay_refund.pm,
+ httemplate/view/cust_main/payment_history.html: add cc-void
+ option
+
+2005-10-05 18:40 ivan
+
+ * httemplate/edit/cust_main.cgi: fix bug with IE and advertising
+ sources (refnum) - needed to make sure the SELECT OPTIONs have
+ explicitly specified VALUEs
+
+2005-10-04 13:27 ivan
+
+ * FS/FS/part_export/everyone_net.pm: fix small error with
+ everyone.net export
+
+2005-10-02 18:41 ivan
+
+ * FS/FS/cust_svc.pm, FS/FS/part_svc.pm, FS/FS/svc_acct.pm,
+ httemplate/view/svc_acct.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/elements/small_custview.html, FS/FS/Conf.pm: update
+ account view and edit: convert to proper templates, make sure
+ usage information displays for any usage-capable export, add
+ ability to edit uid/gid
+
+2005-10-02 07:04 ivan
+
+ * httemplate/docs/install.html: fix leading % causing Mason to barf
+
+2005-10-02 00:09 ivan
+
+ * Makefile, htetc/handler.pl, init.d/freeside-init: add dev make
+ target for quick iterative development
+
+2005-09-29 13:19 ivan
+
+ * FS/FS/svc_acct.pm: make sure there is an expiraiton date to set
+ as well
+
+2005-09-28 11:27 ivan
+
+ * FS/FS/cust_main.pm: recognize hourly frequency in cust_main->bill
+
+2005-09-25 01:20 ivan
+
+ * httemplate/view/cust_main.cgi: this css did weird things under IE
+
+2005-09-25 01:13 ivan
+
+ * CREDITS, Changes.1.5.8, JSRS-LICENSE, README.1.5.7,
+ FS/FS/UI/Web.pm, httemplate/edit/cust_main/select-country.html,
+ httemplate/edit/cust_main/select-county.html,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/edit/process/rate.cgi,
+ httemplate/elements/jsrsServer.html,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/progress-popup.html,
+ httemplate/elements/xmlhttp.html, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: get rid of JSRS iframe foo for
+ progress bar, use XMLHTTPRequest instead. really should have
+ done that in the first place. JSON will wait until another
+ day...
+
+2005-09-24 15:53 ivan
+
+ * FS/FS/cust_main.pm: parse paybatch order number with dashes
+ correctly
+
+2005-09-22 15:25 ivan
+
+ * rt/lib/RT/URI/freeside/Internal.pm: should fix problem with empty
+ (dir-less) Conf showing up
+
+2005-09-21 05:47 ivan
+
+ * FS/FS/svc_acct.pm, FS/MANIFEST, FS/FS/Conf.pm, FS/FS/Record.pm,
+ FS/bin/freeside-prepaidd, httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/view/cust_main/packages.html, init.d/freeside-init,
+ FS/bin/freeside-daily: add prepaid support which sets RADIUS
+ Expiration attribute, update customer view package UI
+
+2005-09-16 03:10 ivan
+
+ * FS/FS/cust_main.pm: tyop
+
+2005-09-16 01:18 ivan
+
+ * FS/FS/cust_main.pm: with taxclasses, might have multiple records
+ for a state/county/country
+
+2005-09-14 04:01 ivan
+
+ * FS/t/agent_payment_gateway.t, FS/t/banned_pay.t,
+ FS/t/cancel_reason.t, FS/t/payment_gateway.t,
+ FS/t/payment_gateway_option.t, bin/generate-table-module: fix
+ autogenerated simple test
+
+2005-09-13 13:12 ivan
+
+ * httemplate/search/elements/search.html: fix redirect with single
+ item returned from search results and a coderef redirect
+
+2005-09-10 07:50 ivan
+
+ * CREDITS, httemplate/edit/cust_main/contact.html,
+ httemplate/edit/cust_main/select-country.html,
+ httemplate/edit/cust_main/select-county.html,
+ httemplate/edit/cust_main/select-state.html,
+ httemplate/edit/cust_main.cgi, httemplate/elements/xmlhttp.html,
+ httemplate/misc/counties.cgi, httemplate/misc/states.cgi:
+ ajax-style xmlhttprequest state/county/country selector!
+
+2005-09-08 12:15 ivan
+
+ * FS/FS/part_export/radiator.pm: MySQL is case sensitive about
+ table names! huh
+
+2005-09-08 01:50 ivan
+
+ * httemplate/edit/cust_main.cgi: fix dropping of payname
+
+2005-09-07 23:52 ivan
+
+ * httemplate/autohandler: don't need 4k of newlines anymore,
+ H:W:SelectLayers works better
+
+2005-09-07 15:52 ivan
+
+ * FS/FS/part_pkg.pm: add hourly frequency
+
+2005-09-07 15:04 ivan
+
+ * bin/generate-raddb: list current dictionary sources in example so
+ i don't forget
+
+2005-09-07 15:02 ivan
+
+ * FS/FS/raddb.pm: update with dictionaries from freeradius 1.0.4
+ plus dictionary.ip3networks
+
+2005-09-07 05:56 ivan
+
+ * FS/FS/Schema.pm: define username_len so the default add account
+ screen doesn't have a tiny username field (when usernamemax is
+ not defined)
+
+2005-09-07 05:48 ivan
+
+ * httemplate/edit/svc_acct.cgi: fix silly bug sizing username field
+ when adding an account (and usernamemax is not set)
+
+2005-09-07 05:44 ivan
+
+ * httemplate/edit/svc_acct.cgi: fix silly bug sizing username field
+ when adding an account (and username max is not set)
+
+2005-09-07 05:38 ivan
+
+ * httemplate/view/cust_main.cgi: oops, still need areyousure
+ javascript for some sub-bits of the page (package unprovisioning
+ and cancellation, bunch of payment history stuff)
+
+2005-09-07 03:40 ivan
+
+ * FS/FS/: part_svc.pm, part_virtual_field.pm: import dbdef from
+ FS::Schema instead of calling $FS::Record::dbdef directly
+
+2005-09-07 03:25 ivan
+
+ * FS/FS/option_Common.pm: fix bug with new option_Common stuff,
+ forgot to prefix FS::
+
+2005-09-07 03:16 ivan
+
+ * FS/FS/part_export/cpanel.pm: remote access key is a big long
+ thing
+
+2005-09-07 02:37 ivan
+
+ * Changes.1.5.8, FS/FS/part_export/cpanel.pm,
+ eg/export_template.pm: add cpanel export
+
+2005-09-06 14:58 ivan
+
+ * FS/FS/Conf.pm: document variables available in
+ payment_receipt_email
+
+2005-08-27 01:46 ivan
+
+ * FS/MANIFEST, FS/FS/Schema.pm, FS/FS/banned_pay.pm,
+ FS/FS/cancel_reason.pm, FS/FS/cust_main.pm, FS/t/banned_pay.t,
+ FS/t/cancel_reason.t, bin/generate-table-module,
+ httemplate/view/cust_main.cgi,
+ httemplate/misc/cust_main-cancel.cgi: add banned credit card /
+ ACH table, re-do cancel popup to have a checkbox to ban payinfo
+
+2005-08-24 07:07 ivan
+
+ * README.1.5.8, httemplate/docs/upgrade10.html: need
+ H:W:SelectLayers 0.05
+
+2005-08-24 06:47 ivan
+
+ * httemplate/edit/cust_main/billing.html: fix size of cvv2 help
+ popup
+
+2005-08-24 06:22 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/billing.html,
+ httemplate/edit/cust_main/contact.html, Changes.1.5.8,
+ FS/FS/cust_main.pm, FS/FS/cust_main_county.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ httemplate/docs/ach.html, httemplate/docs/cvv2.html,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/elements/overlibmws_draggable.js,
+ httemplate/elements/overlibmws_iframe.js,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/select-month_year.html,
+ httemplate/images/cvv2.png, httemplate/images/cvv2_amex.png,
+ httemplate/view/cust_main/billing.html: customer edit: abstract
+ out billing info to billing.html, re-do payment type selection
+ with HTML::Widgets::SelectLayers, add Switch/Solo/Maestro support
+ for start date & issue #. customer view: re-order fields for
+ consistency. selfservice API: support paystart_month,
+ paystart_year, payissue and payip in MyAccount::process_payment
+ and ::edit_info and Signup::new_customer,
+ FS::cust_main::realtime_bop: support paystart_month paystart_year
+ payissue payip fields
+
+2005-08-23 05:38 ivan
+
+ * httemplate/edit/part_svc.cgi: fix bug with service editing caused
+ by moving dbdef stuff around
+
+2005-08-18 00:58 ivan
+
+ * FS/FS/cust_main.pm: add taxclass kludge to gateway overrides, fix
+ parsing of new-style paybatch
+
+2005-08-17 23:46 ivan
+
+ * install/debian/3.1/INSTALL: slight adjustments to deb install for
+ latest 1.5.8cvs
+
+2005-08-17 22:41 ivan
+
+ * httemplate/edit/process/agent_payment_gateway.html: hopefully
+ this is the last missing file
+
+2005-08-17 22:12 ivan
+
+ * httemplate/edit/process/payment_gateway.html: oops another
+ missing file
+
+2005-08-17 21:16 ivan
+
+ * FS/FS/agent_payment_gateway.pm: missing file
+
+2005-08-17 15:23 ivan
+
+ * FS/FS/Record.pm, FS/FS/Schema.pm, FS/FS/cust_main.pm,
+ FS/FS/option_Common.pm, FS/FS/part_export.pm,
+ FS/FS/part_export_option.pm, FS/FS/part_pkg.pm,
+ FS/FS/payment_gateway.pm, FS/FS/payment_gateway_option.pm,
+ FS/bin/freeside-setup, FS/bin/freeside-upgrade, README.1.5.8,
+ SCHEMA_CHANGE, FS/FS.pm, FS/MANIFEST, FS/t/option_Common.t,
+ FS/t/payment_gateway.t, FS/t/payment_gateway_option.t,
+ bin/generate-table-module, htetc/global.asa, htetc/handler.pl,
+ httemplate/index.html, httemplate/browse/agent.cgi,
+ httemplate/browse/payment_gateway.html,
+ httemplate/docs/upgrade10.html,
+ httemplate/edit/agent_payment_gateway.html,
+ httemplate/edit/payment_gateway.html: infrastructure for easier
+ schema changes, and: add payment_gateway, payment_gateway_option
+ and agent_payment_gateway tables, add paystart_month,
+ paystart_year, payissue and payip fields to cust_main, add
+ preliminary gateway and gateway override editing to web UI, use
+ payment gateway override when processing payments (card type, not
+ taxclass yet)
+
+2005-08-14 18:55 ivan
+
+ * FS/FS/UI/Web.pm: fix brainfart parsing end dates, closes:
+ Bug#1248
+
+2005-08-09 14:38 ivan
+
+ * Changes.1.5.8, FS/FS/part_export/radiator.pm,
+ FS/FS/part_export/sqlradius.pm, FS/t/part_export-radiator.t,
+ FS/FS/part_export/sqlradius_withdomain.pm: add native Radiator
+ export
+
+2005-08-08 08:15 ivan
+
+ * Changes.1.5.8, FS/FS/part_export/everyone_net.pm: add export to
+ everyone.net outsource mail service
+
+2005-08-07 20:15 ivan
+
+ * httemplate/docs/selfservice.html: add some docs on
+ signup_server-payby and -realtime configuration values
+
+2005-08-06 17:41 ivan
+
+ * FS/FS/part_export/forward_shellcommands.pm: update
+ forward_shellcommands export to know about literal source
+ addresses, closes: Bug#1246
+
+2005-08-06 17:40 ivan
+
+ * Changes.1.5.8, FS/FS/agent.pm, FS/FS/cust_pkg.pm,
+ FS/FS/cust_svc.pm, FS/FS/UI/Web.pm, httemplate/browse/agent.cgi,
+ httemplate/search/cust_pay.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/search/elements/search.html: move cust_pkg search to
+ new template, add active/suspended/cancelled customer packages to
+ agent browse
+
+2005-08-04 17:57 ivan
+
+ * httemplate/search/cust_credit.html: fix credit searches by otaker
+
+2005-08-04 01:39 ivan
+
+ * httemplate/docs/install.html: add IPC::Run3 and instructions for
+ adding fs_queue and fs_selfservice users to install docs
+
+2005-08-03 18:42 ivan
+
+ * Makefile: don't use install -D flag, doesn't work on bsd
+
+2005-08-03 00:38 ivan
+
+ * FS/FS/cust_bill.pm: eliminate scary (but harmless) "Use of
+ uninitalized value in length" warnings
+
+2005-08-02 19:23 ivan
+
+ * FS/FS/part_export/: domain_shellcommands.pm,
+ forward_shellcommands.pm, www_shellcommands.pm: don't try to run
+ blank commands for non-svc_acct shellcommand exports too
+
+2005-08-02 12:17 khoff
+
+ * FS/FS/h_cust_svc.pm: Only complain, not die, if we can't find a
+ svc_x record for an h_cust_svc record.
+
+2005-07-14 04:55 ivan
+
+ * FS/FS/cust_main.pm: oops, fix last minute bug with new
+ configurable customer fields on reports
+
+2005-07-14 04:46 ivan
+
+ * FS/FS/: svc_Common.pm, UI/Web.pm: clean up some leftover bits
+ from cust-fields work
+
+2005-07-14 04:31 ivan
+
+ * httemplate/: index.html, search/svc_acct.cgi,
+ search/svc_forward.cgi: add unlinked mail forward (svc_forward)
+ report
+
+2005-07-14 04:18 ivan
+
+ * httemplate/search/cust_bill.html: move account search
+ (httemplate/search/svc_acct.cgi) to new template, cust-fields
+ configuration value to control which customer fields are shown on
+ reports
+
+2005-07-14 03:52 ivan
+
+ * Changes.1.5.8, FS/MANIFEST, FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_event.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_Mixin.pm, FS/FS/cust_pay.pm,
+ FS/FS/svc_Common.pm, FS/FS/UI/Web.pm, FS/t/cust_main_Mixin.t,
+ httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/svc_acct.cgi, httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_forward.cgi, httemplate/search/svc_www.cgi,
+ httemplate/search/elements/search.html: move account search
+ (httemplate/search/svc_acct.cgi) to new template, cust-fields
+ configuration value to control which customer fields are shown on
+ reports
+
+2005-07-12 04:54 ivan
+
+ * README.1.5.7: add alternative for very old Pg
+
+2005-07-12 02:31 ivan
+
+ * httemplate/: browse/part_pkg.cgi, view/cust_pkg.cgi: <rjbs> More
+ of the same: these patches make it safer to subclass
+ FS::part_pkg's pkg_svc method by eliminating qsearches on table
+ pkg_svc.
+
+2005-07-12 02:22 ivan
+
+ * httemplate/edit/part_pkg.cgi: <rjbs> This patch is part of my
+ continuing effort to avoid using SQL and qsearch from templates
+ to find the pkg_svc records for a package.
+
+2005-07-12 02:13 ivan
+
+ * CREDITS, FS/FS/Record.pm: patch from rjbs to add by_key
+ contructor to Record.pm
+
+2005-07-12 02:11 ivan
+
+ * Makefile: okay, really enable RT by default for good now
+
+2005-07-11 07:15 ivan
+
+ * bin/: rate.import, rt-drop-tables: adding rt-drop-tables
+
+2005-07-11 06:01 ivan
+
+ * Makefile: new server
+
+2005-07-11 05:53 ivan
+
+ * httemplate/docs/: index.html, upgrade10.html: note alternate
+ instructions for 0pre6->7
+
+2005-07-11 05:39 ivan
+
+ * Changelog, Changes.1.5.7: s/ANNOUNCE/Changelog/
+
+2005-07-11 05:23 ivan
+
+ * install/freebsd/: INSTALL, ports: freebsd install update i guess
+
+2005-07-11 05:22 ivan
+
+ * bin/postfix.export: fix regex
+
+2005-07-11 05:22 ivan
+
+ * httemplate/browse/queue.cgi: template
+
+2005-07-11 05:21 ivan
+
+ * Makefile: probably best to keep RT disabled by default, at least
+ for this release
+
+2005-07-11 05:09 ivan
+
+ * ANNOUNCE.1.5: last bits
+
+2005-07-11 03:58 ivan
+
+ * FS/t/ClientAPI_SessionCache.t:
+ s/ClientAPI::SessionCache/ClientAPI_SessionCache/ noticed by rjbs
+
+2005-07-11 02:49 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: bug fix for error message on
+ session expiration from Randall Lucas <rlucas@tercent.net>,
+ thanks!
+
+2005-07-09 08:41 ivan
+
+ * FS/FS/cust_bill.pm: fix silly bug preventing html invoicing from
+ finding their logo
+
+2005-07-09 03:55 ivan
+
+ * httemplate/edit/cust_pay.cgi: get rid of the godawful halfass
+ "invoice" on the post payment screen when posting against a
+ specific invoice, replace with having useless "Auto-apply to
+ invoices" box actually show the payment will be applied to one
+ invoice only... closes: Bug#1241
+
+2005-07-09 03:36 ivan
+
+ * FS/FS/: cust_bill.pm, cust_bill_pkg.pm, part_export/sqlradius.pm,
+ part_pkg/flat.pm, part_pkg/flat_comission.pm,
+ part_pkg/flat_comission_cust.pm, part_pkg/flat_comission_pkg.pm,
+ part_pkg/flat_delayed.pm, part_pkg/prepaid.pm,
+ part_pkg/prorate.pm, part_pkg/sesmon_hour.pm,
+ part_pkg/sesmon_minute.pm, part_pkg/sql_external.pm,
+ part_pkg/sql_generic.pm, part_pkg/sqlradacct_hour.pm,
+ part_pkg/subscription.pm, part_pkg/voip_sqlradacct.pm: add desc
+ method to cust_bill_pkg and use it in cust_bill... this should
+ help with any *other* cust_bill_pkg.pkgnum == -1 stuff that needs
+ to be sorted out
+
+2005-07-08 16:06 ivan
+
+ * FS/bin/freeside-daily: fix bug with new efficient
+ customer-finding code. sql isn't perl, null != 0
+
+2005-07-05 14:46 ivan
+
+ * httemplate/docs/install-rt.html: tyop
+
+2005-06-30 06:32 ivan
+
+ * FS/FS/Misc.pm: pod error
+
+2005-06-30 06:20 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add username-percent config option
+
+2005-06-30 05:44 ivan
+
+ * FS/FS/cust_main.pm: oops, really fix error with new prepaid card
+ foo
+
+2005-06-21 20:54 ivan
+
+ * httemplate/docs/upgrade10.html, install/debian/3.1/INSTALL: add
+ IPC::Run3 to install docs
+
+2005-06-16 22:31 ivan
+
+ * httemplate/misc/process/link.cgi: fix preference sort order for
+ linking: sort unaudited services first, secondary sort by svcaprt
+
+2005-06-16 22:07 ivan
+
+ * httemplate/misc/process/link.cgi: add more info to debugging
+
+2005-06-16 22:04 ivan
+
+ * httemplate/misc/process/link.cgi: fix debugging
+
+2005-06-16 21:42 ivan
+
+ * httemplate/misc/process/link.cgi: add debugging for accounts
+ picked to pick
+
+2005-06-14 21:46 ivan
+
+ * README.1.5.7, FS/FS/cust_bill.pm: better error reporting for
+ actual errors from lpr command
+
+2005-06-14 19:31 ivan
+
+ * FS/FS/cust_main.pm: fix error recharging w/prepaid card caused by
+ rounding off of money value, closes: Bug#1237
+
+2005-06-14 17:44 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/search/cust_bill.html: add
+ reprint/fax/email links to invoice search results
+
+2005-06-09 15:40 ivan
+
+ * httemplate/search/cust_bill_event.cgi, FS/FS/cust_bill.pm,
+ httemplate/index.html, httemplate/misc/email_invoice_events.cgi,
+ httemplate/misc/email_invoices.cgi,
+ httemplate/misc/fax_invoice_events.cgi,
+ httemplate/misc/fax_invoices.cgi,
+ httemplate/misc/print_invoice_events.cgi,
+ httemplate/misc/print_invoices.cgi,
+ httemplate/search/cust_bill.html,
+ httemplate/search/report_cust_bill.html: advanced invoice serach,
+ groundwork to add reprint/fax/email links to invoice search
+ results
+
+2005-06-09 13:26 ivan
+
+ * httemplate/browse/part_pkg.cgi: tiny refactor patch from rjbs: It
+ changes the service listing to use $part_pkg->pkg_svc instead of
+ a qsearch, which means that the listing will still work if
+ pkg_svc has been subclassed.
+
+2005-06-09 13:16 ivan
+
+ * FS/FS/cust_svc.pm: documentation fix, noticed by rjbs
+
+2005-06-09 02:15 ivan
+
+ * FS/FS/part_pkg.pm: don't rebless if we're already in the plan
+ subclass, fixes pkg customize link
+
+2005-06-09 00:19 ivan
+
+ * FS/bin/freeside-daily: declare new $opt_a
+
+2005-06-09 00:13 ivan
+
+ * FS/bin/freeside-daily: significant speedup from only selected
+ customers with outstanding packages or invoice events in the
+ initial select, and add -a flag for agentnum
+
+2005-06-08 23:56 ivan
+
+ * FS/FS/cust_bill.pm, conf/invoice_html,
+ httemplate/view/cust_bill-logo.cgi: agent-specific logos for html
+ invoices too
+
+2005-06-08 23:36 ivan
+
+ * FS/FS/: cust_bill.pm, part_bill_event.pm: and make
+ (html|latex)(small)?footer optionall per-agent too
+
+2005-06-08 23:22 ivan
+
+ * FS/FS/cust_bill.pm: more sane regex
+
+2005-06-08 23:14 ivan
+
+ * FS/FS/: cust_bill.pm: ugh, hopefully fixup agent_plandata regex
+ for multiple agents
+
+2005-06-08 22:59 ivan
+
+ * FS/FS/: cust_bill.pm: make sure invoice_(latex|html)returnaddress
+ is configurable per-agent
+
+2005-06-08 22:34 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/part_bill_event.pm,
+ httemplate/edit/part_bill_event.cgi: add multiple agent selection
+ to agent-specific invoicing
+
+2005-06-08 17:18 ivan
+
+ * FS/FS/cust_pay.pm: add ignore_noapply flag to make sure payments
+ are forced in anyway on import
+
+2005-06-08 14:52 ivan
+
+ * FS/FS/cust_bill_pkg.pm: last bit to allow -1 for non-pkg, non-tax
+ line items
+
+2005-06-08 02:03 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/agent_delete_svc.html,
+ fs_selfservice/FS-SelfService/cgi/delete_svc.html,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_external.html,
+ fs_selfservice/FS-SelfService/cgi/provision.html,
+ fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/recharge_prepay.html,
+ fs_selfservice/FS-SelfService/cgi/recharge_results.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_invoice.html,
+ httemplate/view/svc_acct.cgi: prepaid card recharge
+
+2005-06-07 14:02 ivan
+
+ * FS/FS/Misc.pm: debugging output change in send_email
+
+2005-06-06 13:07 ivan
+
+ * FS/FS/cust_bill.pm: eek, fix silly problem in invoice sending
+ refactoring
+
+2005-06-06 12:54 ivan
+
+ * FS/FS/Misc.pm: some additional warnings
+
+2005-06-06 10:00 ivan
+
+ * FS/FS/Misc.pm: fix message ID generation for ancient perl, bah
+
+2005-06-02 18:51 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: argh. this should finally fix
+ the last of the Internal vs External breakage i hope
+
+2005-06-02 02:36 ivan
+
+ * httemplate/search/cust_bill_event.html: Capitalization
+
+2005-06-02 02:29 ivan
+
+ * httemplate/index.html, httemplate/misc/print_invoices.cgi,
+ httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_bill_event.html, FS/FS/cust_bill_event.pm,
+ FS/FS/part_bill_event.pm, FS/FS/UI/Web.pm,
+ httemplate/misc/email-invoice.cgi,
+ httemplate/misc/email_invoices.cgi,
+ httemplate/misc/fax-invoice.cgi,
+ httemplate/misc/fax_invoices.cgi,
+ httemplate/misc/print-invoice.cgi, FS/FS/cust_bill.pm,
+ FS/FS/part_pkg.pm, httemplate/view/cust_bill.cgi,
+ FS/bin/freeside-queued, httemplate/search/elements/search.html,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/progress-popup.html, htetc/global.asa,
+ htetc/handler.pl: add ability to search on a date range of
+ invoice events and then reprint or reemail (boy was that a bit
+ more work than i expected), closes: Bug#946
+
+2005-06-01 17:02 ivan
+
+ * rt/html/Ticket/Elements/AddCustomers: remove warning
+
+2005-06-01 16:40 ivan
+
+ * httemplate/view/cust_bill.cgi: align terminology for consistancy.
+ or something.
+
+2005-06-01 14:40 ivan
+
+ * httemplate/search/report_receivables.cgi: remove trailing
+ whitespace
+
+2005-06-01 13:31 ivan
+
+ * FS/FS/TicketSystem/: RT_External.pm, RT_Internal.pm: fix up
+ RT_Internal again, hopefully this is the last of the breakage
+ from RT_Internal
+
+2005-05-31 19:39 ivan
+
+ * httemplate/edit/part_pkg.cgi: really. *sigh*
+
+2005-05-31 16:42 ivan
+
+ * FS/FS/part_pkg/sesmon_minute.pm: tyop refactoring old
+ sesmon_minute price plkan, noticed by rjbs
+
+2005-05-31 16:32 ivan
+
+ * httemplate/edit/part_pkg.cgi: ack, this should finally fix the
+ package editing problem
+
+2005-05-26 12:30 ivan
+
+ * httemplate/view/: cust_bill.cgi: silly perl version bs
+
+2005-05-26 12:15 ivan
+
+ * FS/FS/svc_www.pm, httemplate/edit/svc_www.cgi,
+ httemplate/view/svc_www.cgi: make svc_www.usersvc optional
+
+2005-05-25 20:45 ivan
+
+ * httemplate/edit/part_pkg.cgi: 72?!
+
+2005-05-24 08:33 ivan
+
+ * Makefile: 1.5.7. and enable RT by default, finally
+
+2005-05-23 04:49 ivan
+
+ * htetc/freeside-rt.conf: so Search.tsf and Search.rdf work
+
+2005-05-22 16:38 ivan
+
+ * FS/FS/svc_acct.pm: fix quick crypt_password bug when its passwd
+ an empty param
+
+2005-05-22 13:39 ivan
+
+ * httemplate/view/cust_bill.cgi: oops, quote $link w/new templating
+
+2005-05-22 02:25 ivan
+
+ * httemplate/browse/agent.cgi: Avoid Gratuitous Capitalizaiton
+
+2005-05-21 21:24 ivan
+
+ * FS/FS/prepay_credit.pm: add optional agentnum field to POD doc
+
+2005-05-21 11:38 ivan
+
+ * httemplate/browse/agent.cgi: make sure the customers tables for
+ each agent line up with each other, too
+
+2005-05-21 10:26 ivan
+
+ * httemplate/search/cust_main.cgi: hehe, allow changing the browse
+ order of any sort
+
+2005-05-21 10:14 ivan
+
+ * httemplate/browse/agent.cgi: line up
+ prospect/active/suspended/cancelled customers
+
+2005-05-19 07:10 ivan
+
+ * FS/FS/part_export/shellcommands.pm: A group number must refer to
+ an already existing group - so add manually it if you want to
+ define a set of static gids or something, default is just going
+ to cause headaches
+
+2005-05-19 04:05 ivan
+
+ * FS/FS/svc_acct.pm: ! or !! also
+
+2005-05-19 03:45 ivan
+
+ * FS/FS/part_export/shellcommands.pm: fix up some defaults to
+ include gid too
+
+2005-05-19 03:29 ivan
+
+ * FS/FS/part_export/: acct_sql.pm, shellcommands.pm: missing ;
+
+2005-05-19 03:26 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/acct_sql.pm,
+ part_export/shellcommands.pm,
+ part_export/shellcommands_withdomain.pm: fix shellcommands export
+ encrypting "magic" shadow values * NP *LK*
+
+2005-05-19 02:49 ivan
+
+ * FS/FS/svc_acct.pm: oops, remove old-style duplicate check from
+ replace, _check_duplicate was already below it
+
+2005-05-19 01:51 ivan
+
+ * httemplate/view/cust_bill.cgi: oops, fix alternate view/etc.
+ links
+
+2005-05-19 01:43 ivan
+
+ * httemplate/: misc/email-invoice.cgi, misc/fax-invoice.cgi,
+ misc/print-invoice.cgi, view/cust_bill.cgi: re-email/fax/print
+ links should respect template, also add direct re-send links like
+ the view links and convert view/cust_bill.cgi to proper template
+
+2005-05-18 09:57 ivan
+
+ * httemplate/browse/agent.cgi: oops, it helps to get the link right
+
+2005-05-18 09:55 ivan
+
+ * httemplate/: browse/agent.cgi, search/report_receivables.cgi: add
+ agent-specific A/R aging report, closes: bug#1229
+
+2005-05-18 09:37 ivan
+
+ * bin/masonize: report the file that had a masonize error
+
+2005-05-18 07:50 ivan
+
+ * FS/FS/part_export/acct_sql.pm: actually, quota goes in pw_shell.
+ of course!
+
+2005-05-18 03:43 ivan
+
+ * FS/FS/cust_bill.pm: oops, losing notes!
+
+2005-05-15 06:49 ivan
+
+ * httemplate/search/report_receivables.cgi: this status column is
+ probably faster, one giant SQL query. and add back in the
+ customer link, oops
+
+2005-05-15 06:00 ivan
+
+ * FS/FS/cust_main.pm, httemplate/search/report_receivables.cgi,
+ httemplate/search/elements/search.html: move receivables report
+ to search template
+
+2005-05-15 04:58 ivan
+
+ * httemplate/search/cust_bill.html: use money_char config
+
+2005-05-15 04:46 ivan
+
+ * httemplate/search/cust_bill.html: align
+
+2005-05-14 13:11 ivan
+
+ * README.1.5.7.lastbit: hmm virtual fields have no history?
+
+2005-05-14 13:11 ivan
+
+ * README.1.5.7: 0.26
+
+2005-05-14 12:57 ivan
+
+ * README.1.5.7, rt/lib/RT/URI/freeside.pm,
+ rt/lib/RT/URI/freeside/Internal.pm: fixup RT integration grr!
+
+2005-05-14 11:03 ivan
+
+ * FS/FS/cust_bill.pm: h helps halot
+
+2005-05-14 10:59 ivan
+
+ * FS/FS/cust_bill.pm: well this is sorta halfass anyway but useful
+
+2005-05-14 10:04 ivan
+
+ * FS/FS/Conf.pm, conf/invoice_html,
+ httemplate/view/cust_bill-logo.cgi: html invoices: when
+ displaying, use the actual logo from the conf dir - same as the
+ emailed copy
+
+2005-05-14 09:30 ivan
+
+ * FS/FS/: Misc.pm, cust_bill.pm: disable debugging
+
+2005-05-14 09:27 ivan
+
+ * ANNOUNCE.1.5, FS/FS/Conf.pm, FS/FS/Misc.pm, FS/FS/cust_bill.pm,
+ FS/FS/part_bill_event.pm, conf/invoice_html, conf/logo.png,
+ httemplate/docs/billing.html, httemplate/view/cust_bill.cgi: html
+ invoices!
+
+ http://chris-linfoot.net/d6plinks/CWLT-5VZD4Y
+ http://www.dsv.su.se/~jpalme/ietf/mhtml.html
+ ftp://ftp.dsv.su.se/users/jpalme/draft-ietf-mhtml-info.txt
+ http://mailformat.dan.info/headers/mime.html
+ http://www.faqs.org/rfcs/rfc2392.html
+ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cdosys/html/_cdosys_content-type_multipart.asp
+
+ (MIME is hard, let's go shopping!)
+
+2005-05-13 08:06 ivan
+
+ * FS/FS/cust_bill.pm: fix picking up alternate invoice_latexnotes_*
+ files, and expand country codes on invoices. and oops,
+ print_html changes slipped in last commit too. well, they were
+ ready anyway.
+
+2005-05-13 03:55 ivan
+
+ * conf/invoice_latex: better to do something fancy like scale down
+ the font size to fit in the intended space or something but hey,
+ this is good enough for now :)
+
+2005-05-13 03:54 ivan
+
+ * FS/FS/cust_bill.pm: substitute a non-breaking space if there is
+ no invoice_latexreturnaddress file
+
+2005-05-11 07:07 ivan
+
+ * FS/FS/export_svc.pm: new progressbar display causes a silly error
+ in edge case where no dup checking necessary, closes: Bug#1226
+
+2005-05-10 11:30 khoff
+
+ * rt/html/Ticket/Elements/EditCustomers: Missing '</A>' tag.
+
+2005-05-05 06:04 ivan
+
+ * conf/: invoice_latex: no comma between state and address
+
+2005-05-04 18:46 ivan
+
+ * httemplate/search/svc_domain.cgi: the ? between svc_domain.cgi
+ and the domain id is missing
+
+2005-05-04 02:33 ivan
+
+ * FS/FS/part_pkg.pm: use new pkg_svc.pkgsvcnum primary key when
+ modifying pkg_svc records, closes: Bug#1221
+
+2005-05-04 02:20 ivan
+
+ * FS/FS/Record.pm: err msg
+
+2005-05-03 18:06 ivan
+
+ * FS/FS/cust_bill.pm: patch to just update the template or
+ conf/invoice_latex* to use the new one
+
+2005-05-03 17:40 ivan
+
+ * conf/invoice_latex, conf/invoice_latexfooter,
+ conf/invoice_latexreturnaddress, conf/logo.eps,
+ httemplate/docs/billing.html, FS/FS/Conf.pm, FS/FS/cust_bill.pm:
+ great new invoice template from kristian!
+
+2005-05-03 10:22 ivan
+
+ * FS/FS/cust_bill.pm: minutely better error reporting for pdf
+ problems
+
+2005-05-03 06:29 ivan
+
+ * FS/bin/: freeside-addoutsource, freeside-addoutsourceuser: remove
+ unnecessary host=localhost from outsource instance creation foo
+
+2005-05-03 05:56 ivan
+
+ * README.1.5.7: fix some wrapping
+
+2005-05-03 02:56 ivan
+
+ * FS/FS/cust_pay.pm: on receipts, show "Electronic Check" instead
+ of "Chek" for payby = CHEK transactions
+
+2005-05-03 01:51 ivan
+
+ * FS/bin/freeside-sqlradius-radacctd: not running with elevated
+ privs, -T not necessary
+
+2005-05-03 01:46 ivan
+
+ * FS/FS/domain_record.pm: [:ascii:] is not legal for 5.005, alas,
+ it still needs to be supported for just a little bit longer
+
+2005-05-01 23:32 ivan
+
+ * FS/FS/svc_Common.pm, httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_forward.cgi, httemplate/search/svc_www.cgi:
+ move httemplate/search/svc_domain to the new search template
+ along with svc_www and svc_forward
+
+2005-04-30 02:47 ivan
+
+ * httemplate/search/svc_forward.cgi: show "(unlinked)" for unlined
+ forwards instead of nothing
+
+2005-04-30 02:45 ivan
+
+ * httemplate/search/svc_forward.cgi: pull in the customer
+ information as part of the main query for efficiency
+
+2005-04-29 06:00 ivan
+
+ * httemplate/search/: svc_forward.cgi, svc_www.cgi: template
+ forward search using the standard search template: forwards are
+ now paged
+
+2005-04-28 10:05 ivan
+
+ * FS/FS/cust_bill.pm: add < and > to _latex_escape (khoff)
+
+2005-04-25 17:20 khoff
+
+ * bin/svc_broadband.renumber: For renumbering svc_broadband
+ services from one addr_block to another. Hopefully no one will
+ ever have to use this.
+
+2005-04-25 02:33 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Daemon.pm, FS/FS/svc_acct.pm, FS/t/Daemon.t,
+ FS/MANIFEST, FS/FS/part_export/sqlradius.pm,
+ FS/bin/freeside-queued, FS/bin/freeside-selfservice-server,
+ FS/bin/freeside-sqlradius-radacctd, init.d/freeside-init: pick up
+ freeside-sqlradius-radacctd again after all these years, now it
+ just needs to update the "seconds" field(s), finally closes:
+ Bug#1125
+
+2005-04-21 16:13 ivan
+
+ * install/debian/3.1/INSTALL: little bit of apache setup and add
+ the fs_queue user
+
+2005-04-21 14:31 ivan
+
+ * install/debian/3.1/INSTALL: or apache won't start
+
+2005-04-21 04:47 ivan
+
+ * FS/FS/part_export/acct_sql.pm: fix nit with crypt flag when
+ replacing too
+
+2005-04-21 04:35 ivan
+
+ * FS/FS/part_export/acct_sql.pm: support multiple primary keys
+
+2005-04-20 23:18 ivan
+
+ * install/debian/3.1/INSTALL: libjavascript-rpc-perl hit testing
+
+2005-04-20 00:12 ivan
+
+ * FS/FS/part_export/acct_sql.pm: hehe oops
+
+2005-04-19 23:41 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/acct_sql.pm: add vpopmail
+ defaults to acct_sql export
+
+2005-04-19 10:25 ivan
+
+ * README.1.5.7: update pre6 -> 7 upgrade instructions too
+
+2005-04-19 02:50 ivan
+
+ * FS/FS/Conf.pm: disable RT_Libs for now
+
+2005-04-19 02:48 ivan
+
+ * httemplate/docs/install.html, httemplate/docs/upgrade10.html,
+ ANNOUNCE.1.5, README.1.5.7.lastbit, SCHEMA_CHANGE,
+ install/redhat/9/INSTALL: did another upgrade, fixed up the
+ instructions
+
+2005-04-19 02:48 ivan
+
+ * FS/FS/part_pkg.pm: silence an annoying but harmless perl warning
+
+2005-04-18 00:37 ivan
+
+ * FS/FS/cust_main.pm: add some newlines to debugging output, no
+ need to print file and line # so much
+
+2005-04-16 15:26 ivan
+
+ * httemplate/edit/cust_pay.cgi: use money_char on enter payment
+ screen instead of hardcoding $
+
+2005-04-15 13:29 khoff
+
+ * FS/FS/Conf.pm, FS/FS/domain_record.pm, FS/FS/svc_domain.pm,
+ httemplate/view/svc_domain.cgi: Added support for TXT records.
+
+2005-04-14 02:41 ivan
+
+ * FS/FS/cust_bill.pm, conf/invoice_latex, conf/invoice_latex.diff:
+ move invoice_latex templating to Text::Template, with special
+ sauce^W^Wbackwards-compatibility for old templates
+
+2005-04-13 05:31 ivan
+
+ * httemplate/: edit/part_svc.cgi, view/svc_acct.cgi: get rid of
+ some super ancient assumptions about slipip and uid meaning
+ exporting to RADIUS and shell respectively
+
+2005-04-13 05:30 ivan
+
+ * FS/FS/: Record.pm, cust_svc.pm: add nowarn_identical flag to
+ Record.pm and use it in cust_svc svcpart replacement (which is
+ all about the exports anyway)
+
+2005-04-13 03:54 ivan
+
+ * FS/FS/svc_acct.pm: add a line to pod example regarding RADIUS
+ check attributes
+
+2005-04-13 03:32 ivan
+
+ * FS/FS/raddb.pm: add Radius-Operator
+
+2005-04-13 03:16 ivan
+
+ * FS/FS/part_pkg/flat.pm: add explicit use Date::Manip here, oops
+
+2005-04-13 02:55 ivan
+
+ * FS/FS/svc_acct.pm: quiet annoying "use of uninitialized value
+ errors"
+
+2005-04-13 01:16 ivan
+
+ * FS/FS/: cust_main.pm, svc_acct.pm: add skip_fuzzyfiles hack, and
+ add Session-Timeout RADIUS attribute if a svc_acct.seconds value
+ is present
+
+2005-04-12 20:38 ivan
+
+ * CREDITS, FS/FS/part_pkg/flat_comission_cust.pm: fix bug in
+ flat_commission price plan, thanks to Troy Hammonds
+
+2005-04-11 13:13 khoff
+
+ * FS/FS/: Conf.pm, cust_main.pm: Configuration option to override
+ the email address sent to your BOP processor, in case the
+ processor sends a pesky receipt that you don't want your
+ customers getting.
+
+2005-04-11 09:48 khoff
+
+ * FS/FS/: h_cust_svc.pm, h_svc_forward.pm: No need to inflict
+ debugging messages on everyone.
+
+2005-04-10 14:23 ivan
+
+ * install/debian/3.1/INSTALL: a few more packages
+
+2005-04-10 06:01 ivan
+
+ * httemplate/docs/selfservice.html: add apache snippet to
+ self-service install docs
+
+2005-04-10 03:16 ivan
+
+ * httemplate/search/elements/search.html: add some left and right
+ padding so cells don't run into each other so badly
+
+2005-04-09 18:13 ivan
+
+ * Makefile: fix install-apache for bsd make and reverse
+ accidentally-checked-in (again!) RT_ENABLED = 1
+
+2005-04-07 18:12 ivan
+
+ * htetc/freeside-rt.conf: ugh, don't know why that wasn't working
+ and don't f$&# care
+
+2005-04-07 03:35 ivan
+
+ * Makefile, htetc/freeside-base.conf, htetc/freeside-rt.conf,
+ install/debian/3.1/INSTALL: add install/debian/3.1/INSTALL script
+ and script up some apache automation assuming a conf.d type dir
+
+2005-04-07 02:26 ivan
+
+ * FS/FS/Record.pm, FS/bin/freeside-setup, bin/dbdef-create,
+ bin/fix-sequences: depend on DBIx::DBSchema 0.26 for dbdef-create
+ (for Pg 'public' schema fix) and 0.25 in freeside-setup and
+ Record.pm (for DBD::Pg 1.40 is bunk fix)
+
+2005-04-06 23:08 ivan
+
+ * README.1.5.7.lastbit: and the history tables
+
+2005-04-06 20:28 khoff
+
+ * FS/FS/: h_cust_svc.pm, h_svc_forward.pm, h_svc_www.pm: Using
+ current (non-history) records in place of missing history
+ records.
+
+2005-04-06 18:29 ivan
+
+ * httemplate/docs/upgrade8.html: ancient upgrade fix, oops. thanks
+ Rick Harby <rharby at caarnet.com>
+
+2005-04-06 15:52 ivan
+
+ * FS/FS/svc_forward.pm: and fix the error msg haha
+
+2005-04-06 15:50 ivan
+
+ * FS/FS/svc_forward.pm: looks like a domain part for a
+ literally-specified forward src or dst is required, not optional
+
+2005-04-06 03:38 ivan
+
+ * httemplate/docs/install-rt.html: correct links to some
+ atypically-named CPAN distributions
+
+2005-04-05 17:50 khoff
+
+ * FS/FS/h_Common.pm: $pkey should be the primary key of the real
+ table, not the history table.
+
+2005-04-05 14:33 khoff
+
+ * bin/add-history-records.pl: This doesn't fix the problem. To be
+ continued...
+
+2005-04-02 15:49 ivan
+
+ * bin/slony-setup: must be as Pg superuser
+
+2005-04-02 14:46 ivan
+
+ * README.1.5.7, README.1.5.7.lastbit, FS/FS/cust_bill_pkg.pm,
+ FS/FS/part_svc_router.pm, FS/FS/pkg_svc.pm, FS/FS/rate_detail.pm,
+ FS/FS/reg_code_pkg.pm, FS/FS/type_pkgs.pm, FS/bin/freeside-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade10.html:
+ herding elephants: add primary keys to *all* tables for slony
+
+2005-04-02 12:34 ivan
+
+ * bin/slony-setup: adding quick slony setup script
+
+2005-04-01 14:52 khoff
+
+ * FS/FS/: h_cust_svc.pm, h_svc_acct.pm, h_svc_www.pm: Trap, and
+ attempt to resolve, problems caused by missing history records.
+
+2005-04-01 14:34 khoff
+
+ * FS/FS/Record.pm: so we can pass in a time if we're back-filling
+ history records
+
+2005-03-31 21:59 steve
+
+ * FS/FS/cust_main.pm: fix paybatch parsing to support bop::jettis
+
+2005-03-31 03:41 ivan
+
+ * FS/FS/cust_main.pm: add ability to link services w/order_pkg
+ method in addition to provisioning new ones
+
+2005-03-31 01:07 ivan
+
+ * FS/FS/cust_main_invoice.pm: show illegal email addresses used for
+ invoice destinations
+
+2005-03-30 22:56 khoff
+
+ * bin/add-history-records.pl: Printing insert statements is not
+ necessary
+
+2005-03-30 21:02 khoff
+
+ * httemplate/docs/upgrade10.html: Very annoying typo. >:-)
+
+2005-03-30 19:47 khoff
+
+ * bin/add-history-records.pl: Committing the inserts helps.
+
+2005-03-30 16:53 khoff
+
+ * bin/add-history-records.pl: (Apparently) working version.
+ Updates svc_*, cust_svc, and domain_record history tables.
+
+2005-03-30 16:31 khoff
+
+ * FS/FS/h_svc_forward.pm: Another missing 'u'.
+
+2005-03-30 13:40 khoff
+
+ * FS/FS/h_Common.pm: Dump a call trace if something calls
+ FS::h_Common::sql_h_search without END_TIMESTAMP.
+
+2005-03-30 13:22 khoff
+
+ * FS/FS/cust_svc.pm: Have to pass @_ to FS::svc_www::domain_record
+ in case we're really a FS::h_svc_www object.
+
+2005-03-30 13:09 khoff
+
+ * FS/FS/h_svc_www.pm: typo. 'use', not 'se'.
+
+2005-03-30 12:55 khoff
+
+ * bin/add-history-records.pl: Test script to add pre-history table
+ history records.
+
+2005-03-29 17:37 ivan
+
+ * FS/FS/part_export/cp.pm: according to landel CP no longer
+ supports changing username
+
+2005-03-29 17:32 ivan
+
+ * httemplate/docs/selfservice.html: separate out referring customer
+ info to optional section, add a note on setting the agentnum via
+ templte
+
+2005-03-29 17:18 ivan
+
+ * httemplate/search/cust_pay.cgi: fix ambiguous column error when
+ selecting by credit card, fixes: Bug#1189
+
+2005-03-29 14:41 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm,
+ httemplate/docs/selfservice.html: better self-service debugging,
+ don't point to install.html for suEXEC/setuid in self-service
+ setup docs
+
+2005-03-28 17:40 khoff
+
+ * FS/FS/TicketSystem/RT_External.pm,
+ FS/FS/TicketSystem/RT_Internal.pm, httemplate/index.html: A few
+ RT_External fixes.
+
+2005-03-28 17:38 khoff
+
+ * FS/FS/Misc.pm: 'require' not 'use' Fax::Hylafax::Client so it's
+ an optional requirement.
+
+2005-03-27 15:21 ivan
+
+ * FS/FS/cust_main.pm: allow & in bank names
+
+2005-03-27 15:21 ivan
+
+ * FS/FS/: svc_Common.pm, svc_acct.pm: svc_Common / svc_acct
+ child_objects can now set an alternate field for the svcnum, for
+ things like forwards
+
+2005-03-26 03:51 ivan
+
+ * install/fedora/fc3/: INSTALL, sources.list: fc3
+
+2005-03-22 20:16 ivan
+
+ * httemplate/docs/install-rt.html, README.1.5.7: new RT requires
+ Tree::Simple too
+
+2005-03-22 18:59 ivan
+
+ * README.1.5.7, httemplate/docs/install-rt.html: add HTML::Scrubber
+ to rt install/upgrade docs
+
+2005-03-22 10:15 ivan
+
+ * httemplate/docs/upgrade10.html: small fix for indices in upgrade
+ instructions, found by s5
+
+2005-03-21 14:13 khoff
+
+ * FS/FS/Conf.pm, FS/FS/Misc.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_invoice.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pkg.pm, FS/FS/svc_acct.pm,
+ FS/FS/ClientAPI/MyAccount.pm, FS/FS/part_export/http.pm,
+ FS/FS/part_export/infostreet.pm,
+ FS/FS/part_export/shellcommands.pm, htetc/handler.pl,
+ httemplate/docs/install.html, httemplate/edit/cust_main.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/misc/fax-invoice.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main/billing.html,
+ httemplate/view/cust_main/tickets.html: Added support for FAX
+ invoice destinations using a HylaFAX server. Faxing plain text
+ invoices is not supported.
+
+2005-03-21 13:55 pbowen
+
+ * FS/FS/Record.pm: Forgot to load up the conf.
+
+2005-03-18 16:12 pbowen
+
+ * FS/FS/: Record.pm, cust_main.pm: Fixed a few things: -PB 1. Fixed
+ a nasty bug that would clear the payinfo if the private key was
+ not available. 2. Set the default module for encrypt/decrypt to
+ be Crypt::OpenSSL::RSA. 3. Added a die and error message so that
+ it doesn't just pass around plaintext if the encryption engine is
+ broken or missing. 4. Added code so that the masked payinfo is
+ handled correctly in the case that it is blank and it cannot be
+ generated (encrypted payinfo)
+
+2005-03-18 11:21 pbowen
+
+ * FS/FS/Conf.pm, FS/FS/Record.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm, FS/bin/freeside-setup,
+ httemplate/docs/upgrade10.html: Added encrypted fields for Credit
+ Cards, etc... - PB
+
+2005-03-18 11:15 pbowen
+
+ * FS/FS/part_pkg.pm: Added a few additional recurrences for domain
+ billing
+
+2005-03-18 08:47 pbowen
+
+ * FS/FS/Record.pm: Fixed a small bug... if replace is called by
+ SUPER, @_ == 1 if it only contains an undef. -PB
+
+2005-03-18 01:58 ivan
+
+ * httemplate/docs/selfservice.html: selfservice uses HTML::Entities
+
+2005-03-18 01:15 ivan
+
+ * FS/FS/cust_main_county.pm: no idea why this is only showing up on
+ freebsd install
+
+2005-03-17 17:00 ivan
+
+ * FS/FS/cust_main_county.pm: sorry it was late
+
+2005-03-17 13:56 khoff
+
+ * FS/FS/cust_bill.pm: Documentation tyop.
+
+2005-03-17 13:45 ivan
+
+ * httemplate/docs/install-rt.html: Freeside side uses MIME-tools
+ now
+
+2005-03-17 13:41 khoff
+
+ * FS/FS/Conf.pm, FS/FS/Misc.pm, FS/FS/cust_bill.pm,
+ httemplate/docs/install.html, httemplate/misc/email-invoice.cgi:
+ Added options invoice_email_pdf and invoice_email_pdf_note.
+ invoice_email_pdf - Attach PDF invoice to emailed plain text
+ invoices. invoice_email_pdf_note - Replace plain text invoice
+ with this note, when attaching a PDF.
+
+2005-03-16 03:31 ivan
+
+ * FS/FS/cust_main_county.pm: fix regionselector for CR in region
+ names for some reason
+
+2005-03-15 15:27 khoff
+
+ * httemplate/misc/payment.cgi: Missing semicolon.
+
+2005-03-13 03:47 ivan
+
+ * FS/FS/cust_main.pm: and store the refund correctly
+
+2005-03-13 03:34 ivan
+
+ * FS/FS/cust_main.pm: when refunding against a specific card
+ payment, use the card details from the payment instead of the
+ customer record
+
+2005-03-13 03:12 ivan
+
+ * FS/FS/cust_main.pm: add some additional debugging to refunds
+
+2005-03-12 08:07 ivan
+
+ * Makefile, httemplate/docs/install-rt.html,
+ rt/etc/RT_SiteConfig.pm, rt/lib/RT/URI/freeside.pm,
+ rt/lib/RT/URI/freeside/Internal.pm,
+ rt/lib/RT/URI/freeside/XMLRPC.pm: popurl(3) won't give us a good
+ freeside base url since RT calls it from multiple directory
+ depths... have to specify explicity, like external integration
+
+2005-03-12 06:35 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.cgi: - bring prepaid
+ support into this century (close: Bug#1124) - finally get rid of
+ fs_signup (everything is in fs_selfservice now) (Bug#413) -
+ organize main menu sysadmin section so it is slightly less
+ confusing
+
+2005-03-12 06:31 ivan
+
+ * httemplate/docs/schema.html, httemplate/docs/selfservice.html,
+ httemplate/docs/upgrade10.html, README.1.5.7, ANNOUNCE.1.5,
+ FS/FS/agent.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ FS/FS/prepay_credit.pm, FS/bin/freeside-setup,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/index.html, httemplate/browse/agent.cgi,
+ httemplate/edit/prepay_credit.cgi,
+ httemplate/search/prepay_credit.html,
+ httemplate/search/elements/search.html, fs_selfservice/DEPLOY,
+ fs_selfservice/FS-SelfService/ieak.template,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/decline.html,
+ httemplate/edit/process/prepay_credit.cgi,
+ httemplate/edit/process/reg_code.cgi,
+ fs_selfservice/FS-SelfService/cgi/map.gif,
+ fs_selfservice/FS-SelfService/cgi/promocode.html,
+ fs_selfservice/FS-SelfService/cgi/regcode.html,
+ fs_selfservice/FS-SelfService/cgi/signup-agentselect.html,
+ fs_selfservice/FS-SelfService/cgi/signup-alternate.html,
+ fs_selfservice/FS-SelfService/cgi/signup-billaddress.html,
+ fs_selfservice/FS-SelfService/cgi/signup-freeoption.html,
+ fs_selfservice/FS-SelfService/cgi/signup-snarf.html,
+ fs_selfservice/FS-SelfService/cgi/signup.cgi,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ fs_selfservice/FS-SelfService/cgi/stateselect.html,
+ fs_selfservice/FS-SelfService/cgi/success.html,
+ fs_signup/cck.template, fs_signup/fs_signup_server,
+ fs_signup/ieak.template, fs_signup/FS-SignupClient/Changes,
+ fs_signup/FS-SignupClient/MANIFEST,
+ fs_signup/FS-SignupClient/MANIFEST.SKIP,
+ fs_signup/FS-SignupClient/Makefile.PL,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/test.pl,
+ fs_signup/FS-SignupClient/cgi/cvv2.html,
+ fs_signup/FS-SignupClient/cgi/cvv2.png,
+ fs_signup/FS-SignupClient/cgi/cvv2_amex.png,
+ fs_signup/FS-SignupClient/cgi/decline.html,
+ fs_signup/FS-SignupClient/cgi/map.gif,
+ fs_signup/FS-SignupClient/cgi/promocode.html,
+ fs_signup/FS-SignupClient/cgi/regcode.html,
+ fs_signup/FS-SignupClient/cgi/signup-agentselect.html,
+ fs_signup/FS-SignupClient/cgi/signup-alternate.html,
+ fs_signup/FS-SignupClient/cgi/signup-billaddress.html,
+ fs_signup/FS-SignupClient/cgi/signup-freeoption.html,
+ fs_signup/FS-SignupClient/cgi/signup-snarf.html,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ fs_signup/FS-SignupClient/cgi/stateselect.html,
+ fs_signup/FS-SignupClient/cgi/success.html, htetc/global.asa,
+ htetc/handler.pl: - bring prepaid support into this century
+ (close: Bug#1124) - finally get rid of fs_signup (everything is
+ in fs_selfservice now) (Bug#413) - organize main menu sysadmin
+ section so it is slightly less confusing
+
+2005-03-11 02:35 ivan
+
+ * rt/FREESIDE_MODIFIED: update list of modified files
+
+2005-03-11 02:33 ivan
+
+ * rt/etc/RT_SiteConfig.pm: merging
+
+2005-03-11 02:18 ivan
+
+ * httemplate/docs/install-rt.html: note about RT_External
+
+2005-03-10 17:34 khoff
+
+ * rt/: etc/RT_SiteConfig.pm, html/Elements/Header,
+ html/Elements/Menu, html/Elements/Tabs,
+ html/Ticket/Elements/AddCustomers,
+ html/Ticket/Elements/ShowCustomers, lib/RT/URI/freeside.pm,
+ lib/RT/URI/freeside/Internal.pm, lib/RT/URI/freeside/XMLRPC.pm:
+ Reorganized RT->Freeside integration to support Internal (single
+ RT/Freeside database) and XMLRPC interfaces. All the UI stuff is
+ handled the same either way. Integration type is changed by
+ setting $RT::URI::freeside::IntegrationType to either 'Internal'
+ or 'XMLRPC' in your RT_SiteConfig.pm.
+
+2005-03-10 14:49 khoff
+
+ * FS/FS/XMLRPC.pm: Add the ability to do freeside configuration
+ lookups through the XMLRPC interface.
+
+2005-03-10 07:43 ivan
+
+ * install/freebsd/: INSTALL, ports: ports is a steaming pile
+
+2005-03-10 07:33 ivan
+
+ * README.1.5.7, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: arg
+
+2005-03-10 07:18 ivan
+
+ * README.1.5.7, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: add Frontier::RPC to docs too
+
+2005-03-10 04:06 ivan
+
+ * README.1.5.7, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: add IO-stringy (IO::Scalar) to
+ instructions
+
+2005-03-10 01:56 ivan
+
+ * FS/bin/freeside-daily: fine.
+
+2005-03-10 00:58 ivan
+
+ * httemplate/edit/: part_pkg.cgi, process/part_pkg.cgi: fixes
+ package editing problem with extraneous services showing up,
+ closes: Bug#1170
+
+2005-03-09 23:27 ivan
+
+ * install/freebsd/INSTALL: freebsd bs
+
+2005-03-09 00:46 ivan
+
+ * httemplate/docs/install-rt.html: add complete apache config
+ instructions for RT, closes: Bug#1031
+
+2005-03-09 00:18 ivan
+
+ * ANNOUNCE.1.5, httemplate/docs/index.html,
+ httemplate/docs/install-rt.html, httemplate/docs/install.html:
+ preliminary RT docs
+
+2005-03-08 10:37 khoff
+
+ * FS/FS/XMLRPC.pm: Don't require that the method results be
+ FS::Record descendant objects. If they are, we map them to
+ hashrefs. Otherwise we return them verbatim and hope (maybe
+ check) that they're scalars, hashrefs, or arrayrefs.
+
+2005-03-08 10:15 khoff
+
+ * FS/FS/XMLRPC.pm: Minor re-work to allow for pseudo methods, like
+ 'version', and eventually config look-ups (next commit).
+
+2005-03-06 03:45 ivan
+
+ * install/freebsd/ports: adding Text::CSV and
+ Spreadsheet::WriteExcel
+
+2005-03-06 02:15 ivan
+
+ * ANNOUNCE.1.5: d
+
+2005-03-05 19:25 ivan
+
+ * httemplate/search/elements/search.html: specity an explicit EOL
+ for Text::CSV_XS, apparantly sometimes the default is null
+
+2005-03-05 19:22 ivan
+
+ * httemplate/search/elements/search.html: and a slight formatting
+ fix
+
+2005-03-05 19:04 ivan
+
+ * httemplate/search/elements/search.html, README.1.5.7,
+ htetc/global.asa, htetc/handler.pl, httemplate/index.html,
+ httemplate/docs/install.html, httemplate/docs/upgrade10.html,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_bill_event.html,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_main-otaker.cgi,
+ httemplate/search/cust_main-payinfo.html,
+ httemplate/search/cust_main-quickpay.html,
+ httemplate/search/cust_main.cgi,
+ httemplate/search/cust_main.html, httemplate/search/cust_pay.cgi,
+ httemplate/search/cust_pay.html,
+ httemplate/search/cust_pkg_report.cgi,
+ httemplate/search/reg_code.html,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_prepaid_income.html,
+ httemplate/search/report_tax.html,
+ httemplate/search/sqlradius.html,
+ httemplate/search/svc_acct.html,
+ httemplate/search/svc_domain.html, httemplate/search/svc_www.cgi,
+ httemplate/view/cust_bill-pdf.cgi,
+ httemplate/view/cust_bill-ps.cgi: add Excel and CSV download of
+ templated reports and clean up their HTML formatting, closes;
+ Bug#520, Bug#1107
+
+2005-03-04 14:24 ivan
+
+ * httemplate/search/: cust_credit.html, cust_pay.cgi: fix "Column
+ reference "payby" is ambiguous" error when selecting by payment
+ type, fix missing check #s caused by cust_main.payinfo masking
+ cust_pay.payinfo, closes (really this time): Bug#1105
+
+2005-03-04 04:57 ivan
+
+ * httemplate/search/: cust_credit.html, cust_pay.cgi: report
+ correctly even if the customer record has somehow been removed...
+
+2005-03-04 04:34 ivan
+
+ * httemplate/browse/agent.cgi, FS/FS/Record.pm, FS/FS/h_Common.pm,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/report_cust_pay.html, ANNOUNCE.1.5,
+ httemplate/search/elements/search.html: add agent selection to
+ payment and credit reports, add link to agent browse, closes:
+ Bug#1105
+
+2005-03-03 02:25 ivan
+
+ * FS/: MANIFEST, FS/h_Common.pm, FS/h_cust_svc.pm,
+ FS/h_domain_record.pm, FS/h_svc_acct.pm, FS/h_svc_forward.pm,
+ FS/h_svc_www.pm, t/h_domain_record.t: clean up some harmless but
+ scary "Multiple records in scalar search" warnings w/history
+ table searches
+
+2005-03-03 01:05 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: no need for line number in
+ debug output...
+
+2005-03-03 00:58 ivan
+
+ * FS/FS/part_pkg/: voip_sqlradacct.pm: voip: rearrange and compact
+ call details on invoices, so place names get cut off, not
+ anything important
+
+2005-03-03 00:52 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: no need for line number in
+ debug output...
+
+2005-03-03 00:52 ivan
+
+ * FS/FS/cust_bill_pkg_detail.pm: eek, fix foreign key check
+
+2005-03-03 00:45 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: oops, need to use Date::Format
+ for time2str
+
+2005-03-03 00:37 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: voip: add start time for calls
+ to invoice details
+
+2005-03-03 00:21 ivan
+
+ * install/redhat/es3/INSTALL: add tetex packages for typeset
+ invoices
+
+2005-03-03 00:15 ivan
+
+ * FS/FS/Record.pm: want a full stack backtrace for this warning
+
+2005-03-03 00:05 ivan
+
+ * FS/FS/part_export/sqlradius.pm: doc
+
+2005-03-02 13:00 khoff
+
+ * httemplate/docs/install.html, eg/xmlrpc-example.pl,
+ httemplate/misc/xmlrpc.cgi, FS/FS/XMLRPC.pm, htetc/handler.pl:
+ Initial version of the xmlrpc interface for freeside.
+
+2005-03-01 16:47 ivan
+
+ * FS/FS/cust_pkg.pm: set setup date on package changes
+
+2005-03-01 16:03 ivan
+
+ * FS/FS/: cust_pkg.pm, part_pkg.pm: prevent bug causing 'Error
+ crediting customer for service remaining:
+ FS::cust_pkg=HASH(0x9958c60)' error on package cancellations
+ where the part_pkg record didn't have a plan, closes: Bug#1153
+
+2005-02-27 03:18 ivan
+
+ * FS/FS/: rate_prefix.pm, part_pkg/voip_sqlradacct.pm: fix VoIP
+ details on invoices, closes: Bug#1096
+
+2005-02-27 03:05 ivan
+
+ * httemplate/edit/REAL_cust_pkg.cgi: fix last bill date stickiness
+ on errors
+
+2005-02-27 02:18 ivan
+
+ * FS/FS/Record.pm: fix replacement in edge case with NULL integer
+ fields in a table without a primary key
+
+2005-02-26 13:29 ivan
+
+ * README.1.5.7, ANNOUNCE.1.5, ANNOUNCE.1.5.0, README.1.5.0pre7:
+ less cracktastic version numbering
+
+2005-02-25 14:14 ivan
+
+ * bin/pg-readonly: try to set the sequences right for modern Pg
+
+2005-02-25 14:07 ivan
+
+ * bin/pg-readonly: adding quick pg-readonly tool
+
+2005-02-25 12:52 ivan
+
+ * FS/FS/part_pkg.pm: small bugfix for options option
+
+2005-02-25 12:21 ivan
+
+ * FS/FS/part_pkg.pm: oops, need to check this in, adding "options"
+ option to part_pkg::insert to specify part_pkg_option records
+
+2005-02-24 06:22 ivan
+
+ * httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi, FS/FS/rate.pm,
+ FS/FS/svc_acct.pm, FS/FS/UI/Web.pm,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/progress-popup.html, FS/FS/export_svc.pm,
+ FS/FS/part_svc.pm: add progressbar to service definition add -
+ duplicate checking can take a while, closes: Bug#1126
+
+2005-02-22 22:43 ivan
+
+ * httemplate/docs/install.html: update docs wrt mysql support
+
+2005-02-22 10:26 khoff
+
+ * httemplate/edit/cust_pkg.cgi: Alphabetize/clean-up package list
+ to make it easier to find packages in large lists.
+
+2005-02-20 00:51 ivan
+
+ * FS/FS/UI/Web.pm: FS/UI/Web.pm did not return a true value
+
+2005-02-20 00:44 ivan
+
+ * FS/FS/UI/Web.pm, httemplate/edit/rate.cgi, CREDITS,
+ httemplate/elements/jsrsServer.html,
+ httemplate/elements/overlibmws.js,
+ httemplate/elements/progress-init.html,
+ httemplate/elements/progress-popup.html,
+ httemplate/misc/progress.html: use a javascript layer instead of
+ a browser popup (popup blockers), really generalize the
+ progressbar code to make it easy to use as a component
+
+2005-02-17 00:44 ivan
+
+ * httemplate/edit/rate.cgi: generalize progressbar code in
+ preparation for using it wherever needed
+
+2005-02-16 17:37 ivan
+
+ * httemplate/edit/process/rate.cgi: generalize progressbar code in
+ preparation for using it wherever needed
+
+2005-02-16 16:11 ivan
+
+ * FS/FS/: rate.pm, UI/Web.pm: generalize progressbar code in
+ preparation for using it wherever needed
+
+2005-02-16 14:06 ivan
+
+ * install/centos/3/: INSTALL, httpd-init: centos install notes,
+ basically like rhell
+
+2005-02-15 18:53 ivan
+
+ * FS/FS/cust_bill.pm: slightly better error messages for LaTeX
+ problems
+
+2005-02-15 10:47 ivan
+
+ * install/redhat/es3/INSTALL: update rhell3 docs, add some slony
+ notes
+
+2005-02-13 19:49 ivan
+
+ * FS/FS/svc_acct.pm: this should fix uid duplicate checking,
+ closes: Bug#1113
+
+2005-02-11 19:02 ivan
+
+ * httemplate/edit/process/svc_broadband.cgi: transaction not
+ necessary here
+
+2005-02-10 22:44 ivan
+
+ * FS/FS/rate.pm, FS/FS/UI/Web.pm, htetc/global.asa,
+ htetc/handler.pl, httemplate/edit/process/rate.cgi,
+ httemplate/edit/rate.cgi: generalize progressbar code in
+ preparation for using it wherever needed
+
+2005-02-08 17:08 ivan
+
+ * Makefile: more porable syntax for su
+
+2005-02-08 14:33 ivan
+
+ * FS/FS/clientapi_session_field.pm: tyop
+
+2005-02-08 12:51 ivan
+
+ * install/freebsd/: INSTALL, ports: update freebsd install notes
+
+2005-02-08 12:22 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/upgrade10.html,
+ README.1.5.0pre7, FS/FS.pm, FS/MANIFEST,
+ FS/FS/ClientAPI_SessionCache.pm, FS/FS/Conf.pm,
+ FS/FS/clientapi_session.pm, FS/FS/clientapi_session_field.pm,
+ FS/FS/ClientAPI/Agent.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm, FS/t/ClientAPI_SessionCache.t,
+ FS/t/clientapi_session.t, FS/t/clientapi_session_field.t,
+ httemplate/docs/install.html, httemplate/docs/schema.html: make
+ self-service session cache module configurable, start framework
+ for in-database session cache
+
+2005-02-05 15:39 ivan
+
+ * FS/FS/: ClientAPI.pm, ClientAPI/Agent.pm, ClientAPI/MyAccount.pm,
+ ClientAPI/Signup.pm, ClientAPI/passwd.pm: remove unnecessary
+ complication from ClientAPI dispatch foo
+
+2005-02-04 17:30 ivan
+
+ * FS/FS/: ClientAPI.pm, ClientAPI/Agent.pm, ClientAPI/MyAccount.pm,
+ ClientAPI/Signup.pm, ClientAPI/passwd.pm: remove unnecessary
+ circular use of FS::ClientAPI, doesn't work with 5.8.[56] +
+ perl??
+
+2005-02-04 06:44 ivan
+
+ * Makefile: freebsd throws a fatal error if it can't stop apache
+ now, bah
+
+2005-02-04 02:38 ivan
+
+ * httemplate/edit/cust_main.cgi: typo
+
+2005-02-04 02:17 ivan
+
+ * install/redhat/es3/INSTALL: minor update for rhel3 install notes
+
+2005-02-02 00:06 ivan
+
+ * FS/FS/UI/: Base.pm, CGI.pm, Gtk.pm, agent.pm: removing old UI
+ experiment
+
+2005-01-29 04:51 ivan
+
+ * ANNOUNCE.1.5.0: gotta do pre7 already
+
+2005-01-29 04:49 ivan
+
+ * httemplate/browse/agent.cgi, FS/FS/part_pkg/flat.pm: oops, last
+ bit for reg codes
+
+2005-01-29 04:34 ivan
+
+ * FS/FS.pm, FS/FS/agent.pm, FS/FS/cust_pkg.pm, FS/FS/part_pkg.pm,
+ FS/FS/reg_code.pm, FS/FS/reg_code_pkg.pm, FS/bin/freeside-setup,
+ FS/t/reg_code.t, FS/t/reg_code_pkg.t, README.1.5.0pre7,
+ FS/MANIFEST, FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/cgi/regcode.html,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/docs/install.html, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html, httemplate/edit/reg_code.cgi,
+ httemplate/search/reg_code.html,
+ httemplate/edit/process/reg_code.cgi: registration codes
+
+2005-01-27 15:01 ivan
+
+ * httemplate/misc/payment.cgi, FS/FS/ClientAPI/MyAccount.pm:
+ s/defaultcountry/countrydefault/
+
+2005-01-27 14:19 ivan
+
+ * FS/FS/cust_pkg.pm: made a typo applying patch from pbowen
+
+2005-01-27 02:21 ivan
+
+ * httemplate/edit/process/rate.cgi, CREDITS, FS/FS/UID.pm,
+ FS/FS/queue.pm, FS/FS/rate.pm, httemplate/docs/install.html,
+ httemplate/elements/jsrsClient.js, httemplate/misc/progress.html,
+ JSRS-LICENSE, FS/bin/freeside-queued, httemplate/edit/rate.cgi,
+ httemplate/elements/qlib/box.js,
+ httemplate/elements/qlib/boxctrl.js,
+ httemplate/elements/qlib/boxres.js,
+ httemplate/elements/qlib/button.js,
+ httemplate/elements/qlib/buttonres.js,
+ httemplate/elements/qlib/control.js,
+ httemplate/elements/qlib/counter.js,
+ httemplate/elements/qlib/imagelist.js,
+ httemplate/elements/qlib/label.js,
+ httemplate/elements/qlib/messagebox.js,
+ httemplate/elements/qlib/progress.js,
+ httemplate/elements/qlib/sound.js,
+ httemplate/elements/qlib/sprite.js,
+ httemplate/elements/qlib/window.js,
+ httemplate/elements/qlib/wndctrl.js,
+ httemplate/images/progressbar-empty.png,
+ httemplate/images/progressbar-full.png: DHTML progress bar for
+ glacial rate adding and editing, closes: Bug#1100
+
+2005-01-19 13:25 ivan
+
+ * FS/FS/: cust_pkg.pm, part_pkg/flat.pm,
+ part_pkg/flat_comission.pm, part_pkg/flat_comission_cust.pm,
+ part_pkg/flat_comission_pkg.pm, part_pkg/flat_delayed.pm,
+ part_pkg/prorate.pm, part_pkg/sesmon_hour.pm,
+ part_pkg/sesmon_minute.pm, part_pkg/sql_external.pm,
+ part_pkg/sql_generic.pm, part_pkg/sqlradacct_hour.pm,
+ part_pkg/subscription.pm, part_pkg/voip_sqlradacct.pm: credit for
+ unused portion at cancellation, patch from pbowen
+
+2005-01-18 16:57 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm, cust_pkg.pm, part_pkg/flat.pm,
+ part_pkg/sesmon_hour.pm, part_pkg/sesmon_minute.pm,
+ part_pkg/sql_external.pm, part_pkg/sql_generic.pm,
+ part_pkg/sqlradacct_hour.pm, part_pkg/voip_sqlradacct.pm:
+ one-time referral credits
+
+2005-01-07 14:16 ivan
+
+ * httemplate/edit/: rate.cgi, process/rate.cgi: remove separate
+ file for rate processing, causing problems with giant query
+ string, kludge in the non-displayed US-rates, and disable the
+ submit button when pressed
+
+2005-01-06 12:58 ivan
+
+ * FS/FS/Conf.pm: fix description RT_External in ticket_system
+ option
+
+2005-01-06 12:20 ivan
+
+ * FS/FS/: cust_svc.pm, part_export/artera_turbo.pm: just 0-pad the
+ key codes, don't try fancy things with hex and sprintf
+
+2005-01-06 11:48 ivan
+
+ * FS/FS/: cust_svc.pm, part_export/artera_turbo.pm: format artera
+ turbo hex keycodes in uppercase
+
+2005-01-06 11:02 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: add enable_edit flag so
+ serials and key codes can be edited locally
+
+2005-01-05 11:29 ivan
+
+ * FS/FS/: cust_svc.pm, part_export/artera_turbo.pm: key codes are
+ hex!
+
+2005-01-05 02:01 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: add some debugging to
+ voip_sqlradacct
+
+2005-01-04 19:07 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: arg, really get the sub name
+ correct this time
+
+2005-01-04 19:01 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: missing underscore!
+
+2005-01-04 18:47 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: queue status changes rather
+ than run them immediately, always format keycode as %010d,
+ closes: Bug#936, Bug#1060
+
+2005-01-03 10:25 ivan
+
+ * FS/FS/cust_main.pm: eliminate warning: Argument "" isn\'t numeric
+ in numeric gt (>)
+
+2004-12-31 00:47 ivan
+
+ * httemplate/edit/part_pkg.cgi: add ignore_unrateable flag to voip
+ price plan
+
+2004-12-31 00:31 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: add ignore_unrateable flag to
+ voip price plan
+
+2004-12-31 00:24 ivan
+
+ * FS/FS/part_pkg/voip_sqlradacct.pm: add ignore_unrateable flag to
+ voip price plan
+
+2004-12-30 23:43 ivan
+
+ * FS/FS/cust_svc.pm: fix up some bugs in VoIP rating
+
+2004-12-30 16:48 ivan
+
+ * FS/FS/: cust_svc.pm, svc_acct.pm, part_pkg/voip_sqlradacct.pm:
+ fix up some bugs in VoIP rating
+
+2004-12-30 15:47 ivan
+
+ * htetc/global.asa: search the current dir *first*, otherwise some
+ weird Apache::ASP bugs could crop up if things are ever named the
+ same
+
+2004-12-30 01:59 ivan
+
+ * htetc/global.asa: kludge to fix nested includes with
+ Apache::ASP... dunno how much longer i want to support that,
+ should just switch to Mason
+
+2004-12-29 17:41 ivan
+
+ * FS/FS/: cust_svc.pm, domain_record.pm, Report/Table/Monthly.pm:
+ domain_record.pm
+
+2004-12-29 04:01 ivan
+
+ * CREDITS: update credits
+
+2004-12-29 04:00 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/h_cust_svc.pm, FS/FS/Record.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm,
+ FS/FS/h_Common.pm, FS/FS/h_svc_acct.pm, FS/FS/h_svc_broadband.pm,
+ FS/FS/h_svc_domain.pm, FS/FS/h_svc_external.pm,
+ FS/FS/h_svc_forward.pm, FS/FS/h_svc_www.pm, FS/FS/svc_acct.pm,
+ FS/MANIFEST, FS/t/h_Common.t, FS/t/h_cust_svc.t,
+ FS/t/h_svc_acct.t, FS/t/h_svc_broadband.t, FS/t/h_svc_domain.t,
+ FS/t/h_svc_external.t, FS/t/h_svc_forward.t, FS/t/h_svc_www.t,
+ httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/packages.html, ANNOUNCE.1.5.0:
+ historical (immutable) invoice details about services and other
+ history infrastructure
+
+2004-12-28 15:30 ivan
+
+ * FS/FS/part_export/sqlradius.pm: add debug flag to sqlradius
+ export
+
+2004-12-27 02:23 ivan
+
+ * ANNOUNCE.1.5.0: note integrated rt is updated
+
+2004-12-27 02:19 ivan
+
+ * FS/FS/: cust_pay.pm, cust_credit.pm: prevent unsuspension errors
+ from causing payment or credit transactions from finishing
+
+2004-12-27 01:23 ivan
+
+ * FS/FS/cust_main_county.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main/contact.html: UI: rework shipping
+ address javascript, closes: Bug#1085
+
+2004-12-24 15:35 ivan
+
+ * FS/FS/svc_acct.pm: smtp can have uid 0 in addition to root and
+ toor
+
+2004-12-24 15:28 ivan
+
+ * bin/passwd.import: remove $Id$ line
+
+2004-12-24 15:27 ivan
+
+ * bin/passwd.import: import NP and *LK* from shadow file as * (no
+ password)
+
+2004-12-23 18:54 ivan
+
+ * httemplate/edit/: cust_pay.cgi, process/cust_pay.cgi: add ability
+ to set payment date manually
+
+2004-12-23 03:39 ivan
+
+ * httemplate/edit/svc_www.cgi: fix typo that manifests when using
+ svc_www-enable_subdomains config option
+
+2004-12-23 01:15 ivan
+
+ * httemplate/edit/process/part_pkg.cgi: fix bug with custom pricing
+ packages when no primary service is selected
+
+2004-12-23 01:07 ivan
+
+ * FS/FS/part_pkg.pm: better debugging for options passed to insert
+ method
+
+2004-12-23 00:32 ivan
+
+ * README.1.5.0pre7, FS/bin/freeside-setup,
+ httemplate/docs/upgrade10.html: allow NULL zip in some countries
+
+2004-12-23 00:00 ivan
+
+ * README.1.5.0pre7, FS/bin/freeside-setup,
+ httemplate/docs/upgrade10.html: going with 6 digit misnamed "npa"
+ for now
+
+2004-12-23 00:00 ivan
+
+ * bin/: rate-us.import, rate.import: adding rate import scripts
+
+2004-12-22 23:29 ivan
+
+ * FS/FS/rate_region.pm: better short prefix display
+
+2004-12-22 23:28 ivan
+
+ * httemplate/edit/rate.cgi: hide US regions for now, we don't
+ currently need them for rating just invoice/session display and
+ the web pages are so giant they're timing out
+
+2004-12-22 06:40 ivan
+
+ * Makefile: chkconfig ON
+
+2004-12-22 06:09 ivan
+
+ * Makefile: /usr/bin/true on fleabsd
+
+2004-12-22 06:06 ivan
+
+ * httemplate/edit/: REAL_cust_pkg.cgi, process/REAL_cust_pkg.cgi:
+ warn and require confirmation when editing next bill dates to a
+ date in the past, closes; Bug#430
+
+2004-12-22 01:53 ivan
+
+ * FS/bin/freeside-daily: just "vaccum analyze" is fine
+
+2004-12-21 15:19 ivan
+
+ * FS/FS/rate_detail.pm: need to use table modules we call
+ ut_foreign_key on: rate, rate_region
+
+2004-12-20 03:41 ivan
+
+ * rt/FREESIDE_MODIFIED: backport from 3.3-TESTING to fix XSS on
+ ticket lists
+
+2004-12-20 03:29 ivan
+
+ * rt/html/Elements/CollectionAsTable/Row: backport from 3.3-TESTING
+ to fix XSS on ticket lists
+
+2004-12-20 02:13 ivan
+
+ * FS/FS/Misc.pm, FS/FS/cust_main.pm, httemplate/view/cust_bill.cgi:
+ better error messages on email errors
+
+2004-12-20 00:21 ivan
+
+ * Makefile: remove quotes which were causing problems. grr make
+
+2004-12-20 00:16 ivan
+
+ * Makefile: add init script enable command in deb and redhat
+
+2004-12-18 15:32 ivan
+
+ * httemplate/docs/: billing.html, install.html: add info about
+ teTeX and Ghostscript
+
+2004-12-18 02:52 ivan
+
+ * httemplate/index.html: fix spelling
+
+2004-12-13 01:13 ivan
+
+ * FS/FS/Conf.pm, httemplate/index.html: add config option for
+ address2 search, closes: Bug#1022
+
+2004-12-12 10:51 ivan
+
+ * httemplate/view/cust_main/quick-charge.html: fix form action url
+ for template
+
+2004-12-12 00:34 ivan
+
+ * FS/FS/cust_main.pm: fix customer status display for some cases
+ with suspended accounts
+
+2004-12-11 15:16 ivan
+
+ * FS/FS/part_export/acct_sql.pm: finish modification
+
+2004-12-11 14:50 ivan
+
+ * httemplate/docs/install.html: update install doc
+
+2004-12-11 12:41 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/part_bill_event.pm,
+ httemplate/edit/part_bill_event.cgi: add 'send_if_newest' invoice
+ event, closes: Bug#977
+
+2004-12-10 23:50 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/order_pkg.html,
+ httemplate/view/cust_main/packages.html,
+ httemplate/view/cust_main/payment_history.html,
+ httemplate/view/cust_main/quick-charge.html: voiding of echeck
+ payments instead of refunds
+
+2004-12-10 15:51 ivan
+
+ * httemplate/docs/selfservice.html: correct path to selfservice
+
+2004-12-10 14:28 ivan
+
+ * FS/FS/CGI.pm: ui tweak for small customer view - line up billing
+ and service address boxes
+
+2004-12-10 13:35 ivan
+
+ * rt/html/Elements/Header: fix link to freeside docs in RT header
+
+2004-12-10 13:25 ivan
+
+ * httemplate/docs/: overview-new.dia, overview-new.png: move the
+ "self-service SSH tunnel" label to avoid ambiguity
+
+2004-12-09 16:51 ivan
+
+ * FS/bin/freeside-setup: promo codes not unique...
+
+2004-12-09 16:04 ivan
+
+ * rt/html/Elements/Tabs: fix link back to billing main
+
+2004-12-09 15:14 ivan
+
+ * httemplate/search/cust_main.cgi: typo
+
+2004-12-09 15:05 ivan
+
+ * httemplate/search/cust_main.cgi: typo
+
+2004-12-09 14:26 ivan
+
+ * httemplate/search/cust_main.cgi: UI: dont link to empty lists
+
+2004-12-09 14:23 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: fix links to null custom
+ fields
+
+2004-12-09 14:20 ivan
+
+ * httemplate/search/cust_main.cgi: UI: dont link to empty lists
+
+2004-12-09 14:06 ivan
+
+ * httemplate/search/cust_main.cgi: UI: same font size as the rest
+ of the page
+
+2004-12-09 14:02 ivan
+
+ * httemplate/search/cust_main.cgi: UI: condense ticket subtable a
+ little
+
+2004-12-09 13:59 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: hopefully make links to search
+ for empty value of custom tickets work???
+
+2004-12-09 13:53 ivan
+
+ * httemplate/index.html: remove extra list item for now
+
+2004-12-09 13:33 ivan
+
+ * httemplate/view/cust_main/tickets.html,
+ FS/FS/TicketSystem/RT_External.pm: set default requestor to email
+ invoice addresses
+
+2004-12-09 12:43 ivan
+
+ * FS/bin/freeside-setup: fix some typos noticed by pbowen
+
+2004-12-09 04:46 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: fix new ticket link
+
+2004-12-09 04:18 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: narrow select to avoid pickup
+ up wrong id field
+
+2004-12-09 04:03 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: use new var
+
+2004-12-09 04:01 ivan
+
+ * FS/FS/Conf.pm: typo
+
+2004-12-09 03:57 ivan
+
+ * FS/FS/: Conf.pm, TicketSystem/RT_External.pm: add config value
+ for default queue id
+
+2004-12-09 03:17 ivan
+
+ * httemplate/index.html: finish up for now
+
+2004-12-09 02:07 ivan
+
+ * httemplate/search/cust_main.cgi: deuglify
+
+2004-12-09 01:57 ivan
+
+ * httemplate/search/cust_main.cgi: fix typo
+
+2004-12-09 01:21 ivan
+
+ * FS/FS/TicketSystem/RT_Internal.pm,
+ httemplate/search/cust_main.cgi,
+ FS/FS/TicketSystem/RT_External.pm, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_main/billing.html,
+ httemplate/view/cust_main/contacts.html,
+ httemplate/view/cust_main/misc.html,
+ httemplate/view/cust_main/tickets.html: more RT integration
+
+2004-12-06 06:42 ivan
+
+ * httemplate/search/cust_main.cgi: fix total link
+
+2004-12-06 06:36 ivan
+
+ * httemplate/search/cust_main.cgi: fix total links and line up
+ custom field columns
+
+2004-12-06 06:15 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: ... and this last piece of sql
+ too
+
+2004-12-06 06:13 ivan
+
+ * FS/FS/TicketSystem/RT_External.pm: and forgot to include the sql
+ for counting tickets with severities...
+
+2004-12-06 06:11 ivan
+
+ * FS/FS/TicketSystem/RT_Internal.pm: fix typo
+
+2004-12-06 06:09 ivan
+
+ * httemplate/search/cust_main.cgi: fix reading custome field values
+
+2004-12-06 06:00 ivan
+
+ * FS/FS/Conf.pm, FS/FS/TicketSystem.pm,
+ FS/FS/TicketSystem/RT_External.pm,
+ FS/FS/TicketSystem/RT_Internal.pm, FS/FS/TicketSystem/RT_Libs.pm,
+ httemplate/search/cust_main.cgi: 1st try at adding custom field
+ handling
+
+2004-12-06 00:09 ivan
+
+ * FS/FS/cust_bill.pm: fix harmless "Use of uninitialized value in
+ length" warning in latex escapes
+
+2004-12-05 22:56 ivan
+
+ * httemplate/search/cust_main.cgi: link customers back to tickets!
+
+2004-12-03 17:09 ivan
+
+ * rt/html/Elements/PageLayout: landing rt 3.2.2
+
+2004-12-03 15:41 ivan
+
+ * htetc/handler.pl: landing rt 3.2.2
+
+2004-12-03 13:23 ivan
+
+ * README.1.5.0pre7: landing RT 3.2.2
+
+2004-12-03 12:51 ivan
+
+ * rt/: config, config.pld, bin/rt-commit-handler.in,
+ etc/upgrade/2.1.71, html/Admin/Elements/ModifyQueue,
+ html/Admin/Elements/ModifyUser, html/Admin/Users/Prefs.html,
+ html/Elements/Footer, html/Elements/Header,
+ html/Elements/PageLayout, html/Elements/ShadedBox,
+ html/Elements/ShadedInputRow, html/Elements/ShadedRow,
+ html/Elements/SimpleSearch, html/Elements/Tabs,
+ html/Elements/ViewUser, html/NoAuth/webrt.css,
+ html/Search/Listing.html, html/Search/Elements/PickRestriction,
+ html/Search/Elements/TicketHeader,
+ html/Search/Elements/TicketHeaderCell,
+ html/Search/Elements/TicketRow, html/Ticket/Elements/EditLinks,
+ html/Ticket/Elements/ShowLink, html/Ticket/Elements/ShowLinks,
+ html/Ticket/Elements/ShowSummary, html/Ticket/Elements/Tabs,
+ sbin/rt-setup-database.in: landing rt 3.2.2
+
+2004-12-03 12:40 ivan
+
+ * rt/etc/upgrade/: 3.1.0/acl.Informix, 3.1.0/acl.Oracle,
+ 3.1.0/acl.Pg, 3.1.0/acl.SQLite, 3.1.0/acl.mysql, 3.1.0/content,
+ 3.1.0/schema.Informix, 3.1.0/schema.Oracle, 3.1.0/schema.Pg,
+ 3.1.0/schema.SQLite, 3.1.0/schema.mysql, 3.1.15/content,
+ 3.1.17/content: Initial revision
+
+2004-12-03 12:37 ivan
+
+ * rt/: html/Tools/MyDay.html, html/Tools/Offline.html,
+ html/Tools/Elements/Tabs, html/Ticket/ShowEmailRecord.html,
+ html/Ticket/Elements/ShowTransactionAttachments,
+ html/Ticket/Elements/PreviewScrips,
+ html/Ticket/Elements/ShowGroupMembers,
+ html/Ticket/Elements/ShowUserEntry, html/Search/Build.html,
+ html/Search/Edit.html, html/Search/Results.html,
+ html/Search/Results.rdf, html/Search/Results.tsv,
+ html/Search/Elements/BuildFormatString,
+ html/Search/Elements/DisplayOptions,
+ html/Search/Elements/EditSearches,
+ html/Search/Elements/NewListActions,
+ html/Search/Elements/PickCFs, html/Search/Elements/SearchPrivacy,
+ html/Search/Elements/SelectAndOr,
+ html/Search/Elements/SelectLinks,
+ html/Search/Elements/SelectPersonType,
+ html/Search/Elements/SelectSearchesForObjects,
+ html/Search/Elements/EditFormat, html/Search/Elements/PickBasics,
+ html/Search/Elements/PickCriteria,
+ html/Search/Elements/SelectSearchObject,
+ html/Admin/Tools/Configuration.html, html/Admin/Tools/index.html,
+ html/Admin/Elements/ToolTabs, html/Elements/ShowLinks,
+ html/Elements/EditLinks, html/Elements/QuickCreate,
+ html/Elements/ScrubHTML, html/Elements/TicketList,
+ html/Elements/ShowLink, html/Elements/TitleBox,
+ html/Elements/CollectionAsTable/Header,
+ html/Elements/CollectionAsTable/ParseFormat,
+ html/Elements/CollectionAsTable/Row,
+ html/Elements/RT__Ticket/ColumnMap,
+ html/NoAuth/images/autohandler, lib/t/05cronsupport.pl.in,
+ lib/RT/Attributes.pm, lib/RT/Attribute_Overlay.pm,
+ lib/RT/Attributes_Overlay.pm, lib/RT/Attribute.pm,
+ lib/RT/I18N/en_malkovich.po,
+ lib/RT/Action/RecordCorrespondence.pm,
+ lib/RT/Action/RecordComment.pm,
+ lib/RT/Interface/Email/Auth/GnuPG.pm,
+ lib/RT/Condition/PriorityChange.pm,
+ lib/RT/Interface/Web/Handler.pm, lib/RT/Search/FromSQL.pm,
+ bin/standalone_httpd.in, etc/schema.Sybase, etc/acl.Sybase:
+ Initial revision
+
+2004-12-03 12:27 ivan
+
+ * rt/sbin/: rt-setup-database, rt-test-dependencies: remove
+ autogenerated file
+
+2004-12-02 02:18 ivan
+
+ * httemplate/search/cust_main.cgi,
+ rt/html/Ticket/Elements/AddCustomers,
+ rt/html/Ticket/Elements/EditCustomers: fix license boilerplate
+ and search sorting
+
+2004-12-02 01:59 ivan
+
+ * httemplate/images/small-logo.png, rt/FREESIDE_MODIFIED,
+ rt/html/Elements/Header, rt/html/Elements/PageLayout,
+ FS/FS/CGI.pm, FS/FS/Conf.pm, FS/FS/TicketSystem.pm,
+ FS/FS/cust_main.pm, FS/FS/ClientAPI/Agent.pm,
+ httemplate/index.html, rt/html/Ticket/ModifyCustomers.html,
+ rt/html/Ticket/Elements/AddCustomers,
+ rt/html/Ticket/Elements/EditCustomers,
+ rt/html/Ticket/Elements/ShowCustomers,
+ rt/html/Ticket/Elements/ShowSummary,
+ rt/html/Ticket/Elements/Tabs, FS/FS/TicketSystem/RT_Internal.pm,
+ FS/FS/TicketSystem/RT_Libs.pm, htetc/global.asa,
+ htetc/handler.pl, httemplate/search/cust_main.cgi,
+ rt/lib/RT/Interface/Web_Vendor.pm, rt/lib/RT/URI/freeside.pm:
+ second big RT integration checkin, customer linking/delinking
+ interface
+
+2004-12-01 10:49 ivan
+
+ * FS/FS/cust_pkg.pm: don't check that agent is allowed to purchase
+ the package on changes
+
+2004-12-01 10:38 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: add processing for ship
+ state/county/country
+
+2004-11-30 19:35 ivan
+
+ * FS/FS/part_pkg.pm, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/flat_comission.pm,
+ FS/FS/part_pkg/flat_comission_cust.pm,
+ FS/FS/part_pkg/flat_comission_pkg.pm,
+ FS/FS/part_pkg/flat_delayed.pm, FS/FS/part_pkg/prorate.pm,
+ FS/FS/part_pkg/sesmon_hour.pm, FS/FS/part_pkg/sesmon_minute.pm,
+ FS/FS/part_pkg/sql_external.pm, FS/FS/part_pkg/sql_generic.pm,
+ FS/FS/part_pkg/sqlradacct_hour.pm,
+ FS/FS/part_pkg/subscription.pm,
+ FS/FS/part_pkg/voip_sqlradacct.pm,
+ fs_signup/FS-SignupClient/cgi/signup-freeoption.html:
+ creditcard-less promo code signup
+
+2004-11-30 11:55 khoff
+
+ * httemplate/view/svc_broadband.cgi: Got a little trigger happy
+ with the search/replace.
+
+2004-11-29 15:52 khoff
+
+ * httemplate/view/svc_broadband.cgi: Include netmask and gateway in
+ broadband service view.
+
+2004-11-27 11:09 ivan
+
+ * FS/FS/Conf.pm, FS/FS/TicketSystem/RT_External.pm,
+ FS/FS/TicketSystem/RT_Internal.pm, FS/FS/TicketSystem/RT_Libs.pm,
+ httemplate/index.html, rt/FREESIDE_MODIFIED,
+ rt/html/Elements/Footer, rt/html/Elements/Header,
+ rt/html/Elements/PageLayout, rt/html/Elements/SimpleSearch,
+ rt/html/Elements/Tabs, ANNOUNCE.1.5.0, Makefile, FS/FS.pm,
+ htetc/global.asa, htetc/handler.pl, rt/html/NoAuth/webrt.css,
+ rt/html/NoAuth/images/small-logo.png: ticket system integration
+ framework and skin RT
+
+2004-11-26 01:39 ivan
+
+ * FS/FS/: agent_type.pm, cust_credit_refund.pm,
+ cust_main_invoice.pm, nas.pm, part_pop_local.pm,
+ part_svc_column.pm, part_virtual_field.pm, port.pm, queue.pm,
+ queue_arg.pm, router.pm, session.pm, svc_acct_pop.pm,
+ type_pkgs.pm: remove POD VERSION sections
+
+2004-11-26 01:08 ivan
+
+ * FS/FS/Conf.pm: update description for signup_server-realtime to
+ reflect current reality, closes: Bug#575
+
+2004-11-26 00:51 ivan
+
+ * FS/FS/part_pkg.pm, httemplate/edit/process/part_pkg.cgi: move
+ part_pkg transactional stuff from web interface to part_pkg.pm,
+ bumps Bug#18 to 1.5
+
+2004-11-25 22:50 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add password-noampersand and
+ password-noexlamation config files, patch from Stephpen Bechard,
+ closes: Bug#539
+
+2004-11-24 12:54 ivan
+
+ * Makefile: don't enabled RT by default
+
+2004-11-24 10:28 khoff
+
+ * httemplate/: index.html, search/svc_broadband.cgi: Added IP
+ address search.
+
+2004-11-24 02:28 ivan
+
+ * httemplate/edit/process/cust_main.cgi: fix redundant too-early
+ checks which are causing an error
+
+2004-11-24 01:00 ivan
+
+ * Makefile: some RT install updates
+
+2004-11-23 17:30 ivan
+
+ * FS/bin/freeside-daily: fix perms on automated backups
+
+2004-11-23 17:28 ivan
+
+ * httemplate/index.html: add rate plan maintenance to sysadmin
+ section
+
+2004-11-22 10:20 ivan
+
+ * README.1.5.0pre7, FS/FS/ClientAPI/Signup.pm,
+ FS/bin/freeside-setup, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html, FS/FS/Record.pm,
+ FS/FS/cust_pkg.pm, FS/FS/part_pkg.pm,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/cgi/promocode.html,
+ fs_signup/FS-SignupClient/cgi/signup-billaddress.html,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/edit/cust_main.cgi, httemplate/edit/part_pkg.cgi:
+ promo codes and separate signup addresses for hdn
+
+2004-11-22 03:11 ivan
+
+ * httemplate/search/sqlradius.cgi: Called-Station-ID label
+
+2004-11-21 18:31 ivan
+
+ * httemplate/search/: sqlradius.cgi, sqlradius.html: UI fix on
+ search directions, fix bug preventing show_called_station,
+ hide_ip and hide_data form working
+
+2004-11-20 09:26 ivan
+
+ * FS/FS/cust_svc.pm, FS/FS/rate.pm, FS/FS/rate_detail.pm,
+ FS/FS/rate_prefix.pm, FS/FS/rate_region.pm,
+ FS/t/part_pkg-voip_sqlradacct.t, FS/t/rate.t, FS/t/rate_detail.t,
+ FS/t/rate_prefix.t, FS/t/rate_region.t, ANNOUNCE.1.5.0,
+ README.1.5.0pre7, SCHEMA_CHANGE,
+ FS/FS/part_pkg/voip_sqlradacct.pm, FS/bin/freeside-setup,
+ httemplate/browse/rate.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/rate.cgi, httemplate/edit/rate_region.cgi,
+ httemplate/edit/process/rate.cgi,
+ httemplate/edit/process/rate_region.cgi, FS/FS.pm, FS/MANIFEST,
+ FS/FS/part_export/sqlradius.pm, eg/table_template.pm,
+ htetc/global.asa, htetc/handler.pl,
+ httemplate/search/sqlradius.cgi,
+ httemplate/search/sqlradius.html: first pass at VoIP rating
+
+2004-11-17 21:06 ivan
+
+ * sql-ledger/: doc/copyright, locale/cn/COPYING,
+ locale/cn/LANGUAGE, locale/cn/admin, locale/cn/all, locale/cn/am,
+ locale/cn/ap, locale/cn/ar, locale/cn/arap, locale/cn/ca,
+ locale/cn/cp, locale/cn/ct, locale/cn/gl, locale/cn/ic,
+ locale/cn/io, locale/cn/ir, locale/cn/is, locale/cn/login,
+ locale/cn/menu, locale/cn/oe, locale/cn/pe, locale/cn/rc,
+ locale/cn/rp, locale/de/all, locale/es/COPYING,
+ locale/es/LANGUAGE, locale/es/Num2text, locale/es/admin,
+ locale/es/all, locale/es/am, locale/es/ap, locale/es/ar,
+ locale/es/arap, locale/es/ca, locale/es/cp, locale/es/ct,
+ locale/es/gl, locale/es/ic, locale/es/io, locale/es/ir,
+ locale/es/is, locale/es/login, locale/es/menu, locale/es/oe,
+ locale/es/pe, locale/es/rc, locale/es/rp, locale/no/COPYING,
+ locale/no/LANGUAGE, locale/no/admin, locale/no/all, locale/no/am,
+ locale/no/ap, locale/no/ar, locale/no/arap, locale/no/ca,
+ locale/no/cp, locale/no/ct, locale/no/gl, locale/no/ic,
+ locale/no/io, locale/no/ir, locale/no/is, locale/no/login,
+ locale/no/menu, locale/no/oe, locale/no/pe, locale/no/rc,
+ locale/no/rp, locale/tw/COPYING, locale/tw/LANGUAGE,
+ locale/tw/admin, locale/tw/all, locale/tw/am, locale/tw/ap,
+ locale/tw/ar, locale/tw/arap, locale/tw/ca, locale/tw/cp,
+ locale/tw/ct, locale/tw/gl, locale/tw/ic, locale/tw/io,
+ locale/tw/ir, locale/tw/is, locale/tw/login, locale/tw/menu,
+ locale/tw/oe, locale/tw/pe, locale/tw/rc, locale/tw/rp,
+ sql/Canada-gifi.sql, sql/Canada_General-chart.sql,
+ sql/Czech_Republic-chart.sql, sql/Italy-chart.sql,
+ sql/Simplified_Chinese_Default-chart.sql, sql/Spain-chart.sql,
+ sql/Traditional_Chinese_Default-chart.sql, users/members.default:
+ removing files moved in 2.4.4
+
+2004-11-17 05:22 ivan
+
+ * httemplate/edit/part_pkg.cgi: #debugging cruft
+
+2004-11-17 05:19 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix package options to be sticky on
+ clone-ing (customize package)
+
+2004-11-16 14:12 ivan
+
+ * sql-ledger/: sql-ledger-2.0.8.tar.gz, sql-ledger-2.4.4.tar.gz,
+ old/sql-ledger/VERSION, old/sql-ledger/am.pl,
+ old/sql-ledger/favicon.ico, old/sql-ledger/login.pl,
+ old/sql-ledger/menu.ini, old/sql-ledger/setup.pl,
+ old/sql-ledger/sql-ledger.conf.default,
+ old/sql-ledger/sql-ledger.png, old/sql-ledger/SL/AM.pm,
+ old/sql-ledger/SL/AP.pm, old/sql-ledger/SL/AR.pm,
+ old/sql-ledger/SL/CA.pm, old/sql-ledger/SL/CP.pm,
+ old/sql-ledger/SL/CT.pm, old/sql-ledger/SL/Form.pm,
+ old/sql-ledger/SL/GL.pm, old/sql-ledger/SL/IC.pm,
+ old/sql-ledger/SL/IR.pm, old/sql-ledger/SL/IS.pm,
+ old/sql-ledger/SL/Inifile.pm, old/sql-ledger/SL/Mailer.pm,
+ old/sql-ledger/SL/Menu.pm, old/sql-ledger/SL/Num2text.pm,
+ old/sql-ledger/SL/OE.pm, old/sql-ledger/SL/PE.pm,
+ old/sql-ledger/SL/RC.pm, old/sql-ledger/SL/RP.pm,
+ old/sql-ledger/SL/User.pm, old/sql-ledger/bin/lynx/menu.pl,
+ old/sql-ledger/bin/mozilla/admin.pl,
+ old/sql-ledger/bin/mozilla/am.pl,
+ old/sql-ledger/bin/mozilla/ap.pl,
+ old/sql-ledger/bin/mozilla/ar.pl,
+ old/sql-ledger/bin/mozilla/arap.pl,
+ old/sql-ledger/bin/mozilla/ca.pl,
+ old/sql-ledger/bin/mozilla/cp.pl,
+ old/sql-ledger/bin/mozilla/ct.pl,
+ old/sql-ledger/bin/mozilla/gl.pl,
+ old/sql-ledger/bin/mozilla/ic.pl,
+ old/sql-ledger/bin/mozilla/io.pl,
+ old/sql-ledger/bin/mozilla/ir.pl,
+ old/sql-ledger/bin/mozilla/is.pl,
+ old/sql-ledger/bin/mozilla/login.pl,
+ old/sql-ledger/bin/mozilla/menu.pl,
+ old/sql-ledger/bin/mozilla/oe.pl,
+ old/sql-ledger/bin/mozilla/pe.pl,
+ old/sql-ledger/bin/mozilla/rc.pl,
+ old/sql-ledger/bin/mozilla/rp.pl,
+ old/sql-ledger/css/sql-ledger.css, old/sql-ledger/doc/COPYING,
+ old/sql-ledger/doc/README, old/sql-ledger/doc/UPGRADE-1.6-1.8,
+ old/sql-ledger/doc/UPGRADE-1.8-1.8.3,
+ old/sql-ledger/doc/UPGRADE-1.8.3-1.8.4,
+ old/sql-ledger/doc/UPGRADE-1.8.4-1.8.5,
+ old/sql-ledger/doc/UPGRADE-1.8.5-1.8.7,
+ old/sql-ledger/doc/UPGRADE-1.8.7-2.0.0,
+ old/sql-ledger/doc/UPGRADE-2.0-2.0.8,
+ old/sql-ledger/doc/copyright, old/sql-ledger/doc/faq.html,
+ old/sql-ledger/locale/br/COPYING,
+ old/sql-ledger/locale/br/LANGUAGE,
+ old/sql-ledger/locale/br/admin, old/sql-ledger/locale/br/all,
+ old/sql-ledger/locale/br/am, old/sql-ledger/locale/br/ap,
+ old/sql-ledger/locale/br/ar, old/sql-ledger/locale/br/arap,
+ old/sql-ledger/locale/br/ca, old/sql-ledger/locale/br/cp,
+ old/sql-ledger/locale/br/ct, old/sql-ledger/locale/br/gl,
+ old/sql-ledger/locale/br/ic, old/sql-ledger/locale/br/io,
+ old/sql-ledger/locale/br/ir, old/sql-ledger/locale/br/is,
+ old/sql-ledger/locale/br/login, old/sql-ledger/locale/br/menu,
+ old/sql-ledger/locale/br/oe, old/sql-ledger/locale/br/pe,
+ old/sql-ledger/locale/br/rc, old/sql-ledger/locale/br/rp,
+ old/sql-ledger/locale/cn/COPYING,
+ old/sql-ledger/locale/cn/LANGUAGE,
+ old/sql-ledger/locale/cn/admin, old/sql-ledger/locale/cn/all,
+ old/sql-ledger/locale/cn/am, old/sql-ledger/locale/cn/ap,
+ old/sql-ledger/locale/cn/ar, old/sql-ledger/locale/cn/arap,
+ old/sql-ledger/locale/cn/ca, old/sql-ledger/locale/cn/cp,
+ old/sql-ledger/locale/cn/ct, old/sql-ledger/locale/cn/gl,
+ old/sql-ledger/locale/cn/ic, old/sql-ledger/locale/cn/io,
+ old/sql-ledger/locale/cn/ir, old/sql-ledger/locale/cn/is,
+ old/sql-ledger/locale/cn/login, old/sql-ledger/locale/cn/menu,
+ old/sql-ledger/locale/cn/oe, old/sql-ledger/locale/cn/pe,
+ old/sql-ledger/locale/cn/rc, old/sql-ledger/locale/cn/rp,
+ old/sql-ledger/locale/ct/COPYING,
+ old/sql-ledger/locale/ct/LANGUAGE,
+ old/sql-ledger/locale/ct/admin, old/sql-ledger/locale/ct/all,
+ old/sql-ledger/locale/ct/am, old/sql-ledger/locale/ct/ap,
+ old/sql-ledger/locale/ct/ar, old/sql-ledger/locale/ct/arap,
+ old/sql-ledger/locale/ct/ca, old/sql-ledger/locale/ct/cp,
+ old/sql-ledger/locale/ct/ct, old/sql-ledger/locale/ct/gl,
+ old/sql-ledger/locale/ct/ic, old/sql-ledger/locale/ct/io,
+ old/sql-ledger/locale/ct/ir, old/sql-ledger/locale/ct/is,
+ old/sql-ledger/locale/ct/login, old/sql-ledger/locale/ct/menu,
+ old/sql-ledger/locale/ct/oe, old/sql-ledger/locale/ct/pe,
+ old/sql-ledger/locale/ct/rc, old/sql-ledger/locale/ct/rp,
+ old/sql-ledger/locale/cz/COPYING,
+ old/sql-ledger/locale/cz/LANGUAGE,
+ old/sql-ledger/locale/cz/admin, old/sql-ledger/locale/cz/all,
+ old/sql-ledger/locale/cz/am, old/sql-ledger/locale/cz/ap,
+ old/sql-ledger/locale/cz/ar, old/sql-ledger/locale/cz/arap,
+ old/sql-ledger/locale/cz/ca, old/sql-ledger/locale/cz/cp,
+ old/sql-ledger/locale/cz/ct, old/sql-ledger/locale/cz/gl,
+ old/sql-ledger/locale/cz/ic, old/sql-ledger/locale/cz/io,
+ old/sql-ledger/locale/cz/ir, old/sql-ledger/locale/cz/is,
+ old/sql-ledger/locale/cz/login, old/sql-ledger/locale/cz/menu,
+ old/sql-ledger/locale/cz/oe, old/sql-ledger/locale/cz/pe,
+ old/sql-ledger/locale/cz/rc, old/sql-ledger/locale/cz/rp,
+ old/sql-ledger/locale/de/COPYING,
+ old/sql-ledger/locale/de/LANGUAGE,
+ old/sql-ledger/locale/de/Num2text,
+ old/sql-ledger/locale/de/admin, old/sql-ledger/locale/de/all,
+ old/sql-ledger/locale/de/am, old/sql-ledger/locale/de/ap,
+ old/sql-ledger/locale/de/ar, old/sql-ledger/locale/de/arap,
+ old/sql-ledger/locale/de/ca, old/sql-ledger/locale/de/cp,
+ old/sql-ledger/locale/de/ct, old/sql-ledger/locale/de/gl,
+ old/sql-ledger/locale/de/ic, old/sql-ledger/locale/de/io,
+ old/sql-ledger/locale/de/ir, old/sql-ledger/locale/de/is,
+ old/sql-ledger/locale/de/locales.pl,
+ old/sql-ledger/locale/de/login, old/sql-ledger/locale/de/menu,
+ old/sql-ledger/locale/de/oe, old/sql-ledger/locale/de/pe,
+ old/sql-ledger/locale/de/rc, old/sql-ledger/locale/de/rp,
+ old/sql-ledger/locale/dk/COPYING,
+ old/sql-ledger/locale/dk/LANGUAGE,
+ old/sql-ledger/locale/dk/admin, old/sql-ledger/locale/dk/all,
+ old/sql-ledger/locale/dk/am, old/sql-ledger/locale/dk/ap,
+ old/sql-ledger/locale/dk/ar, old/sql-ledger/locale/dk/arap,
+ old/sql-ledger/locale/dk/ca, old/sql-ledger/locale/dk/cp,
+ old/sql-ledger/locale/dk/ct, old/sql-ledger/locale/dk/gl,
+ old/sql-ledger/locale/dk/ic, old/sql-ledger/locale/dk/io,
+ old/sql-ledger/locale/dk/ir, old/sql-ledger/locale/dk/is,
+ old/sql-ledger/locale/dk/login, old/sql-ledger/locale/dk/menu,
+ old/sql-ledger/locale/dk/oe, old/sql-ledger/locale/dk/pe,
+ old/sql-ledger/locale/dk/rc, old/sql-ledger/locale/dk/rp,
+ old/sql-ledger/locale/ee/COPYING,
+ old/sql-ledger/locale/ee/LANGUAGE,
+ old/sql-ledger/locale/ee/admin, old/sql-ledger/locale/ee/all,
+ old/sql-ledger/locale/ee/am, old/sql-ledger/locale/ee/ap,
+ old/sql-ledger/locale/ee/ar, old/sql-ledger/locale/ee/arap,
+ old/sql-ledger/locale/ee/ca, old/sql-ledger/locale/ee/cp,
+ old/sql-ledger/locale/ee/ct, old/sql-ledger/locale/ee/gl,
+ old/sql-ledger/locale/ee/ic, old/sql-ledger/locale/ee/io,
+ old/sql-ledger/locale/ee/ir, old/sql-ledger/locale/ee/is,
+ old/sql-ledger/locale/ee/login, old/sql-ledger/locale/ee/menu,
+ old/sql-ledger/locale/ee/oe, old/sql-ledger/locale/ee/pe,
+ old/sql-ledger/locale/ee/rc, old/sql-ledger/locale/ee/rp,
+ old/sql-ledger/locale/en_GB/COPYING,
+ old/sql-ledger/locale/en_GB/LANGUAGE,
+ old/sql-ledger/locale/en_GB/admin,
+ old/sql-ledger/locale/en_GB/all, old/sql-ledger/locale/en_GB/am,
+ old/sql-ledger/locale/en_GB/ap, old/sql-ledger/locale/en_GB/ar,
+ old/sql-ledger/locale/en_GB/arap, old/sql-ledger/locale/en_GB/bp,
+ old/sql-ledger/locale/en_GB/ca, old/sql-ledger/locale/en_GB/cp,
+ old/sql-ledger/locale/en_GB/ct, old/sql-ledger/locale/en_GB/gl,
+ old/sql-ledger/locale/en_GB/ic, old/sql-ledger/locale/en_GB/io,
+ old/sql-ledger/locale/en_GB/ir, old/sql-ledger/locale/en_GB/is,
+ old/sql-ledger/locale/en_GB/login,
+ old/sql-ledger/locale/en_GB/menu, old/sql-ledger/locale/en_GB/oe,
+ old/sql-ledger/locale/en_GB/pe, old/sql-ledger/locale/en_GB/rc,
+ old/sql-ledger/locale/en_GB/rp, old/sql-ledger/locale/es/COPYING,
+ old/sql-ledger/locale/es/LANGUAGE,
+ old/sql-ledger/locale/es/Num2text,
+ old/sql-ledger/locale/es/admin, old/sql-ledger/locale/es/all,
+ old/sql-ledger/locale/es/am, old/sql-ledger/locale/es/ap,
+ old/sql-ledger/locale/es/ar, old/sql-ledger/locale/es/arap,
+ old/sql-ledger/locale/es/ca, old/sql-ledger/locale/es/cp,
+ old/sql-ledger/locale/es/ct, old/sql-ledger/locale/es/gl,
+ old/sql-ledger/locale/es/ic, old/sql-ledger/locale/es/io,
+ old/sql-ledger/locale/es/ir, old/sql-ledger/locale/es/is,
+ old/sql-ledger/locale/es/login, old/sql-ledger/locale/es/menu,
+ old/sql-ledger/locale/es/oe, old/sql-ledger/locale/es/pe,
+ old/sql-ledger/locale/es/rc, old/sql-ledger/locale/es/rp,
+ old/sql-ledger/locale/fi/COPYING,
+ old/sql-ledger/locale/fi/LANGUAGE,
+ old/sql-ledger/locale/fi/admin, old/sql-ledger/locale/fi/all,
+ old/sql-ledger/locale/fi/am, old/sql-ledger/locale/fi/ap,
+ old/sql-ledger/locale/fi/ar, old/sql-ledger/locale/fi/arap,
+ old/sql-ledger/locale/fi/ca, old/sql-ledger/locale/fi/cp,
+ old/sql-ledger/locale/fi/ct, old/sql-ledger/locale/fi/gl,
+ old/sql-ledger/locale/fi/ic, old/sql-ledger/locale/fi/io,
+ old/sql-ledger/locale/fi/ir, old/sql-ledger/locale/fi/is,
+ old/sql-ledger/locale/fi/login, old/sql-ledger/locale/fi/menu,
+ old/sql-ledger/locale/fi/oe, old/sql-ledger/locale/fi/pe,
+ old/sql-ledger/locale/fi/rc, old/sql-ledger/locale/fi/rp,
+ old/sql-ledger/locale/fr/COPYING,
+ old/sql-ledger/locale/fr/LANGUAGE,
+ old/sql-ledger/locale/fr/admin, old/sql-ledger/locale/fr/all,
+ old/sql-ledger/locale/fr/am, old/sql-ledger/locale/fr/ap,
+ old/sql-ledger/locale/fr/ar, old/sql-ledger/locale/fr/arap,
+ old/sql-ledger/locale/fr/ca, old/sql-ledger/locale/fr/cp,
+ old/sql-ledger/locale/fr/ct, old/sql-ledger/locale/fr/gl,
+ old/sql-ledger/locale/fr/ic, old/sql-ledger/locale/fr/io,
+ old/sql-ledger/locale/fr/ir, old/sql-ledger/locale/fr/is,
+ old/sql-ledger/locale/fr/login, old/sql-ledger/locale/fr/menu,
+ old/sql-ledger/locale/fr/oe, old/sql-ledger/locale/fr/pe,
+ old/sql-ledger/locale/fr/rc, old/sql-ledger/locale/fr/rp,
+ old/sql-ledger/locale/hu/COPYING,
+ old/sql-ledger/locale/hu/LANGUAGE,
+ old/sql-ledger/locale/hu/admin, old/sql-ledger/locale/hu/all,
+ old/sql-ledger/locale/hu/am, old/sql-ledger/locale/hu/ap,
+ old/sql-ledger/locale/hu/ar, old/sql-ledger/locale/hu/arap,
+ old/sql-ledger/locale/hu/ca, old/sql-ledger/locale/hu/cp,
+ old/sql-ledger/locale/hu/ct, old/sql-ledger/locale/hu/gl,
+ old/sql-ledger/locale/hu/ic, old/sql-ledger/locale/hu/io,
+ old/sql-ledger/locale/hu/ir, old/sql-ledger/locale/hu/is,
+ old/sql-ledger/locale/hu/login, old/sql-ledger/locale/hu/menu,
+ old/sql-ledger/locale/hu/oe, old/sql-ledger/locale/hu/pe,
+ old/sql-ledger/locale/hu/rc, old/sql-ledger/locale/hu/rp,
+ old/sql-ledger/locale/is/COPYING,
+ old/sql-ledger/locale/is/LANGUAGE,
+ old/sql-ledger/locale/is/admin, old/sql-ledger/locale/is/all,
+ old/sql-ledger/locale/is/am, old/sql-ledger/locale/is/ap,
+ old/sql-ledger/locale/is/ar, old/sql-ledger/locale/is/arap,
+ old/sql-ledger/locale/is/ca, old/sql-ledger/locale/is/cp,
+ old/sql-ledger/locale/is/ct, old/sql-ledger/locale/is/gl,
+ old/sql-ledger/locale/is/ic, old/sql-ledger/locale/is/io,
+ old/sql-ledger/locale/is/ir, old/sql-ledger/locale/is/is,
+ old/sql-ledger/locale/is/login, old/sql-ledger/locale/is/menu,
+ old/sql-ledger/locale/is/oe, old/sql-ledger/locale/is/pe,
+ old/sql-ledger/locale/is/rc, old/sql-ledger/locale/is/rp,
+ old/sql-ledger/locale/it/COPYING,
+ old/sql-ledger/locale/it/LANGUAGE,
+ old/sql-ledger/locale/it/Num2text,
+ old/sql-ledger/locale/it/admin, old/sql-ledger/locale/it/all,
+ old/sql-ledger/locale/it/am, old/sql-ledger/locale/it/ap,
+ old/sql-ledger/locale/it/ar, old/sql-ledger/locale/it/arap,
+ old/sql-ledger/locale/it/ca, old/sql-ledger/locale/it/cp,
+ old/sql-ledger/locale/it/ct, old/sql-ledger/locale/it/gl,
+ old/sql-ledger/locale/it/ic, old/sql-ledger/locale/it/io,
+ old/sql-ledger/locale/it/ir, old/sql-ledger/locale/it/is,
+ old/sql-ledger/locale/it/login, old/sql-ledger/locale/it/menu,
+ old/sql-ledger/locale/it/oe, old/sql-ledger/locale/it/pe,
+ old/sql-ledger/locale/it/qe, old/sql-ledger/locale/it/rc,
+ old/sql-ledger/locale/it/rp, old/sql-ledger/locale/lt/COPYING,
+ old/sql-ledger/locale/lt/LANGUAGE,
+ old/sql-ledger/locale/lt/admin, old/sql-ledger/locale/lt/all,
+ old/sql-ledger/locale/lt/am, old/sql-ledger/locale/lt/ap,
+ old/sql-ledger/locale/lt/ar, old/sql-ledger/locale/lt/arap,
+ old/sql-ledger/locale/lt/ca, old/sql-ledger/locale/lt/cp,
+ old/sql-ledger/locale/lt/ct, old/sql-ledger/locale/lt/gl,
+ old/sql-ledger/locale/lt/ic, old/sql-ledger/locale/lt/io,
+ old/sql-ledger/locale/lt/ir, old/sql-ledger/locale/lt/is,
+ old/sql-ledger/locale/lt/login, old/sql-ledger/locale/lt/menu,
+ old/sql-ledger/locale/lt/oe, old/sql-ledger/locale/lt/pe,
+ old/sql-ledger/locale/lt/rc, old/sql-ledger/locale/lt/rp,
+ old/sql-ledger/locale/mx/COPYING,
+ old/sql-ledger/locale/mx/LANGUAGE,
+ old/sql-ledger/locale/mx/admin, old/sql-ledger/locale/mx/all,
+ old/sql-ledger/locale/mx/am, old/sql-ledger/locale/mx/ap,
+ old/sql-ledger/locale/mx/ar, old/sql-ledger/locale/mx/arap,
+ old/sql-ledger/locale/mx/ca, old/sql-ledger/locale/mx/cp,
+ old/sql-ledger/locale/mx/ct, old/sql-ledger/locale/mx/gl,
+ old/sql-ledger/locale/mx/ic, old/sql-ledger/locale/mx/io,
+ old/sql-ledger/locale/mx/ir, old/sql-ledger/locale/mx/is,
+ old/sql-ledger/locale/mx/login, old/sql-ledger/locale/mx/menu,
+ old/sql-ledger/locale/mx/oe, old/sql-ledger/locale/mx/pe,
+ old/sql-ledger/locale/mx/rc, old/sql-ledger/locale/mx/rp,
+ old/sql-ledger/locale/nl/COPYING,
+ old/sql-ledger/locale/nl/LANGUAGE,
+ old/sql-ledger/locale/nl/Num2text,
+ old/sql-ledger/locale/nl/admin, old/sql-ledger/locale/nl/all,
+ old/sql-ledger/locale/nl/am, old/sql-ledger/locale/nl/ap,
+ old/sql-ledger/locale/nl/ar, old/sql-ledger/locale/nl/arap,
+ old/sql-ledger/locale/nl/ca, old/sql-ledger/locale/nl/cp,
+ old/sql-ledger/locale/nl/ct, old/sql-ledger/locale/nl/gl,
+ old/sql-ledger/locale/nl/ic, old/sql-ledger/locale/nl/io,
+ old/sql-ledger/locale/nl/ir, old/sql-ledger/locale/nl/is,
+ old/sql-ledger/locale/nl/login, old/sql-ledger/locale/nl/menu,
+ old/sql-ledger/locale/nl/oe, old/sql-ledger/locale/nl/pe,
+ old/sql-ledger/locale/nl/rc, old/sql-ledger/locale/nl/rp,
+ old/sql-ledger/locale/no/COPYING,
+ old/sql-ledger/locale/no/LANGUAGE,
+ old/sql-ledger/locale/no/admin, old/sql-ledger/locale/no/all,
+ old/sql-ledger/locale/no/am, old/sql-ledger/locale/no/ap,
+ old/sql-ledger/locale/no/ar, old/sql-ledger/locale/no/arap,
+ old/sql-ledger/locale/no/ca, old/sql-ledger/locale/no/cp,
+ old/sql-ledger/locale/no/ct, old/sql-ledger/locale/no/gl,
+ old/sql-ledger/locale/no/ic, old/sql-ledger/locale/no/io,
+ old/sql-ledger/locale/no/ir, old/sql-ledger/locale/no/is,
+ old/sql-ledger/locale/no/login, old/sql-ledger/locale/no/menu,
+ old/sql-ledger/locale/no/oe, old/sql-ledger/locale/no/pe,
+ old/sql-ledger/locale/no/rc, old/sql-ledger/locale/no/rp,
+ old/sql-ledger/locale/pa/COPYING,
+ old/sql-ledger/locale/pa/LANGUAGE,
+ old/sql-ledger/locale/pa/admin, old/sql-ledger/locale/pa/all,
+ old/sql-ledger/locale/pa/am, old/sql-ledger/locale/pa/ap,
+ old/sql-ledger/locale/pa/ar, old/sql-ledger/locale/pa/arap,
+ old/sql-ledger/locale/pa/ca, old/sql-ledger/locale/pa/cp,
+ old/sql-ledger/locale/pa/ct, old/sql-ledger/locale/pa/gl,
+ old/sql-ledger/locale/pa/ic, old/sql-ledger/locale/pa/io,
+ old/sql-ledger/locale/pa/ir, old/sql-ledger/locale/pa/is,
+ old/sql-ledger/locale/pa/login, old/sql-ledger/locale/pa/menu,
+ old/sql-ledger/locale/pa/oe, old/sql-ledger/locale/pa/pe,
+ old/sql-ledger/locale/pa/rc, old/sql-ledger/locale/pa/rp,
+ old/sql-ledger/locale/pl/COPYING,
+ old/sql-ledger/locale/pl/LANGUAGE,
+ old/sql-ledger/locale/pl/admin, old/sql-ledger/locale/pl/all,
+ old/sql-ledger/locale/pl/am, old/sql-ledger/locale/pl/ap,
+ old/sql-ledger/locale/pl/ar, old/sql-ledger/locale/pl/arap,
+ old/sql-ledger/locale/pl/ca, old/sql-ledger/locale/pl/cp,
+ old/sql-ledger/locale/pl/ct, old/sql-ledger/locale/pl/gl,
+ old/sql-ledger/locale/pl/ic, old/sql-ledger/locale/pl/io,
+ old/sql-ledger/locale/pl/ir, old/sql-ledger/locale/pl/is,
+ old/sql-ledger/locale/pl/login, old/sql-ledger/locale/pl/menu,
+ old/sql-ledger/locale/pl/oe, old/sql-ledger/locale/pl/pe,
+ old/sql-ledger/locale/pl/rc, old/sql-ledger/locale/pl/rp,
+ old/sql-ledger/locale/pt/COPYING,
+ old/sql-ledger/locale/pt/LANGUAGE,
+ old/sql-ledger/locale/pt/admin, old/sql-ledger/locale/pt/all,
+ old/sql-ledger/locale/pt/am, old/sql-ledger/locale/pt/ap,
+ old/sql-ledger/locale/pt/ar, old/sql-ledger/locale/pt/arap,
+ old/sql-ledger/locale/pt/ca, old/sql-ledger/locale/pt/cp,
+ old/sql-ledger/locale/pt/ct, old/sql-ledger/locale/pt/gl,
+ old/sql-ledger/locale/pt/ic, old/sql-ledger/locale/pt/io,
+ old/sql-ledger/locale/pt/ir, old/sql-ledger/locale/pt/is,
+ old/sql-ledger/locale/pt/login, old/sql-ledger/locale/pt/menu,
+ old/sql-ledger/locale/pt/oe, old/sql-ledger/locale/pt/pe,
+ old/sql-ledger/locale/pt/rc, old/sql-ledger/locale/pt/rp,
+ old/sql-ledger/locale/ru/COPYING,
+ old/sql-ledger/locale/ru/LANGUAGE,
+ old/sql-ledger/locale/ru/admin, old/sql-ledger/locale/ru/all,
+ old/sql-ledger/locale/ru/am, old/sql-ledger/locale/ru/ap,
+ old/sql-ledger/locale/ru/ar, old/sql-ledger/locale/ru/arap,
+ old/sql-ledger/locale/ru/ca, old/sql-ledger/locale/ru/cp,
+ old/sql-ledger/locale/ru/ct, old/sql-ledger/locale/ru/gl,
+ old/sql-ledger/locale/ru/ic, old/sql-ledger/locale/ru/io,
+ old/sql-ledger/locale/ru/ir, old/sql-ledger/locale/ru/is,
+ old/sql-ledger/locale/ru/login, old/sql-ledger/locale/ru/menu,
+ old/sql-ledger/locale/ru/oe, old/sql-ledger/locale/ru/pe,
+ old/sql-ledger/locale/ru/rc, old/sql-ledger/locale/ru/rp,
+ old/sql-ledger/locale/se/COPYING,
+ old/sql-ledger/locale/se/LANGUAGE,
+ old/sql-ledger/locale/se/admin, old/sql-ledger/locale/se/all,
+ old/sql-ledger/locale/se/am, old/sql-ledger/locale/se/ap,
+ old/sql-ledger/locale/se/ar, old/sql-ledger/locale/se/arap,
+ old/sql-ledger/locale/se/ca, old/sql-ledger/locale/se/cp,
+ old/sql-ledger/locale/se/ct, old/sql-ledger/locale/se/gl,
+ old/sql-ledger/locale/se/ic, old/sql-ledger/locale/se/io,
+ old/sql-ledger/locale/se/ir, old/sql-ledger/locale/se/is,
+ old/sql-ledger/locale/se/login, old/sql-ledger/locale/se/menu,
+ old/sql-ledger/locale/se/oe, old/sql-ledger/locale/se/pe,
+ old/sql-ledger/locale/se/rc, old/sql-ledger/locale/se/rp,
+ old/sql-ledger/locale/tr/COPYING,
+ old/sql-ledger/locale/tr/LANGUAGE,
+ old/sql-ledger/locale/tr/admin, old/sql-ledger/locale/tr/all,
+ old/sql-ledger/locale/tr/am, old/sql-ledger/locale/tr/ap,
+ old/sql-ledger/locale/tr/ar, old/sql-ledger/locale/tr/arap,
+ old/sql-ledger/locale/tr/ca, old/sql-ledger/locale/tr/cp,
+ old/sql-ledger/locale/tr/ct, old/sql-ledger/locale/tr/gl,
+ old/sql-ledger/locale/tr/ic, old/sql-ledger/locale/tr/io,
+ old/sql-ledger/locale/tr/ir, old/sql-ledger/locale/tr/is,
+ old/sql-ledger/locale/tr/login, old/sql-ledger/locale/tr/menu,
+ old/sql-ledger/locale/tr/oe, old/sql-ledger/locale/tr/pe,
+ old/sql-ledger/locale/tr/rc, old/sql-ledger/locale/tr/rp,
+ old/sql-ledger/locale/tw/COPYING,
+ old/sql-ledger/locale/tw/LANGUAGE,
+ old/sql-ledger/locale/tw/admin, old/sql-ledger/locale/tw/all,
+ old/sql-ledger/locale/tw/am, old/sql-ledger/locale/tw/ap,
+ old/sql-ledger/locale/tw/ar, old/sql-ledger/locale/tw/arap,
+ old/sql-ledger/locale/tw/ca, old/sql-ledger/locale/tw/cp,
+ old/sql-ledger/locale/tw/ct, old/sql-ledger/locale/tw/gl,
+ old/sql-ledger/locale/tw/ic, old/sql-ledger/locale/tw/io,
+ old/sql-ledger/locale/tw/ir, old/sql-ledger/locale/tw/is,
+ old/sql-ledger/locale/tw/login, old/sql-ledger/locale/tw/menu,
+ old/sql-ledger/locale/tw/oe, old/sql-ledger/locale/tw/pe,
+ old/sql-ledger/locale/tw/rc, old/sql-ledger/locale/tw/rp,
+ old/sql-ledger/locale/ua/COPYING,
+ old/sql-ledger/locale/ua/LANGUAGE,
+ old/sql-ledger/locale/ua/admin, old/sql-ledger/locale/ua/all,
+ old/sql-ledger/locale/ua/am, old/sql-ledger/locale/ua/ap,
+ old/sql-ledger/locale/ua/ar, old/sql-ledger/locale/ua/arap,
+ old/sql-ledger/locale/ua/ca, old/sql-ledger/locale/ua/cp,
+ old/sql-ledger/locale/ua/ct, old/sql-ledger/locale/ua/gl,
+ old/sql-ledger/locale/ua/ic, old/sql-ledger/locale/ua/io,
+ old/sql-ledger/locale/ua/ir, old/sql-ledger/locale/ua/is,
+ old/sql-ledger/locale/ua/login, old/sql-ledger/locale/ua/menu,
+ old/sql-ledger/locale/ua/oe, old/sql-ledger/locale/ua/pe,
+ old/sql-ledger/locale/ua/rc, old/sql-ledger/locale/ua/rp,
+ old/sql-ledger/locale/ve/COPYING,
+ old/sql-ledger/locale/ve/LANGUAGE,
+ old/sql-ledger/locale/ve/admin, old/sql-ledger/locale/ve/all,
+ old/sql-ledger/locale/ve/am, old/sql-ledger/locale/ve/ap,
+ old/sql-ledger/locale/ve/ar, old/sql-ledger/locale/ve/arap,
+ old/sql-ledger/locale/ve/ca, old/sql-ledger/locale/ve/cp,
+ old/sql-ledger/locale/ve/ct, old/sql-ledger/locale/ve/gl,
+ old/sql-ledger/locale/ve/ic, old/sql-ledger/locale/ve/io,
+ old/sql-ledger/locale/ve/ir, old/sql-ledger/locale/ve/is,
+ old/sql-ledger/locale/ve/login, old/sql-ledger/locale/ve/menu,
+ old/sql-ledger/locale/ve/oe, old/sql-ledger/locale/ve/pe,
+ old/sql-ledger/locale/ve/rc, old/sql-ledger/locale/ve/rp,
+ old/sql-ledger/sql/Austria-chart.sql,
+ old/sql-ledger/sql/Austria-gifi.sql,
+ old/sql-ledger/sql/Brazil_General-chart.sql,
+ old/sql-ledger/sql/Canada-gifi.sql,
+ old/sql-ledger/sql/Canada_General-chart.sql,
+ old/sql-ledger/sql/Czech_Republic-chart.sql,
+ old/sql-ledger/sql/Danish_Default-chart.sql,
+ old/sql-ledger/sql/Default-chart.sql,
+ old/sql-ledger/sql/Dutch_Default-chart.sql,
+ old/sql-ledger/sql/Dutch_Standard-chart.sql,
+ old/sql-ledger/sql/France-chart.sql,
+ old/sql-ledger/sql/German-Sample-chart.sql,
+ old/sql-ledger/sql/German-Sample-gifi.sql,
+ old/sql-ledger/sql/Germany-DATEV-SKR03-chart.sql,
+ old/sql-ledger/sql/Germany-DATEV-SKR03-gifi.sql,
+ old/sql-ledger/sql/Germany-SKR03-chart.sql,
+ old/sql-ledger/sql/Germany-SKR03-gifi.sql,
+ old/sql-ledger/sql/Italy-chart.sql,
+ old/sql-ledger/sql/Oracle-indices.sql,
+ old/sql-ledger/sql/Oracle-tables.sql,
+ old/sql-ledger/sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ old/sql-ledger/sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ old/sql-ledger/sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ old/sql-ledger/sql/Oracle-upgrade-2.0.0-2.0.8.sql,
+ old/sql-ledger/sql/Pg-indices.sql,
+ old/sql-ledger/sql/Pg-tables.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.2.6-1.2.7.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.2.7-1.4.0.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.4.0-1.6.0.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.6.0-1.8.0.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.8.0-1.8.4.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.8.4-1.8.5.sql,
+ old/sql-ledger/sql/Pg-upgrade-1.8.5-2.0.0.sql,
+ old/sql-ledger/sql/Pg-upgrade-2.0.0-2.0.8.sql,
+ old/sql-ledger/sql/Poland-chart.sql,
+ old/sql-ledger/sql/Simplified_Chinese_Default-chart.sql,
+ old/sql-ledger/sql/Spain-chart.sql,
+ old/sql-ledger/sql/Swiss-German-chart.sql,
+ old/sql-ledger/sql/Swiss-German-gifi.sql,
+ old/sql-ledger/sql/Traditional_Chinese_Default-chart.sql,
+ old/sql-ledger/sql/US_General-chart.sql,
+ old/sql-ledger/templates/Brazilian_Portuguese-balance_sheet.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-check.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-income_statement.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-invoice.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-invoice.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-packing_list.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-packing_list.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-purchase_order.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-purchase_order.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-receipt.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-sales_order.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-sales_order.tex,
+ old/sql-ledger/templates/Brazilian_Portuguese-statement.html,
+ old/sql-ledger/templates/Brazilian_Portuguese-statement.tex,
+ old/sql-ledger/templates/Danish-balance_sheet.html,
+ old/sql-ledger/templates/Danish-check.tex,
+ old/sql-ledger/templates/Danish-income_statement.html,
+ old/sql-ledger/templates/Danish-invoice.html,
+ old/sql-ledger/templates/Danish-invoice.tex,
+ old/sql-ledger/templates/Danish-packing_list.html,
+ old/sql-ledger/templates/Danish-packing_list.tex,
+ old/sql-ledger/templates/Danish-purchase_order.html,
+ old/sql-ledger/templates/Danish-purchase_order.tex,
+ old/sql-ledger/templates/Danish-receipt.tex,
+ old/sql-ledger/templates/Danish-sales_order.html,
+ old/sql-ledger/templates/Danish-sales_order.tex,
+ old/sql-ledger/templates/Danish-statement.html,
+ old/sql-ledger/templates/Danish-statement.tex,
+ old/sql-ledger/templates/Default-balance_sheet.html,
+ old/sql-ledger/templates/Default-check.tex,
+ old/sql-ledger/templates/Default-income_statement.html,
+ old/sql-ledger/templates/Default-invoice.html,
+ old/sql-ledger/templates/Default-invoice.tex,
+ old/sql-ledger/templates/Default-packing_list.html,
+ old/sql-ledger/templates/Default-packing_list.tex,
+ old/sql-ledger/templates/Default-purchase_order.html,
+ old/sql-ledger/templates/Default-purchase_order.tex,
+ old/sql-ledger/templates/Default-receipt.tex,
+ old/sql-ledger/templates/Default-sales_order.html,
+ old/sql-ledger/templates/Default-sales_order.tex,
+ old/sql-ledger/templates/Default-statement.html,
+ old/sql-ledger/templates/Default-statement.tex,
+ old/sql-ledger/templates/Dutch-balance_sheet.html,
+ old/sql-ledger/templates/Dutch-check.tex,
+ old/sql-ledger/templates/Dutch-income_statement.html,
+ old/sql-ledger/templates/Dutch-invoice.html,
+ old/sql-ledger/templates/Dutch-invoice.tex,
+ old/sql-ledger/templates/Dutch-packing_list.html,
+ old/sql-ledger/templates/Dutch-packing_list.tex,
+ old/sql-ledger/templates/Dutch-purchase_order.html,
+ old/sql-ledger/templates/Dutch-purchase_order.tex,
+ old/sql-ledger/templates/Dutch-receipt.tex,
+ old/sql-ledger/templates/Dutch-sales_order.html,
+ old/sql-ledger/templates/Dutch-sales_order.tex,
+ old/sql-ledger/templates/Dutch-statement.html,
+ old/sql-ledger/templates/Dutch-statement.tex,
+ old/sql-ledger/templates/Estonian-balance_sheet.html,
+ old/sql-ledger/templates/Estonian-check.tex,
+ old/sql-ledger/templates/Estonian-income_statement.html,
+ old/sql-ledger/templates/Estonian-invoice.html,
+ old/sql-ledger/templates/Estonian-invoice.tex,
+ old/sql-ledger/templates/Estonian-packing_list.html,
+ old/sql-ledger/templates/Estonian-packing_list.tex,
+ old/sql-ledger/templates/Estonian-purchase_order.html,
+ old/sql-ledger/templates/Estonian-purchase_order.tex,
+ old/sql-ledger/templates/Estonian-receipt.tex,
+ old/sql-ledger/templates/Estonian-sales_order.html,
+ old/sql-ledger/templates/Estonian-sales_order.tex,
+ old/sql-ledger/templates/Estonian-statement.html,
+ old/sql-ledger/templates/Estonian-statement.tex,
+ old/sql-ledger/templates/French-balance_sheet.html,
+ old/sql-ledger/templates/French-check.tex,
+ old/sql-ledger/templates/French-income_statement.html,
+ old/sql-ledger/templates/French-invoice.html,
+ old/sql-ledger/templates/French-invoice.tex,
+ old/sql-ledger/templates/French-packing_list.html,
+ old/sql-ledger/templates/French-packing_list.tex,
+ old/sql-ledger/templates/French-purchase_order.html,
+ old/sql-ledger/templates/French-purchase_order.tex,
+ old/sql-ledger/templates/French-receipt.tex,
+ old/sql-ledger/templates/French-sales_order.html,
+ old/sql-ledger/templates/French-sales_order.tex,
+ old/sql-ledger/templates/French-statement.html,
+ old/sql-ledger/templates/French-statement.tex,
+ old/sql-ledger/templates/German-balance_sheet.html,
+ old/sql-ledger/templates/German-check.tex,
+ old/sql-ledger/templates/German-income_statement.html,
+ old/sql-ledger/templates/German-invoice.html,
+ old/sql-ledger/templates/German-invoice.tex,
+ old/sql-ledger/templates/German-packing_list.html,
+ old/sql-ledger/templates/German-packing_list.tex,
+ old/sql-ledger/templates/German-purchase_order.html,
+ old/sql-ledger/templates/German-purchase_order.tex,
+ old/sql-ledger/templates/German-receipt.tex,
+ old/sql-ledger/templates/German-sales_order.html,
+ old/sql-ledger/templates/German-sales_order.tex,
+ old/sql-ledger/templates/German-statement.html,
+ old/sql-ledger/templates/German-statement.tex,
+ old/sql-ledger/templates/Service-balance_sheet.html,
+ old/sql-ledger/templates/Service-check.tex,
+ old/sql-ledger/templates/Service-income_statement.html,
+ old/sql-ledger/templates/Service-invoice.html,
+ old/sql-ledger/templates/Service-invoice.tex,
+ old/sql-ledger/templates/Service-packing_list.html,
+ old/sql-ledger/templates/Service-packing_list.tex,
+ old/sql-ledger/templates/Service-purchase_order.html,
+ old/sql-ledger/templates/Service-purchase_order.tex,
+ old/sql-ledger/templates/Service-receipt.tex,
+ old/sql-ledger/templates/Service-sales_order.html,
+ old/sql-ledger/templates/Service-sales_order.tex,
+ old/sql-ledger/templates/Service-statement.html,
+ old/sql-ledger/templates/Service-statement.tex,
+ old/sql-ledger/templates/Spanish_A4-balance_sheet.html,
+ old/sql-ledger/templates/Spanish_A4-check.tex,
+ old/sql-ledger/templates/Spanish_A4-income_statement.html,
+ old/sql-ledger/templates/Spanish_A4-invoice.html,
+ old/sql-ledger/templates/Spanish_A4-invoice.tex,
+ old/sql-ledger/templates/Spanish_A4-packing_list.html,
+ old/sql-ledger/templates/Spanish_A4-packing_list.tex,
+ old/sql-ledger/templates/Spanish_A4-purchase_order.html,
+ old/sql-ledger/templates/Spanish_A4-purchase_order.tex,
+ old/sql-ledger/templates/Spanish_A4-receipt.tex,
+ old/sql-ledger/templates/Spanish_A4-sales_order.html,
+ old/sql-ledger/templates/Spanish_A4-sales_order.tex,
+ old/sql-ledger/templates/Spanish_A4-statement.html,
+ old/sql-ledger/templates/Spanish_A4-statement.tex,
+ old/sql-ledger/templates/Spanish_Letter-balance_sheet.html,
+ old/sql-ledger/templates/Spanish_Letter-check.tex,
+ old/sql-ledger/templates/Spanish_Letter-income_statement.html,
+ old/sql-ledger/templates/Spanish_Letter-invoice.html,
+ old/sql-ledger/templates/Spanish_Letter-invoice.tex,
+ old/sql-ledger/templates/Spanish_Letter-packing_list.html,
+ old/sql-ledger/templates/Spanish_Letter-packing_list.tex,
+ old/sql-ledger/templates/Spanish_Letter-purchase_order.html,
+ old/sql-ledger/templates/Spanish_Letter-purchase_order.tex,
+ old/sql-ledger/templates/Spanish_Letter-receipt.tex,
+ old/sql-ledger/templates/Spanish_Letter-sales_order.html,
+ old/sql-ledger/templates/Spanish_Letter-sales_order.tex,
+ old/sql-ledger/templates/Spanish_Letter-statement.html,
+ old/sql-ledger/templates/Spanish_Letter-statement.tex,
+ old/sql-ledger/users/members.default: removing files from import
+ mistake
+
+2004-11-16 06:19 ivan
+
+ * htetc/handler.pl: can't set $p without $cgi
+
+2004-11-16 06:16 ivan
+
+ * htetc/handler.pl: correct package for $r
+
+2004-11-16 06:11 ivan
+
+ * htetc/handler.pl: handle RT NoAuth sections
+
+2004-11-15 02:35 ivan
+
+ * sql-ledger/locale/: sv/arap, sv/cp, sv/oe, sv/pe, sv/pos, sv/rc,
+ nb/admin, sv/arapprn, sv/bp, sv/hr, sv/ps, sv/pw, nb/all, nb/am,
+ nb/ap, nb/ar, nb/ca, nb/ct, nb/gl, nb/ic, nb/ir, nb/io, nb/is,
+ nb/login, nb/menu, nb/rp, nb/COPYING, nb/LANGUAGE, nb/arap,
+ nb/oe, nb/arapprn, nb/bp, nb/cp, nb/hr, nb/pe, nb/pos, nb/ps,
+ nb/pw, nb/rc, tw_utf/admin, tw_utf/all, tw_utf/COPYING,
+ tw_utf/am, tw_utf/ap, tw_utf/ar, tw_utf/arap, tw_utf/bp,
+ tw_utf/ca, tw_utf/cp, tw_utf/ct, tw_utf/gl, tw_utf/hr, tw_utf/ic,
+ tw_utf/LANGUAGE, tw_utf/io, tw_utf/ir, tw_utf/is, tw_utf/login,
+ tw_utf/menu, tw_utf/oe, tw_utf/pe, tw_utf/pos, tw_big5/admin,
+ tw_utf/arapprn, tw_utf/ps, tw_utf/pw, tw_utf/rc, tw_utf/rp,
+ tw_big5/all, tw_big5/am, tw_big5/ap, tw_big5/COPYING, tw_big5/ar,
+ tw_big5/arap, tw_big5/bp, tw_big5/ca, tw_big5/cp, tw_big5/ct,
+ tw_big5/gl, tw_big5/hr, tw_big5/ic, tw_big5/io, tw_big5/ir,
+ tw_big5/LANGUAGE, tw_big5/is, tw_big5/login, tw_big5/menu,
+ tw_big5/oe, tw_big5/pe, be_nl/admin, tw_big5/arapprn,
+ tw_big5/pos, tw_big5/ps, tw_big5/pw, tw_big5/rc, tw_big5/rp,
+ tw_big5/temp, be_nl/all, be_nl/am, be_nl/ap, be_nl/ar, be_nl/ca,
+ be_nl/ct, be_nl/gl, be_nl/ic, be_nl/io, be_nl/ir, be_nl/is,
+ be_nl/login, be_nl/menu, be_nl/COPYING, be_nl/LANGUAGE,
+ be_nl/arap, be_nl/oe, be_nl/rp, be_nl/Num2text, be_nl/bp,
+ be_nl/cp, be_nl/pe, be_nl/pos, be_nl/rc, be_nl/arapprn, be_nl/hr,
+ be_nl/ps, be_nl/pw, cn_utf/admin, cn_utf/all, cn_utf/COPYING,
+ cn_utf/am, cn_utf/ap, cn_utf/ar, cn_utf/arap, cn_utf/bp,
+ cn_utf/ca, cn_utf/cp, cn_utf/ct, cn_utf/gl, cn_utf/hr, cn_utf/ic,
+ cn_utf/io, cn_utf/ir, cn_utf/LANGUAGE, cn_utf/is, cn_utf/login,
+ cn_utf/menu, cn_utf/oe, cn_utf/pe, cn_utf/pos, cn_utf/ps,
+ cn_utf/rc, cn_utf/arapprn, cn_utf/pw, cn_utf/rp, gr/COPYING,
+ gr/LANGUAGE, gr/admin, gr/all, gr/am, gr/ap, gr/ar, gr/ca, gr/ct,
+ gr/gl, gr/ic, gr/io, gr/ir, gr/is, gr/login, gr/menu, gr/rp,
+ gr/arap, gr/bp, gr/cp, gr/oe, gr/pe, gr/pos, gr/rc, gr/arapprn,
+ gr/hr, gr/ps, gr/pw: Initial revision
+
+2004-11-15 02:32 ivan
+
+ * sql-ledger/locale/: co/admin, co/all, co/am, co/ap, co/ar, co/ca,
+ co/ct, co/gl, co/ic, co/io, co/ir, co/login, co/menu, co/rp,
+ co/arap, co/cp, co/is, co/oe, co/pe, co/bp, co/pos, co/ps, co/rc,
+ co/arapprn, co/hr, co/pw, dk/bp, dk/pos, dk/ps, dk/hr,
+ dk/arapprn, dk/pw, br/bp, br/arapprn, br/hr, br/pos, br/ps,
+ br/pw, it/arapprn, it/bp, it/hr, it/pos, it/ps, it/pw, ct/bp,
+ ct/pos, ct/ps, ct/arapprn, ct/hr, ct/pw, ee/Num2text, ee/bp,
+ ee/pos, ee/arapprn, ee/hr, ee/ps, ee/pw, nl/bp, nl/pos,
+ nl/arapprn, nl/hr, nl/ps, nl/pw, tr/bp, tr/arapprn, tr/hr,
+ tr/pos, tr/ps, tr/pw, ve/bp, ve/hr, ve/pos, ve/ps, ve/pw,
+ ve/arapprn, pa/bp, pa/hr, pa/pos, pa/ps, pa/pw, pa/arapprn,
+ cz/bp, cz/pos, cz/arapprn, cz/hr, cz/ps, cz/pw, pt/bp, pt/pos,
+ pt/ps, ec/admin, pt/arapprn, pt/hr, pt/pw, ec/all, ec/am, ec/ap,
+ ec/ar, ec/arap, ec/COPYING, ec/bp, ec/ca, ec/cp, ec/ct, ec/gl,
+ ec/hr, ec/ic, ec/io, ec/ir, ec/LANGUAGE, ec/Num2text, ec/is,
+ ec/login, ec/menu, ec/oe, ec/pe, ec/pos, ec/ps, ec/rc,
+ ec/arapprn, ec/pw, ec/rp, pl/arapprn, pl/bp, pl/hr, pl/pos,
+ pl/ps, pl/pw, mx/bp, mx/pos, mx/arapprn, mx/hr, mx/ps, mx/pw,
+ fi/bp, fi/pos, fi/arapprn, fi/hr, fi/ps, fi/pw, ru/bp, ru/pos,
+ ru/arapprn, ru/hr, ru/ps, ru/pw, ua/bp, ua/arapprn, ua/hr,
+ ua/pos, ua/ps, ua/pw, se/arapprn, se/bp, se/hr, se/pos, se/ps,
+ se/pw, hu/Num2text, hu/bp, hu/hr, hu/pos, hu/ps, hu/pw,
+ hu/arapprn, lt/arapprn, lt/bp, lt/hr, lt/pos, lt/ps, lt/pw,
+ is/bp, es_iso/login, is/arapprn, is/hr, is/pos, is/ps, is/pw,
+ es_iso/admin, es_iso/all, es_iso/ar, es_iso/ct, es_iso/gl,
+ es_iso/ic, es_iso/ir, es_iso/is, es_iso/rp, es_iso/am, es_iso/ap,
+ es_iso/ca, es_iso/menu, es_iso/COPYING, es_iso/LANGUAGE,
+ es_iso/Num2text, es_iso/arap, es_iso/io, es_iso/oe, es_iso/pe,
+ es_iso/bp, es_iso/cp, es_iso/pos, es_iso/rc, es_iso/arapprn,
+ es_iso/hr, es_iso/ps, es_iso/pw, lv/COPYING, lv/LANGUAGE,
+ lv/admin, lv/all, lv/am, lv/ap, lv/ar, lv/ca, lv/ct, lv/gl,
+ lv/ic, lv/io, lv/ir, lv/login, lv/menu, lv/rp, lv/arap, lv/cp,
+ lv/is, lv/oe, lv/pe, lv/bp, lv/pos, lv/ps, lv/rc, es_utf/admin,
+ es_utf/login, lv/arapprn, lv/hr, lv/pw, es_utf/all, es_utf/ar,
+ es_utf/ct, es_utf/gl, es_utf/ic, es_utf/ir, es_utf/is, es_utf/rp,
+ es_utf/LANGUAGE, es_utf/am, es_utf/ap, es_utf/ca, es_utf/io,
+ es_utf/menu, es_utf/COPYING, es_utf/Num2text, es_utf/arap,
+ es_utf/bp, es_utf/cp, es_utf/oe, es_utf/pe, es_utf/pos,
+ es_utf/rc, es_utf/arapprn, es_utf/hr, es_utf/ps, es_utf/pw,
+ eg/COPYING, eg/LANGUAGE, eg/admin, en_GB/arapprn, en_GB/hr,
+ en_GB/pos, en_GB/ps, en_GB/pw, eg/all, eg/am, eg/ap, eg/ar,
+ eg/arap, eg/bp, eg/ca, eg/cp, eg/ct, eg/gl, eg/ic, eg/io, eg/ir,
+ eg/hr, eg/is, eg/login, eg/menu, eg/oe, eg/arapprn, eg/pe,
+ eg/pos, eg/ps, eg/pw, eg/rc, eg/rp, sv/COPYING, sv/LANGUAGE,
+ sv/admin, sv/all, sv/am, sv/ap, sv/ar, sv/ca, sv/ct, sv/gl,
+ sv/ic, sv/io, sv/ir, sv/login, sv/is, sv/menu, sv/rp: Initial
+ revision
+
+2004-11-15 02:29 ivan
+
+ * sql-ledger/: index.html, sql-ledger.gif, bin/mozilla/bp.pl,
+ bin/mozilla/pos.pl, bin/mozilla/ps.pl, bin/mozilla/hr.pl,
+ bin/js/menu.pl, bin/mozilla/arapprn.pl, bin/mozilla/pw.pl,
+ doc/COPYRIGHT, doc/README.DB2, doc/UPGRADE-2.0.8-2.0.9,
+ doc/UPGRADE-2.0.9-2.2.0, doc/UPGRADE-2.2.0-2.2.7,
+ doc/UPGRADE-2.2.7-2.4.0, doc/UPGRADE-2.4.0-2.4.1,
+ doc/UPGRADE-2.4.1-2.4.2, doc/UPGRADE-2.4.2-2.4.3,
+ doc/UPGRADE-2.4.3-2.4.4, sql/Italy-gifi.sql,
+ sql/Czech-Republic-chart.sql,
+ sql/Simplified-Chinese_Default-chart.sql,
+ sql/Traditional-Chinese_Default-chart.sql,
+ sql/Canada-English_General-chart.sql,
+ sql/Pg-upgrade-2.3.0-2.3.1.sql, sql/Swedish-chart.sql,
+ sql/DB2-create.sql, sql/Italy_General-chart.sql,
+ sql/Oracle-upgrade-2.0.8-2.2.0.sql,
+ sql/Pg-upgrade-2.0.8-2.2.0.sql, sql/Pg-upgrade-2.2.0-2.3.0.sql,
+ sql/Hungary-chart.sql, sql/Norwegian_Default-chart.sql,
+ sql/Belgium-chart.sql, sql/Belgium-gifi.sql,
+ sql/Hungary-gifi.sql, sql/Pg-upgrade-2.3.1-2.3.3.sql,
+ sql/Canada-English-gifi.sql, sql/Italy_cc2424-chart.sql,
+ sql/Pg-upgrade-2.3.3-2.3.4.sql, sql/Pg-upgrade-2.3.4-2.3.5.sql,
+ sql/Pg-upgrade-2.3.5-2.3.6.sql, sql/Spain-ISO-chart.sql,
+ sql/Spain-UTF8-chart.sql, sql/Canada-French-gifi.sql,
+ sql/DB2-indices.sql, sql/DB2-remove.sql, sql/DB2-set.sql,
+ sql/DB2-tables.sql, sql/DB2-sql-ledger.order,
+ sql/Latvia-chart.sql, sql/Pg-upgrade-2.3.6-2.3.7.sql,
+ sql/NAICS.sql, sql/Pg-upgrade-2.3.7-2.3.8.sql,
+ sql/Pg-upgrade-2.3.8-2.3.9.sql, sql/Colombia-PUC-chart.sql,
+ sql/Colombia-PUC-gifi.sql, sql/Egypt-chart.sql,
+ sql/Pg-functions.sql, sql/US_Manufacturing-chart.sql,
+ sql/Pg-upgrade-2.3.9-2.4.2.sql, sql/Pg-upgrade-2.4.2-2.4.3.sql,
+ sql/Pg-upgrade-2.4.3-2.4.4.sql,
+ sql/Simplified-Chinese_Default-UTF8-chart.sql,
+ sql/Traditional-Chinese_Default-UTF8-chart.sql,
+ sql/US_Service_Company-chart.sql,
+ templates/Default-pos_invoice.txt,
+ templates/Norwegian-balance_sheet.html,
+ templates/Danish-pos_invoice.txt,
+ templates/Dutch-pos_invoice.txt, templates/Norwegian-check.tex,
+ templates/Norwegian-income_statement.html,
+ templates/Norwegian-invoice.html,
+ templates/Norwegian-invoice.tex,
+ templates/Norwegian-packing_list.html,
+ templates/Norwegian-packing_list.tex,
+ templates/Norwegian-purchase_order.html,
+ templates/Norwegian-purchase_order.tex,
+ templates/Norwegian-receipt.tex,
+ templates/Italian-balance_sheet.html,
+ templates/Italian-check.tex,
+ templates/Italian-income_statement.html,
+ templates/Italian-invoice.html, templates/Italian-invoice.tex,
+ templates/Italian-packing_list.html,
+ templates/Italian-packing_list.tex,
+ templates/Norwegian-sales_order.html,
+ templates/Norwegian-sales_order.tex,
+ templates/Norwegian-statement.html,
+ templates/Norwegian-statement.tex,
+ templates/Default-bin_list.html, templates/Default-bin_list.tex,
+ templates/Hungarian-balance_sheet.html,
+ templates/Italian-purchase_order.html,
+ templates/Italian-purchase_order.tex,
+ templates/Italian-receipt.tex,
+ templates/Italian-sales_order.html,
+ templates/Italian-sales_order.tex,
+ templates/Italian-statement.html,
+ templates/Italian-statement.tex,
+ templates/Default-pick_list.html,
+ templates/Default-pick_list.tex,
+ templates/Default-request_quotation.html,
+ templates/Default-request_quotation.tex,
+ templates/Default-sales_quotation.html,
+ templates/Default-sales_quotation.tex,
+ templates/Hungarian-check.tex,
+ templates/Hungarian-income_statement.html,
+ templates/Hungarian-invoice.html,
+ templates/Hungarian-invoice.tex,
+ templates/Hungarian-packing_list.html,
+ templates/Hungarian-packing_list.tex,
+ templates/Hungarian-pos_invoice.txt,
+ templates/Hungarian-purchase_order.html,
+ templates/Hungarian-purchase_order.tex,
+ templates/Hungarian-receipt.tex,
+ templates/Default-work_order.tex,
+ templates/Hungarian-sales_order.html,
+ templates/Hungarian-sales_order.tex,
+ templates/Hungarian-statement.html,
+ templates/Hungarian-statement.tex, templates/Danish-bin_list.tex,
+ templates/Danish-work_order.html,
+ templates/Danish-work_order.tex,
+ templates/Default-work_order.html,
+ templates/Dutch-work_order.html, templates/Dutch-work_order.tex,
+ templates/Estonian-pos_invoice.txt,
+ templates/Estonian-work_order.html,
+ templates/Estonian-work_order.tex,
+ templates/French-pos_invoice.txt,
+ templates/French-work_order.html,
+ templates/French-work_order.tex,
+ templates/German-work_order.html,
+ templates/German-work_order.tex,
+ templates/Hungarian-work_order.html,
+ templates/Hungarian-work_order.tex,
+ templates/Italian-work_order.html,
+ templates/Italian-work_order.tex,
+ templates/Norwegian-work_order.html,
+ templates/Norwegian-work_order.tex,
+ templates/Service-work_order.html,
+ templates/Service-work_order.tex,
+ templates/Spanish_A4-work_order.html,
+ templates/Brazilian_Portuguese-bin_list.html,
+ templates/Brazilian_Portuguese-bin_list.tex,
+ templates/Danish-pick_list.html,
+ templates/German-pos_invoice.txt,
+ templates/Italian-pos_invoice.txt,
+ templates/Norwegian-pos_invoice.txt,
+ templates/Service-pos_invoice.txt,
+ templates/Spanish_A4-pos_invoice.txt,
+ templates/Spanish_A4-work_order.tex,
+ templates/Spanish_Letter-pos_invoice.txt,
+ templates/Spanish_Letter-work_order.html,
+ templates/Spanish_Letter-work_order.tex,
+ templates/Brazilian_Portuguese-pick_list.html,
+ templates/Brazilian_Portuguese-pick_list.tex,
+ templates/Brazilian_Portuguese-pos_invoice.txt,
+ templates/Brazilian_Portuguese-request_quotation.html,
+ templates/Brazilian_Portuguese-request_quotation.tex,
+ templates/Brazilian_Portuguese-sales_quotation.html,
+ templates/Brazilian_Portuguese-sales_quotation.tex,
+ templates/Brazilian_Portuguese-work_order.html,
+ templates/Brazilian_Portuguese-work_order.tex,
+ templates/Danish-bin_list.html, templates/Danish-pick_list.tex,
+ templates/Danish-request_quotation.html,
+ templates/Danish-request_quotation.tex,
+ templates/Danish-sales_quotation.html,
+ templates/Danish-sales_quotation.tex,
+ templates/Dutch-bin_list.html, templates/Dutch-bin_list.tex,
+ templates/Dutch-pick_list.html, templates/Dutch-pick_list.tex,
+ templates/Dutch-request_quotation.html,
+ templates/Dutch-request_quotation.tex,
+ templates/Dutch-sales_quotation.html,
+ templates/Dutch-sales_quotation.tex,
+ templates/Estonian-bin_list.html,
+ templates/Estonian-bin_list.tex,
+ templates/Estonian-pick_list.html,
+ templates/Estonian-pick_list.tex,
+ templates/Estonian-request_quotation.html,
+ templates/Estonian-request_quotation.tex,
+ templates/French-bin_list.html, templates/French-bin_list.tex,
+ templates/French-pick_list.html, templates/French-pick_list.tex,
+ templates/French-request_quotation.html,
+ templates/French-request_quotation.tex,
+ templates/French-sales_quotation.html,
+ templates/French-sales_quotation.tex,
+ templates/German-bin_list.html, templates/German-bin_list.tex,
+ templates/German-pick_list.html, templates/German-pick_list.tex,
+ templates/German-request_quotation.html,
+ templates/German-request_quotation.tex,
+ templates/German-sales_quotation.html,
+ templates/German-sales_quotation.tex,
+ templates/Hungarian-bin_list.html,
+ templates/Hungarian-bin_list.tex,
+ templates/Hungarian-pick_list.html,
+ templates/Hungarian-pick_list.tex,
+ templates/Hungarian-request_quotation.html,
+ templates/Hungarian-request_quotation.tex,
+ templates/Hungarian-sales_quotation.html,
+ templates/Hungarian-sales_quotation.tex,
+ templates/Italian-bin_list.html, templates/Italian-bin_list.tex,
+ templates/Italian-pick_list.html,
+ templates/Italian-pick_list.tex,
+ templates/Italian-request_quotation.html,
+ templates/Italian-request_quotation.tex,
+ templates/Italian-sales_quotation.html,
+ templates/Italian-sales_quotation.tex,
+ templates/Norwegian-bin_list.html,
+ templates/Norwegian-bin_list.tex,
+ templates/Norwegian-pick_list.html,
+ templates/Norwegian-pick_list.tex,
+ templates/Norwegian-request_quotation.html,
+ templates/Norwegian-request_quotation.tex,
+ templates/Norwegian-sales_quotation.html,
+ templates/Norwegian-sales_quotation.tex,
+ templates/Service-bin_list.html, templates/Service-bin_list.tex,
+ templates/Service-pick_list.html,
+ templates/Service-pick_list.tex,
+ templates/Service-request_quotation.html,
+ templates/Service-request_quotation.tex,
+ templates/Service-sales_quotation.html,
+ templates/Service-sales_quotation.tex,
+ templates/Spanish_A4-bin_list.html,
+ templates/Spanish_A4-bin_list.tex,
+ templates/Spanish_A4-pick_list.html,
+ templates/Spanish_A4-pick_list.tex,
+ templates/Spanish_A4-request_quotation.html,
+ templates/Spanish_A4-request_quotation.tex,
+ templates/Spanish_A4-sales_quotation.html,
+ templates/Spanish_A4-sales_quotation.tex,
+ templates/Spanish_Letter-bin_list.html,
+ templates/Spanish_Letter-bin_list.tex,
+ templates/Brazilian_Portuguese-ap_transaction.html,
+ templates/Brazilian_Portuguese-ap_transaction.tex,
+ templates/Brazilian_Portuguese-ar_transaction.html,
+ templates/Spanish_Letter-pick_list.html,
+ templates/Spanish_Letter-pick_list.tex,
+ templates/Spanish_Letter-request_quotation.html,
+ templates/Spanish_Letter-request_quotation.tex,
+ templates/Spanish_Letter-sales_quotation.html,
+ templates/Spanish_Letter-sales_quotation.tex,
+ templates/Brazilian_Portuguese-ar_transaction.tex,
+ templates/Danish-ap_transaction.html,
+ templates/Danish-ap_transaction.tex,
+ templates/Danish-ar_transaction.html,
+ templates/Danish-ar_transaction.tex,
+ templates/Default-ap_transaction.html,
+ templates/Default-ap_transaction.tex,
+ templates/Default-ar_transaction.html,
+ templates/Default-ar_transaction.tex,
+ templates/Dutch-ap_transaction.html,
+ templates/Dutch-ap_transaction.tex,
+ templates/Dutch-ar_transaction.html,
+ templates/Dutch-ar_transaction.tex,
+ templates/Estonian-ap_transaction.html,
+ templates/Estonian-ap_transaction.tex,
+ templates/Estonian-ar_transaction.html,
+ templates/Estonian-ar_transaction.tex,
+ templates/French-ap_transaction.html,
+ templates/French-ap_transaction.tex,
+ templates/French-ar_transaction.html,
+ templates/French-ar_transaction.tex,
+ templates/German-ap_transaction.html,
+ templates/German-ap_transaction.tex,
+ templates/German-ar_transaction.html,
+ templates/German-ar_transaction.tex,
+ templates/Hungarian-ap_transaction.html,
+ templates/Hungarian-ap_transaction.tex,
+ templates/Hungarian-ar_transaction.html,
+ templates/Hungarian-ar_transaction.tex,
+ templates/Italian-ap_transaction.html,
+ templates/Italian-ap_transaction.tex,
+ templates/Italian-ar_transaction.html,
+ templates/Italian-ar_transaction.tex,
+ templates/Norwegian-ap_transaction.html,
+ templates/Norwegian-ap_transaction.tex,
+ templates/Norwegian-ar_transaction.html,
+ templates/Norwegian-ar_transaction.tex,
+ templates/Service-ap_transaction.html,
+ templates/Service-ap_transaction.tex,
+ templates/Service-ar_transaction.html,
+ templates/Service-ar_transaction.tex,
+ templates/Spanish_A4-ap_transaction.html,
+ templates/Spanish_A4-ap_transaction.tex,
+ templates/Spanish_A4-ar_transaction.html,
+ templates/Spanish_A4-ar_transaction.tex,
+ templates/Spanish_Letter-ap_transaction.html,
+ templates/Spanish_Letter-ap_transaction.tex,
+ templates/Spanish_Letter-ar_transaction.html,
+ templates/Spanish_Letter-ar_transaction.tex,
+ users/sql-ledger.eps, users/sql-ledger.png, SL/BP.pm, SL/HR.pm,
+ SL/OP.pm, locale/de/bp, locale/de/hr, locale/de/pos,
+ locale/de/ps, locale/de/arapprn, locale/de/pw, locale/fr/bp,
+ locale/fr/pos, locale/fr/hr, locale/fr/ps, locale/co/COPYING,
+ locale/co/LANGUAGE, locale/co/Num2text, locale/fr/Num2text,
+ locale/fr/arapprn, locale/fr/pw: Initial revision
+
+2004-11-15 02:28 ivan
+
+ * sql-ledger/sql-ledger/: VERSION, am.pl, favicon.ico, index.html,
+ login.pl, menu.ini, setup.pl, sql-ledger.conf.default,
+ sql-ledger.gif, sql-ledger.png, SL/AM.pm, SL/AP.pm, SL/AR.pm,
+ SL/BP.pm, SL/CA.pm, SL/CP.pm, SL/CT.pm, SL/Form.pm, SL/GL.pm,
+ SL/HR.pm, SL/IC.pm, SL/IR.pm, SL/IS.pm, SL/Inifile.pm,
+ SL/Mailer.pm, SL/Menu.pm, SL/Num2text.pm, SL/OE.pm, SL/OP.pm,
+ SL/PE.pm, SL/RC.pm, SL/RP.pm, SL/User.pm, bin/js/menu.pl,
+ bin/lynx/menu.pl, bin/mozilla/admin.pl, bin/mozilla/am.pl,
+ bin/mozilla/ap.pl, bin/mozilla/ar.pl, bin/mozilla/arap.pl,
+ bin/mozilla/arapprn.pl, bin/mozilla/bp.pl, bin/mozilla/ca.pl,
+ bin/mozilla/cp.pl, bin/mozilla/ct.pl, bin/mozilla/gl.pl,
+ bin/mozilla/hr.pl, bin/mozilla/ic.pl, bin/mozilla/io.pl,
+ bin/mozilla/ir.pl, bin/mozilla/is.pl, bin/mozilla/login.pl,
+ bin/mozilla/menu.pl, bin/mozilla/oe.pl, bin/mozilla/pe.pl,
+ bin/mozilla/pos.pl, bin/mozilla/ps.pl, bin/mozilla/pw.pl,
+ bin/mozilla/rc.pl, bin/mozilla/rp.pl, css/sql-ledger.css,
+ doc/COPYING, doc/COPYRIGHT, doc/README, doc/README.DB2,
+ doc/UPGRADE-1.6-1.8, doc/UPGRADE-1.8-1.8.3,
+ doc/UPGRADE-1.8.3-1.8.4, doc/UPGRADE-1.8.4-1.8.5,
+ doc/UPGRADE-1.8.5-1.8.7, doc/UPGRADE-1.8.7-2.0.0,
+ doc/UPGRADE-2.0-2.0.8, doc/UPGRADE-2.0.8-2.0.9,
+ doc/UPGRADE-2.0.9-2.2.0, doc/UPGRADE-2.2.0-2.2.7,
+ doc/UPGRADE-2.2.7-2.4.0, doc/UPGRADE-2.4.0-2.4.1,
+ doc/UPGRADE-2.4.1-2.4.2, doc/UPGRADE-2.4.2-2.4.3,
+ doc/UPGRADE-2.4.3-2.4.4, doc/faq.html, locale/be_nl/COPYING,
+ locale/be_nl/LANGUAGE, locale/be_nl/Num2text, locale/be_nl/admin,
+ locale/be_nl/all, locale/be_nl/am, locale/be_nl/ap,
+ locale/be_nl/ar, locale/be_nl/arap, locale/be_nl/arapprn,
+ locale/be_nl/bp, locale/be_nl/ca, locale/be_nl/cp,
+ locale/be_nl/ct, locale/be_nl/gl, locale/be_nl/hr,
+ locale/be_nl/ic, locale/be_nl/io, locale/be_nl/ir,
+ locale/be_nl/is, locale/be_nl/login, locale/be_nl/menu,
+ locale/be_nl/oe, locale/be_nl/pe, locale/be_nl/pos,
+ locale/be_nl/ps, locale/be_nl/pw, locale/be_nl/rc,
+ locale/be_nl/rp, locale/br/COPYING, locale/br/LANGUAGE,
+ locale/br/admin, locale/br/all, locale/br/am, locale/br/ap,
+ locale/br/ar, locale/br/arap, locale/br/arapprn, locale/br/bp,
+ locale/br/ca, locale/br/cp, locale/br/ct, locale/br/gl,
+ locale/br/hr, locale/br/ic, locale/br/io, locale/br/ir,
+ locale/br/is, locale/br/login, locale/br/menu, locale/br/oe,
+ locale/br/pe, locale/br/pos, locale/br/ps, locale/br/pw,
+ locale/br/rc, locale/br/rp, locale/cn_utf/COPYING,
+ locale/cn_utf/LANGUAGE, locale/cn_utf/admin, locale/cn_utf/all,
+ locale/cn_utf/am, locale/cn_utf/ap, locale/cn_utf/ar,
+ locale/cn_utf/arap, locale/cn_utf/arapprn, locale/cn_utf/bp,
+ locale/cn_utf/ca, locale/cn_utf/cp, locale/cn_utf/ct,
+ locale/cn_utf/gl, locale/cn_utf/hr, locale/cn_utf/ic,
+ locale/cn_utf/io, locale/cn_utf/ir, locale/cn_utf/is,
+ locale/cn_utf/login, locale/cn_utf/menu, locale/cn_utf/oe,
+ locale/cn_utf/pe, locale/cn_utf/pos, locale/cn_utf/ps,
+ locale/cn_utf/pw, locale/cn_utf/rc, locale/cn_utf/rp,
+ locale/co/COPYING, locale/co/LANGUAGE, locale/co/Num2text,
+ locale/co/admin, locale/co/all, locale/co/am, locale/co/ap,
+ locale/co/ar, locale/co/arap, locale/co/arapprn, locale/co/bp,
+ locale/co/ca, locale/co/cp, locale/co/ct, locale/co/gl,
+ locale/co/hr, locale/co/ic, locale/co/io, locale/co/ir,
+ locale/co/is, locale/co/login, locale/co/menu, locale/co/oe,
+ locale/co/pe, locale/co/pos, locale/co/ps, locale/co/pw,
+ locale/co/rc, locale/co/rp, locale/ct/COPYING,
+ locale/ct/LANGUAGE, locale/ct/admin, locale/ct/all, locale/ct/am,
+ locale/ct/ap, locale/ct/ar, locale/ct/arap, locale/ct/arapprn,
+ locale/ct/bp, locale/ct/ca, locale/ct/cp, locale/ct/ct,
+ locale/ct/gl, locale/ct/hr, locale/ct/ic, locale/ct/io,
+ locale/ct/ir, locale/ct/is, locale/ct/login, locale/ct/menu,
+ locale/ct/oe, locale/ct/pe, locale/ct/pos, locale/ct/ps,
+ locale/ct/pw, locale/ct/rc, locale/ct/rp, locale/cz/COPYING,
+ locale/cz/LANGUAGE, locale/cz/admin, locale/cz/all, locale/cz/am,
+ locale/cz/ap, locale/cz/ar, locale/cz/arap, locale/cz/arapprn,
+ locale/cz/bp, locale/cz/ca, locale/cz/cp, locale/cz/ct,
+ locale/cz/gl, locale/cz/hr, locale/cz/ic, locale/cz/io,
+ locale/cz/ir, locale/cz/is, locale/cz/login, locale/cz/menu,
+ locale/cz/oe, locale/cz/pe, locale/cz/pos, locale/cz/ps,
+ locale/cz/pw, locale/cz/rc, locale/cz/rp, locale/de/COPYING,
+ locale/de/LANGUAGE, locale/de/Num2text, locale/de/admin,
+ locale/de/am, locale/de/ap, locale/de/ar, locale/de/arap,
+ locale/de/arapprn, locale/de/bp, locale/de/ca, locale/de/cp,
+ locale/de/ct, locale/de/gl, locale/de/hr, locale/de/ic,
+ locale/de/io, locale/de/ir, locale/de/is, locale/de/locales.pl,
+ locale/de/login, locale/de/menu, locale/de/oe, locale/de/pe,
+ locale/de/pos, locale/de/ps, locale/de/pw, locale/de/rc,
+ locale/de/rp, locale/dk/COPYING, locale/dk/LANGUAGE,
+ locale/dk/admin, locale/dk/all, locale/dk/am, locale/dk/ap,
+ locale/dk/ar, locale/dk/arap, locale/dk/arapprn, locale/dk/bp,
+ locale/dk/ca, locale/dk/cp, locale/dk/ct, locale/dk/gl,
+ locale/dk/hr, locale/dk/ic, locale/dk/io, locale/dk/ir,
+ locale/dk/is, locale/dk/login, locale/dk/menu, locale/dk/oe,
+ locale/dk/pe, locale/dk/pos, locale/dk/ps, locale/dk/pw,
+ locale/dk/rc, locale/dk/rp, locale/ec/COPYING,
+ locale/ec/LANGUAGE, locale/ec/Num2text, locale/ec/admin,
+ locale/ec/all, locale/ec/am, locale/ec/ap, locale/ec/ar,
+ locale/ec/arap, locale/ec/arapprn, locale/ec/bp, locale/ec/ca,
+ locale/ec/cp, locale/ec/ct, locale/ec/gl, locale/ec/hr,
+ locale/ec/ic, locale/ec/io, locale/ec/ir, locale/ec/is,
+ locale/ec/login, locale/ec/menu, locale/ec/oe, locale/ec/pe,
+ locale/ec/pos, locale/ec/ps, locale/ec/pw, locale/ec/rc,
+ locale/ec/rp, locale/ee/COPYING, locale/ee/LANGUAGE,
+ locale/ee/Num2text, locale/ee/admin, locale/ee/all, locale/ee/am,
+ locale/ee/ap, locale/ee/ar, locale/ee/arap, locale/ee/arapprn,
+ locale/ee/bp, locale/ee/ca, locale/ee/cp, locale/ee/ct,
+ locale/ee/gl, locale/ee/hr, locale/ee/ic, locale/ee/io,
+ locale/ee/ir, locale/ee/is, locale/ee/login, locale/ee/menu,
+ locale/ee/oe, locale/ee/pe, locale/ee/pos, locale/ee/ps,
+ locale/ee/pw, locale/ee/rc, locale/ee/rp, locale/eg/COPYING,
+ locale/eg/LANGUAGE, locale/eg/admin, locale/eg/all, locale/eg/am,
+ locale/eg/ap, locale/eg/ar, locale/eg/arap, locale/eg/arapprn,
+ locale/eg/bp, locale/eg/ca, locale/eg/cp, locale/eg/ct,
+ locale/eg/gl, locale/eg/hr, locale/eg/ic, locale/eg/io,
+ locale/eg/ir, locale/eg/is, locale/eg/login, locale/eg/menu,
+ locale/eg/oe, locale/eg/pe, locale/eg/pos, locale/eg/ps,
+ locale/eg/pw, locale/eg/rc, locale/eg/rp, locale/en_GB/COPYING,
+ locale/en_GB/LANGUAGE, locale/en_GB/admin, locale/en_GB/all,
+ locale/en_GB/am, locale/en_GB/ap, locale/en_GB/ar,
+ locale/en_GB/arap, locale/en_GB/arapprn, locale/en_GB/bp,
+ locale/en_GB/ca, locale/en_GB/cp, locale/en_GB/ct,
+ locale/en_GB/gl, locale/en_GB/hr, locale/en_GB/ic,
+ locale/en_GB/io, locale/en_GB/ir, locale/en_GB/is,
+ locale/en_GB/login, locale/en_GB/menu, locale/en_GB/oe,
+ locale/en_GB/pe, locale/en_GB/pos, locale/en_GB/ps,
+ locale/en_GB/pw, locale/en_GB/rc, locale/en_GB/rp,
+ locale/es_iso/COPYING, locale/es_iso/LANGUAGE,
+ locale/es_iso/Num2text, locale/es_iso/admin, locale/es_iso/all,
+ locale/es_iso/am, locale/es_iso/ap, locale/es_iso/ar,
+ locale/es_iso/arap, locale/es_iso/arapprn, locale/es_iso/bp,
+ locale/es_iso/ca, locale/es_iso/cp, locale/es_iso/ct,
+ locale/es_iso/gl, locale/es_iso/hr, locale/es_iso/ic,
+ locale/es_iso/io, locale/es_iso/ir, locale/es_iso/is,
+ locale/es_iso/login, locale/es_iso/menu, locale/es_iso/oe,
+ locale/es_iso/pe, locale/es_iso/pos, locale/es_iso/ps,
+ locale/es_iso/pw, locale/es_iso/rc, locale/es_iso/rp,
+ locale/es_utf/COPYING, locale/es_utf/LANGUAGE,
+ locale/es_utf/Num2text, locale/es_utf/admin, locale/es_utf/all,
+ locale/es_utf/am, locale/es_utf/ap, locale/es_utf/ar,
+ locale/es_utf/arap, locale/es_utf/arapprn, locale/es_utf/bp,
+ locale/es_utf/ca, locale/es_utf/cp, locale/es_utf/ct,
+ locale/es_utf/gl, locale/es_utf/hr, locale/es_utf/ic,
+ locale/es_utf/io, locale/es_utf/ir, locale/es_utf/is,
+ locale/es_utf/login, locale/es_utf/menu, locale/es_utf/oe,
+ locale/es_utf/pe, locale/es_utf/pos, locale/es_utf/ps,
+ locale/es_utf/pw, locale/es_utf/rc, locale/es_utf/rp,
+ locale/fi/COPYING, locale/fi/LANGUAGE, locale/fi/admin,
+ locale/fi/all, locale/fi/am, locale/fi/ap, locale/fi/ar,
+ locale/fi/arap, locale/fi/arapprn, locale/fi/bp, locale/fi/ca,
+ locale/fi/cp, locale/fi/ct, locale/fi/gl, locale/fi/hr,
+ locale/fi/ic, locale/fi/io, locale/fi/ir, locale/fi/is,
+ locale/fi/login, locale/fi/menu, locale/fi/oe, locale/fi/pe,
+ locale/fi/pos, locale/fi/ps, locale/fi/pw, locale/fi/rc,
+ locale/fi/rp, locale/fr/COPYING, locale/fr/LANGUAGE,
+ locale/fr/Num2text, locale/fr/admin, locale/fr/all, locale/fr/am,
+ locale/fr/ap, locale/fr/ar, locale/fr/arap, locale/fr/arapprn,
+ locale/fr/bp, locale/fr/ca, locale/fr/cp, locale/fr/ct,
+ locale/fr/gl, locale/fr/hr, locale/fr/ic, locale/fr/io,
+ locale/fr/ir, locale/fr/is, locale/fr/login, locale/fr/menu,
+ locale/fr/oe, locale/fr/pe, locale/fr/pos, locale/fr/ps,
+ locale/fr/pw, locale/fr/rc, locale/fr/rp, locale/gr/COPYING,
+ locale/gr/LANGUAGE, locale/gr/admin, locale/gr/all, locale/gr/am,
+ locale/gr/ap, locale/gr/ar, locale/gr/arap, locale/gr/arapprn,
+ locale/gr/bp, locale/gr/ca, locale/gr/cp, locale/gr/ct,
+ locale/gr/gl, locale/gr/hr, locale/gr/ic, locale/gr/io,
+ locale/gr/ir, locale/gr/is, locale/gr/login, locale/gr/menu,
+ locale/gr/oe, locale/gr/pe, locale/gr/pos, locale/gr/ps,
+ locale/gr/pw, locale/gr/rc, locale/gr/rp, locale/hu/COPYING,
+ locale/hu/LANGUAGE, locale/hu/Num2text, locale/hu/admin,
+ locale/hu/all, locale/hu/am, locale/hu/ap, locale/hu/ar,
+ locale/hu/arap, locale/hu/arapprn, locale/hu/bp, locale/hu/ca,
+ locale/hu/cp, locale/hu/ct, locale/hu/gl, locale/hu/hr,
+ locale/hu/ic, locale/hu/io, locale/hu/ir, locale/hu/is,
+ locale/hu/login, locale/hu/menu, locale/hu/oe, locale/hu/pe,
+ locale/hu/pos, locale/hu/ps, locale/hu/pw, locale/hu/rc,
+ locale/hu/rp, locale/is/COPYING, locale/is/LANGUAGE,
+ locale/is/admin, locale/is/all, locale/is/am, locale/is/ap,
+ locale/is/ar, locale/is/arap, locale/is/arapprn, locale/is/bp,
+ locale/is/ca, locale/is/cp, locale/is/ct, locale/is/gl,
+ locale/is/hr, locale/is/ic, locale/is/io, locale/is/ir,
+ locale/is/is, locale/is/login, locale/is/menu, locale/is/oe,
+ locale/is/pe, locale/is/pos, locale/is/ps, locale/is/pw,
+ locale/is/rc, locale/is/rp, locale/it/COPYING,
+ locale/it/LANGUAGE, locale/it/Num2text, locale/it/admin,
+ locale/it/all, locale/it/am, locale/it/ap, locale/it/ar,
+ locale/it/arap, locale/it/arapprn, locale/it/bp, locale/it/ca,
+ locale/it/cp, locale/it/ct, locale/it/gl, locale/it/hr,
+ locale/it/ic, locale/it/io, locale/it/ir, locale/it/is,
+ locale/it/login, locale/it/menu, locale/it/oe, locale/it/pe,
+ locale/it/pos, locale/it/ps, locale/it/pw, locale/it/qe,
+ locale/it/rc, locale/it/rp, locale/lt/COPYING,
+ locale/lt/LANGUAGE, locale/lt/admin, locale/lt/all, locale/lt/am,
+ locale/lt/ap, locale/lt/ar, locale/lt/arap, locale/lt/arapprn,
+ locale/lt/bp, locale/lt/ca, locale/lt/cp, locale/lt/ct,
+ locale/lt/gl, locale/lt/hr, locale/lt/ic, locale/lt/io,
+ locale/lt/ir, locale/lt/is, locale/lt/login, locale/lt/menu,
+ locale/lt/oe, locale/lt/pe, locale/lt/pos, locale/lt/ps,
+ locale/lt/pw, locale/lt/rc, locale/lt/rp, locale/lv/COPYING,
+ locale/lv/LANGUAGE, locale/lv/admin, locale/lv/all, locale/lv/am,
+ locale/lv/ap, locale/lv/ar, locale/lv/arap, locale/lv/arapprn,
+ locale/lv/bp, locale/lv/ca, locale/lv/cp, locale/lv/ct,
+ locale/lv/gl, locale/lv/hr, locale/lv/ic, locale/lv/io,
+ locale/lv/ir, locale/lv/is, locale/lv/login, locale/lv/menu,
+ locale/lv/oe, locale/lv/pe, locale/lv/pos, locale/lv/ps,
+ locale/lv/pw, locale/lv/rc, locale/lv/rp, locale/mx/COPYING,
+ locale/mx/LANGUAGE, locale/mx/admin, locale/mx/all, locale/mx/am,
+ locale/mx/ap, locale/mx/ar, locale/mx/arap, locale/mx/arapprn,
+ locale/mx/bp, locale/mx/ca, locale/mx/cp, locale/mx/ct,
+ locale/mx/gl, locale/mx/hr, locale/mx/ic, locale/mx/io,
+ locale/mx/ir, locale/mx/is, locale/mx/login, locale/mx/menu,
+ locale/mx/oe, locale/mx/pe, locale/mx/pos, locale/mx/ps,
+ locale/mx/pw, locale/mx/rc, locale/mx/rp, locale/nb/COPYING,
+ locale/nb/LANGUAGE, locale/nb/admin, locale/nb/all, locale/nb/am,
+ locale/nb/ap, locale/nb/ar, locale/nb/arap, locale/nb/arapprn,
+ locale/nb/bp, locale/nb/ca, locale/nb/cp, locale/nb/ct,
+ locale/nb/gl, locale/nb/hr, locale/nb/ic, locale/nb/io,
+ locale/nb/ir, locale/nb/is, locale/nb/login, locale/nb/menu,
+ locale/nb/oe, locale/nb/pe, locale/nb/pos, locale/nb/ps,
+ locale/nb/pw, locale/nb/rc, locale/nb/rp, locale/nl/COPYING,
+ locale/nl/LANGUAGE, locale/nl/Num2text, locale/nl/admin,
+ locale/nl/all, locale/nl/am, locale/nl/ap, locale/nl/ar,
+ locale/nl/arap, locale/nl/arapprn, locale/nl/bp, locale/nl/ca,
+ locale/nl/cp, locale/nl/ct, locale/nl/gl, locale/nl/hr,
+ locale/nl/ic, locale/nl/io, locale/nl/ir, locale/nl/is,
+ locale/nl/login, locale/nl/menu, locale/nl/oe, locale/nl/pe,
+ locale/nl/pos, locale/nl/ps, locale/nl/pw, locale/nl/rc,
+ locale/nl/rp, locale/pa/COPYING, locale/pa/LANGUAGE,
+ locale/pa/admin, locale/pa/all, locale/pa/am, locale/pa/ap,
+ locale/pa/ar, locale/pa/arap, locale/pa/arapprn, locale/pa/bp,
+ locale/pa/ca, locale/pa/cp, locale/pa/ct, locale/pa/gl,
+ locale/pa/hr, locale/pa/ic, locale/pa/io, locale/pa/ir,
+ locale/pa/is, locale/pa/login, locale/pa/menu, locale/pa/oe,
+ locale/pa/pe, locale/pa/pos, locale/pa/ps, locale/pa/pw,
+ locale/pa/rc, locale/pa/rp, locale/pl/COPYING,
+ locale/pl/LANGUAGE, locale/pl/admin, locale/pl/all, locale/pl/am,
+ locale/pl/ap, locale/pl/ar, locale/pl/arap, locale/pl/arapprn,
+ locale/pl/bp, locale/pl/ca, locale/pl/cp, locale/pl/ct,
+ locale/pl/gl, locale/pl/hr, locale/pl/ic, locale/pl/io,
+ locale/pl/ir, locale/pl/is, locale/pl/login, locale/pl/menu,
+ locale/pl/oe, locale/pl/pe, locale/pl/pos, locale/pl/ps,
+ locale/pl/pw, locale/pl/rc, locale/pl/rp, locale/pt/COPYING,
+ locale/pt/LANGUAGE, locale/pt/admin, locale/pt/all, locale/pt/am,
+ locale/pt/ap, locale/pt/ar, locale/pt/arap, locale/pt/arapprn,
+ locale/pt/bp, locale/pt/ca, locale/pt/cp, locale/pt/ct,
+ locale/pt/gl, locale/pt/hr, locale/pt/ic, locale/pt/io,
+ locale/pt/ir, locale/pt/is, locale/pt/login, locale/pt/menu,
+ locale/pt/oe, locale/pt/pe, locale/pt/pos, locale/pt/ps,
+ locale/pt/pw, locale/pt/rc, locale/pt/rp, locale/ru/COPYING,
+ locale/ru/LANGUAGE, locale/ru/admin, locale/ru/all, locale/ru/am,
+ locale/ru/ap, locale/ru/ar, locale/ru/arap, locale/ru/arapprn,
+ locale/ru/bp, locale/ru/ca, locale/ru/cp, locale/ru/ct,
+ locale/ru/gl, locale/ru/hr, locale/ru/ic, locale/ru/io,
+ locale/ru/ir, locale/ru/is, locale/ru/login, locale/ru/menu,
+ locale/ru/oe, locale/ru/pe, locale/ru/pos, locale/ru/ps,
+ locale/ru/pw, locale/ru/rc, locale/ru/rp, locale/se/COPYING,
+ locale/se/LANGUAGE, locale/se/admin, locale/se/all, locale/se/am,
+ locale/se/ap, locale/se/ar, locale/se/arap, locale/se/arapprn,
+ locale/se/bp, locale/se/ca, locale/se/cp, locale/se/ct,
+ locale/se/gl, locale/se/hr, locale/se/ic, locale/se/io,
+ locale/se/ir, locale/se/is, locale/se/login, locale/se/menu,
+ locale/se/oe, locale/se/pe, locale/se/pos, locale/se/ps,
+ locale/se/pw, locale/se/rc, locale/se/rp, locale/sv/COPYING,
+ locale/sv/LANGUAGE, locale/sv/admin, locale/sv/all, locale/sv/am,
+ locale/sv/ap, locale/sv/ar, locale/sv/arap, locale/sv/arapprn,
+ locale/sv/bp, locale/sv/ca, locale/sv/cp, locale/sv/ct,
+ locale/sv/gl, locale/sv/hr, locale/sv/ic, locale/sv/io,
+ locale/sv/ir, locale/sv/is, locale/sv/login, locale/sv/menu,
+ locale/sv/oe, locale/sv/pe, locale/sv/pos, locale/sv/ps,
+ locale/sv/pw, locale/sv/rc, locale/sv/rp, locale/tr/COPYING,
+ locale/tr/LANGUAGE, locale/tr/admin, locale/tr/all, locale/tr/am,
+ locale/tr/ap, locale/tr/ar, locale/tr/arap, locale/tr/arapprn,
+ locale/tr/bp, locale/tr/ca, locale/tr/cp, locale/tr/ct,
+ locale/tr/gl, locale/tr/hr, locale/tr/ic, locale/tr/io,
+ locale/tr/ir, locale/tr/is, locale/tr/login, locale/tr/menu,
+ locale/tr/oe, locale/tr/pe, locale/tr/pos, locale/tr/ps,
+ locale/tr/pw, locale/tr/rc, locale/tr/rp, locale/tw_big5/COPYING,
+ locale/tw_big5/LANGUAGE, locale/tw_big5/admin,
+ locale/tw_big5/all, locale/tw_big5/am, locale/tw_big5/ap,
+ locale/tw_big5/ar, locale/tw_big5/arap, locale/tw_big5/arapprn,
+ locale/tw_big5/bp, locale/tw_big5/ca, locale/tw_big5/cp,
+ locale/tw_big5/ct, locale/tw_big5/gl, locale/tw_big5/hr,
+ locale/tw_big5/ic, locale/tw_big5/io, locale/tw_big5/ir,
+ locale/tw_big5/is, locale/tw_big5/login, locale/tw_big5/menu,
+ locale/tw_big5/oe, locale/tw_big5/pe, locale/tw_big5/pos,
+ locale/tw_big5/ps, locale/tw_big5/pw, locale/tw_big5/rc,
+ locale/tw_big5/rp, locale/tw_big5/temp, locale/tw_utf/COPYING,
+ locale/tw_utf/LANGUAGE, locale/tw_utf/admin, locale/tw_utf/all,
+ locale/tw_utf/am, locale/tw_utf/ap, locale/tw_utf/ar,
+ locale/tw_utf/arap, locale/tw_utf/arapprn, locale/tw_utf/bp,
+ locale/tw_utf/ca, locale/tw_utf/cp, locale/tw_utf/ct,
+ locale/tw_utf/gl, locale/tw_utf/hr, locale/tw_utf/ic,
+ locale/tw_utf/io, locale/tw_utf/ir, locale/tw_utf/is,
+ locale/tw_utf/login, locale/tw_utf/menu, locale/tw_utf/oe,
+ locale/tw_utf/pe, locale/tw_utf/pos, locale/tw_utf/ps,
+ locale/tw_utf/pw, locale/tw_utf/rc, locale/tw_utf/rp,
+ locale/ua/COPYING, locale/ua/LANGUAGE, locale/ua/admin,
+ locale/ua/all, locale/ua/am, locale/ua/ap, locale/ua/ar,
+ locale/ua/arap, locale/ua/arapprn, locale/ua/bp, locale/ua/ca,
+ locale/ua/cp, locale/ua/ct, locale/ua/gl, locale/ua/hr,
+ locale/ua/ic, locale/ua/io, locale/ua/ir, locale/ua/is,
+ locale/ua/login, locale/ua/menu, locale/ua/oe, locale/ua/pe,
+ locale/ua/pos, locale/ua/ps, locale/ua/pw, locale/ua/rc,
+ locale/ua/rp, locale/ve/COPYING, locale/ve/LANGUAGE,
+ locale/ve/admin, locale/ve/all, locale/ve/am, locale/ve/ap,
+ locale/ve/ar, locale/ve/arap, locale/ve/arapprn, locale/ve/bp,
+ locale/ve/ca, locale/ve/cp, locale/ve/ct, locale/ve/gl,
+ locale/ve/hr, locale/ve/ic, locale/ve/io, locale/ve/ir,
+ locale/ve/is, locale/ve/login, locale/ve/menu, locale/ve/oe,
+ locale/ve/pe, locale/ve/pos, locale/ve/ps, locale/ve/pw,
+ locale/ve/rc, locale/ve/rp, sql/Austria-chart.sql,
+ sql/Austria-gifi.sql, sql/Belgium-chart.sql,
+ sql/Belgium-gifi.sql, sql/Brazil_General-chart.sql,
+ sql/Canada-English-gifi.sql,
+ sql/Canada-English_General-chart.sql, sql/Canada-French-gifi.sql,
+ sql/Colombia-PUC-chart.sql, sql/Colombia-PUC-gifi.sql,
+ sql/Czech-Republic-chart.sql, sql/DB2-create.sql,
+ sql/DB2-indices.sql, sql/DB2-remove.sql, sql/DB2-set.sql,
+ sql/DB2-sql-ledger.order, sql/DB2-tables.sql,
+ sql/Danish_Default-chart.sql, sql/Default-chart.sql,
+ sql/Dutch_Default-chart.sql, sql/Dutch_Standard-chart.sql,
+ sql/Egypt-chart.sql, sql/France-chart.sql,
+ sql/German-Sample-chart.sql, sql/German-Sample-gifi.sql,
+ sql/Germany-DATEV-SKR03-chart.sql,
+ sql/Germany-DATEV-SKR03-gifi.sql, sql/Germany-SKR03-chart.sql,
+ sql/Germany-SKR03-gifi.sql, sql/Hungary-chart.sql,
+ sql/Hungary-gifi.sql, sql/Italy-gifi.sql,
+ sql/Italy_General-chart.sql, sql/Italy_cc2424-chart.sql,
+ sql/Latvia-chart.sql, sql/NAICS.sql,
+ sql/Norwegian_Default-chart.sql, sql/Oracle-indices.sql,
+ sql/Oracle-tables.sql, sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ sql/Oracle-upgrade-2.0.0-2.0.8.sql,
+ sql/Oracle-upgrade-2.0.8-2.2.0.sql, sql/Pg-functions.sql,
+ sql/Pg-indices.sql, sql/Pg-tables.sql,
+ sql/Pg-upgrade-1.2.6-1.2.7.sql, sql/Pg-upgrade-1.2.7-1.4.0.sql,
+ sql/Pg-upgrade-1.4.0-1.6.0.sql, sql/Pg-upgrade-1.6.0-1.8.0.sql,
+ sql/Pg-upgrade-1.8.0-1.8.4.sql, sql/Pg-upgrade-1.8.4-1.8.5.sql,
+ sql/Pg-upgrade-1.8.5-2.0.0.sql, sql/Pg-upgrade-2.0.0-2.0.8.sql,
+ sql/Pg-upgrade-2.0.8-2.2.0.sql, sql/Pg-upgrade-2.2.0-2.3.0.sql,
+ sql/Pg-upgrade-2.3.0-2.3.1.sql, sql/Pg-upgrade-2.3.1-2.3.3.sql,
+ sql/Pg-upgrade-2.3.3-2.3.4.sql, sql/Pg-upgrade-2.3.4-2.3.5.sql,
+ sql/Pg-upgrade-2.3.5-2.3.6.sql, sql/Pg-upgrade-2.3.6-2.3.7.sql,
+ sql/Pg-upgrade-2.3.7-2.3.8.sql, sql/Pg-upgrade-2.3.8-2.3.9.sql,
+ sql/Pg-upgrade-2.3.9-2.4.2.sql, sql/Pg-upgrade-2.4.2-2.4.3.sql,
+ sql/Pg-upgrade-2.4.3-2.4.4.sql, sql/Poland-chart.sql,
+ sql/Simplified-Chinese_Default-UTF8-chart.sql,
+ sql/Simplified-Chinese_Default-chart.sql,
+ sql/Spain-ISO-chart.sql, sql/Spain-UTF8-chart.sql,
+ sql/Swedish-chart.sql, sql/Swiss-German-chart.sql,
+ sql/Swiss-German-gifi.sql,
+ sql/Traditional-Chinese_Default-UTF8-chart.sql,
+ sql/Traditional-Chinese_Default-chart.sql,
+ sql/US_General-chart.sql, sql/US_Manufacturing-chart.sql,
+ sql/US_Service_Company-chart.sql,
+ templates/Brazilian_Portuguese-ap_transaction.html,
+ templates/Brazilian_Portuguese-ap_transaction.tex,
+ templates/Brazilian_Portuguese-ar_transaction.html,
+ templates/Brazilian_Portuguese-ar_transaction.tex,
+ templates/Brazilian_Portuguese-balance_sheet.html,
+ templates/Brazilian_Portuguese-bin_list.html,
+ templates/Brazilian_Portuguese-bin_list.tex,
+ templates/Brazilian_Portuguese-check.tex,
+ templates/Brazilian_Portuguese-income_statement.html,
+ templates/Brazilian_Portuguese-invoice.html,
+ templates/Brazilian_Portuguese-invoice.tex,
+ templates/Brazilian_Portuguese-packing_list.html,
+ templates/Brazilian_Portuguese-packing_list.tex,
+ templates/Brazilian_Portuguese-pick_list.html,
+ templates/Brazilian_Portuguese-pick_list.tex,
+ templates/Brazilian_Portuguese-pos_invoice.txt,
+ templates/Brazilian_Portuguese-purchase_order.html,
+ templates/Brazilian_Portuguese-purchase_order.tex,
+ templates/Brazilian_Portuguese-receipt.tex,
+ templates/Brazilian_Portuguese-request_quotation.html,
+ templates/Brazilian_Portuguese-request_quotation.tex,
+ templates/Brazilian_Portuguese-sales_order.html,
+ templates/Brazilian_Portuguese-sales_order.tex,
+ templates/Brazilian_Portuguese-sales_quotation.html,
+ templates/Brazilian_Portuguese-sales_quotation.tex,
+ templates/Brazilian_Portuguese-statement.html,
+ templates/Brazilian_Portuguese-statement.tex,
+ templates/Brazilian_Portuguese-work_order.html,
+ templates/Brazilian_Portuguese-work_order.tex,
+ templates/Danish-ap_transaction.html,
+ templates/Danish-ap_transaction.tex,
+ templates/Danish-ar_transaction.html,
+ templates/Danish-ar_transaction.tex,
+ templates/Danish-balance_sheet.html,
+ templates/Danish-bin_list.html, templates/Danish-bin_list.tex,
+ templates/Danish-check.tex,
+ templates/Danish-income_statement.html,
+ templates/Danish-invoice.html, templates/Danish-invoice.tex,
+ templates/Danish-packing_list.html,
+ templates/Danish-packing_list.tex,
+ templates/Danish-pick_list.html, templates/Danish-pick_list.tex,
+ templates/Danish-pos_invoice.txt,
+ templates/Danish-purchase_order.html,
+ templates/Danish-purchase_order.tex,
+ templates/Danish-receipt.tex,
+ templates/Danish-request_quotation.html,
+ templates/Danish-request_quotation.tex,
+ templates/Danish-sales_order.html,
+ templates/Danish-sales_order.tex,
+ templates/Danish-sales_quotation.html,
+ templates/Danish-sales_quotation.tex,
+ templates/Danish-statement.html, templates/Danish-statement.tex,
+ templates/Danish-work_order.html,
+ templates/Danish-work_order.tex,
+ templates/Default-ap_transaction.html,
+ templates/Default-ap_transaction.tex,
+ templates/Default-ar_transaction.html,
+ templates/Default-ar_transaction.tex,
+ templates/Default-balance_sheet.html,
+ templates/Default-bin_list.html, templates/Default-bin_list.tex,
+ templates/Default-check.tex,
+ templates/Default-income_statement.html,
+ templates/Default-invoice.html, templates/Default-invoice.tex,
+ templates/Default-packing_list.html,
+ templates/Default-packing_list.tex,
+ templates/Default-pick_list.html,
+ templates/Default-pick_list.tex,
+ templates/Default-pos_invoice.txt,
+ templates/Default-purchase_order.html,
+ templates/Default-purchase_order.tex,
+ templates/Default-receipt.tex,
+ templates/Default-request_quotation.html,
+ templates/Default-request_quotation.tex,
+ templates/Default-sales_order.html,
+ templates/Default-sales_order.tex,
+ templates/Default-sales_quotation.html,
+ templates/Default-sales_quotation.tex,
+ templates/Default-statement.html,
+ templates/Default-statement.tex,
+ templates/Default-work_order.html,
+ templates/Default-work_order.tex,
+ templates/Dutch-ap_transaction.html,
+ templates/Dutch-ap_transaction.tex,
+ templates/Dutch-ar_transaction.html,
+ templates/Dutch-ar_transaction.tex,
+ templates/Dutch-balance_sheet.html,
+ templates/Dutch-bin_list.html, templates/Dutch-bin_list.tex,
+ templates/Dutch-check.tex, templates/Dutch-income_statement.html,
+ templates/Dutch-invoice.html, templates/Dutch-invoice.tex,
+ templates/Dutch-packing_list.html,
+ templates/Dutch-packing_list.tex, templates/Dutch-pick_list.html,
+ templates/Dutch-pick_list.tex, templates/Dutch-pos_invoice.txt,
+ templates/Dutch-purchase_order.html,
+ templates/Dutch-purchase_order.tex, templates/Dutch-receipt.tex,
+ templates/Dutch-request_quotation.html,
+ templates/Dutch-request_quotation.tex,
+ templates/Dutch-sales_order.html,
+ templates/Dutch-sales_order.tex,
+ templates/Dutch-sales_quotation.html,
+ templates/Dutch-sales_quotation.tex,
+ templates/Dutch-statement.html, templates/Dutch-statement.tex,
+ templates/Dutch-work_order.html, templates/Dutch-work_order.tex,
+ templates/Estonian-ap_transaction.html,
+ templates/Estonian-ap_transaction.tex,
+ templates/Estonian-ar_transaction.html,
+ templates/Estonian-ar_transaction.tex,
+ templates/Estonian-balance_sheet.html,
+ templates/Estonian-bin_list.html,
+ templates/Estonian-bin_list.tex, templates/Estonian-check.tex,
+ templates/Estonian-income_statement.html,
+ templates/Estonian-invoice.html, templates/Estonian-invoice.tex,
+ templates/Estonian-packing_list.html,
+ templates/Estonian-packing_list.tex,
+ templates/Estonian-pick_list.html,
+ templates/Estonian-pick_list.tex,
+ templates/Estonian-pos_invoice.txt,
+ templates/Estonian-purchase_order.html,
+ templates/Estonian-purchase_order.tex,
+ templates/Estonian-receipt.tex,
+ templates/Estonian-request_quotation.html,
+ templates/Estonian-request_quotation.tex,
+ templates/Estonian-sales_order.html,
+ templates/Estonian-sales_order.tex,
+ templates/Estonian-statement.html,
+ templates/Estonian-statement.tex,
+ templates/Estonian-work_order.html,
+ templates/Estonian-work_order.tex,
+ templates/French-ap_transaction.html,
+ templates/French-ap_transaction.tex,
+ templates/French-ar_transaction.html,
+ templates/French-ar_transaction.tex,
+ templates/French-balance_sheet.html,
+ templates/French-bin_list.html, templates/French-bin_list.tex,
+ templates/French-check.tex,
+ templates/French-income_statement.html,
+ templates/French-invoice.html, templates/French-invoice.tex,
+ templates/French-packing_list.html,
+ templates/French-packing_list.tex,
+ templates/French-pick_list.html, templates/French-pick_list.tex,
+ templates/French-pos_invoice.txt,
+ templates/French-purchase_order.html,
+ templates/French-purchase_order.tex,
+ templates/French-receipt.tex,
+ templates/French-request_quotation.html,
+ templates/French-request_quotation.tex,
+ templates/French-sales_order.html,
+ templates/French-sales_order.tex,
+ templates/French-sales_quotation.html,
+ templates/French-sales_quotation.tex,
+ templates/French-statement.html, templates/French-statement.tex,
+ templates/French-work_order.html,
+ templates/French-work_order.tex,
+ templates/German-ap_transaction.html,
+ templates/German-ap_transaction.tex,
+ templates/German-ar_transaction.html,
+ templates/German-ar_transaction.tex,
+ templates/German-balance_sheet.html,
+ templates/German-bin_list.html, templates/German-bin_list.tex,
+ templates/German-check.tex,
+ templates/German-income_statement.html,
+ templates/German-invoice.html, templates/German-invoice.tex,
+ templates/German-packing_list.html,
+ templates/German-packing_list.tex,
+ templates/German-pick_list.html, templates/German-pick_list.tex,
+ templates/German-pos_invoice.txt,
+ templates/German-purchase_order.html,
+ templates/German-purchase_order.tex,
+ templates/German-receipt.tex,
+ templates/German-request_quotation.html,
+ templates/German-request_quotation.tex,
+ templates/German-sales_order.html,
+ templates/German-sales_order.tex,
+ templates/German-sales_quotation.html,
+ templates/German-sales_quotation.tex,
+ templates/German-statement.html, templates/German-statement.tex,
+ templates/German-work_order.html,
+ templates/German-work_order.tex,
+ templates/Hungarian-ap_transaction.html,
+ templates/Hungarian-ap_transaction.tex,
+ templates/Hungarian-ar_transaction.html,
+ templates/Hungarian-ar_transaction.tex,
+ templates/Hungarian-balance_sheet.html,
+ templates/Hungarian-bin_list.html,
+ templates/Hungarian-bin_list.tex, templates/Hungarian-check.tex,
+ templates/Hungarian-income_statement.html,
+ templates/Hungarian-invoice.html,
+ templates/Hungarian-invoice.tex,
+ templates/Hungarian-packing_list.html,
+ templates/Hungarian-packing_list.tex,
+ templates/Hungarian-pick_list.html,
+ templates/Hungarian-pick_list.tex,
+ templates/Hungarian-pos_invoice.txt,
+ templates/Hungarian-purchase_order.html,
+ templates/Hungarian-purchase_order.tex,
+ templates/Hungarian-receipt.tex,
+ templates/Hungarian-request_quotation.html,
+ templates/Hungarian-request_quotation.tex,
+ templates/Hungarian-sales_order.html,
+ templates/Hungarian-sales_order.tex,
+ templates/Hungarian-sales_quotation.html,
+ templates/Hungarian-sales_quotation.tex,
+ templates/Hungarian-statement.html,
+ templates/Hungarian-statement.tex,
+ templates/Hungarian-work_order.html,
+ templates/Hungarian-work_order.tex,
+ templates/Italian-ap_transaction.html,
+ templates/Italian-ap_transaction.tex,
+ templates/Italian-ar_transaction.html,
+ templates/Italian-ar_transaction.tex,
+ templates/Italian-balance_sheet.html,
+ templates/Italian-bin_list.html, templates/Italian-bin_list.tex,
+ templates/Italian-check.tex,
+ templates/Italian-income_statement.html,
+ templates/Italian-invoice.html, templates/Italian-invoice.tex,
+ templates/Italian-packing_list.html,
+ templates/Italian-packing_list.tex,
+ templates/Italian-pick_list.html,
+ templates/Italian-pick_list.tex,
+ templates/Italian-pos_invoice.txt,
+ templates/Italian-purchase_order.html,
+ templates/Italian-purchase_order.tex,
+ templates/Italian-receipt.tex,
+ templates/Italian-request_quotation.html,
+ templates/Italian-request_quotation.tex,
+ templates/Italian-sales_order.html,
+ templates/Italian-sales_order.tex,
+ templates/Italian-sales_quotation.html,
+ templates/Italian-sales_quotation.tex,
+ templates/Italian-statement.html,
+ templates/Italian-statement.tex,
+ templates/Italian-work_order.html,
+ templates/Italian-work_order.tex,
+ templates/Norwegian-ap_transaction.html,
+ templates/Norwegian-ap_transaction.tex,
+ templates/Norwegian-ar_transaction.html,
+ templates/Norwegian-ar_transaction.tex,
+ templates/Norwegian-balance_sheet.html,
+ templates/Norwegian-bin_list.html,
+ templates/Norwegian-bin_list.tex, templates/Norwegian-check.tex,
+ templates/Norwegian-income_statement.html,
+ templates/Norwegian-invoice.html,
+ templates/Norwegian-invoice.tex,
+ templates/Norwegian-packing_list.html,
+ templates/Norwegian-packing_list.tex,
+ templates/Norwegian-pick_list.html,
+ templates/Norwegian-pick_list.tex,
+ templates/Norwegian-pos_invoice.txt,
+ templates/Norwegian-purchase_order.html,
+ templates/Norwegian-purchase_order.tex,
+ templates/Norwegian-receipt.tex,
+ templates/Norwegian-request_quotation.html,
+ templates/Norwegian-request_quotation.tex,
+ templates/Norwegian-sales_order.html,
+ templates/Norwegian-sales_order.tex,
+ templates/Norwegian-sales_quotation.html,
+ templates/Norwegian-sales_quotation.tex,
+ templates/Norwegian-statement.html,
+ templates/Norwegian-statement.tex,
+ templates/Norwegian-work_order.html,
+ templates/Norwegian-work_order.tex,
+ templates/Service-ap_transaction.html,
+ templates/Service-ap_transaction.tex,
+ templates/Service-ar_transaction.html,
+ templates/Service-ar_transaction.tex,
+ templates/Service-balance_sheet.html,
+ templates/Service-bin_list.html, templates/Service-bin_list.tex,
+ templates/Service-check.tex,
+ templates/Service-income_statement.html,
+ templates/Service-invoice.html, templates/Service-invoice.tex,
+ templates/Service-packing_list.html,
+ templates/Service-packing_list.tex,
+ templates/Service-pick_list.html,
+ templates/Service-pick_list.tex,
+ templates/Service-pos_invoice.txt,
+ templates/Service-purchase_order.html,
+ templates/Service-purchase_order.tex,
+ templates/Service-receipt.tex,
+ templates/Service-request_quotation.html,
+ templates/Service-request_quotation.tex,
+ templates/Service-sales_order.html,
+ templates/Service-sales_order.tex,
+ templates/Service-sales_quotation.html,
+ templates/Service-sales_quotation.tex,
+ templates/Service-statement.html,
+ templates/Service-statement.tex,
+ templates/Service-work_order.html,
+ templates/Service-work_order.tex,
+ templates/Spanish_A4-ap_transaction.html,
+ templates/Spanish_A4-ap_transaction.tex,
+ templates/Spanish_A4-ar_transaction.html,
+ templates/Spanish_A4-ar_transaction.tex,
+ templates/Spanish_A4-balance_sheet.html,
+ templates/Spanish_A4-bin_list.html,
+ templates/Spanish_A4-bin_list.tex,
+ templates/Spanish_A4-check.tex,
+ templates/Spanish_A4-income_statement.html,
+ templates/Spanish_A4-invoice.html,
+ templates/Spanish_A4-invoice.tex,
+ templates/Spanish_A4-packing_list.html,
+ templates/Spanish_A4-packing_list.tex,
+ templates/Spanish_A4-pick_list.html,
+ templates/Spanish_A4-pick_list.tex,
+ templates/Spanish_A4-pos_invoice.txt,
+ templates/Spanish_A4-purchase_order.html,
+ templates/Spanish_A4-purchase_order.tex,
+ templates/Spanish_A4-receipt.tex,
+ templates/Spanish_A4-request_quotation.html,
+ templates/Spanish_A4-request_quotation.tex,
+ templates/Spanish_A4-sales_order.html,
+ templates/Spanish_A4-sales_order.tex,
+ templates/Spanish_A4-sales_quotation.html,
+ templates/Spanish_A4-sales_quotation.tex,
+ templates/Spanish_A4-statement.html,
+ templates/Spanish_A4-statement.tex,
+ templates/Spanish_A4-work_order.html,
+ templates/Spanish_A4-work_order.tex,
+ templates/Spanish_Letter-ap_transaction.html,
+ templates/Spanish_Letter-ap_transaction.tex,
+ templates/Spanish_Letter-ar_transaction.html,
+ templates/Spanish_Letter-ar_transaction.tex,
+ templates/Spanish_Letter-balance_sheet.html,
+ templates/Spanish_Letter-bin_list.html,
+ templates/Spanish_Letter-bin_list.tex,
+ templates/Spanish_Letter-check.tex,
+ templates/Spanish_Letter-income_statement.html,
+ templates/Spanish_Letter-invoice.html,
+ templates/Spanish_Letter-invoice.tex,
+ templates/Spanish_Letter-packing_list.html,
+ templates/Spanish_Letter-packing_list.tex,
+ templates/Spanish_Letter-pick_list.html,
+ templates/Spanish_Letter-pick_list.tex,
+ templates/Spanish_Letter-pos_invoice.txt,
+ templates/Spanish_Letter-purchase_order.html,
+ templates/Spanish_Letter-purchase_order.tex,
+ templates/Spanish_Letter-receipt.tex,
+ templates/Spanish_Letter-request_quotation.html,
+ templates/Spanish_Letter-request_quotation.tex,
+ templates/Spanish_Letter-sales_order.html,
+ templates/Spanish_Letter-sales_order.tex,
+ templates/Spanish_Letter-sales_quotation.html,
+ templates/Spanish_Letter-sales_quotation.tex,
+ templates/Spanish_Letter-statement.html,
+ templates/Spanish_Letter-statement.tex,
+ templates/Spanish_Letter-work_order.html,
+ templates/Spanish_Letter-work_order.tex, users/sql-ledger.eps,
+ users/sql-ledger.png: remove misplaced sql ledger update
+
+2004-11-13 04:50 ivan
+
+ * sql-ledger/old/sql-ledger/: locale/en_GB/ic, locale/en_GB/io,
+ locale/en_GB/ir, locale/en_GB/is, locale/en_GB/login,
+ locale/en_GB/menu, locale/en_GB/oe, locale/en_GB/pe,
+ locale/en_GB/rc, locale/en_GB/rp, locale/es/COPYING,
+ locale/es/LANGUAGE, locale/es/Num2text, locale/es/admin,
+ locale/es/all, locale/es/am, locale/es/ap, locale/es/ar,
+ locale/es/arap, locale/es/ca, locale/es/cp, locale/es/ct,
+ locale/es/gl, locale/es/ic, locale/es/io, locale/es/ir,
+ locale/es/is, locale/es/login, locale/es/menu, locale/es/oe,
+ locale/es/pe, locale/es/rc, locale/es/rp, locale/fi/COPYING,
+ locale/fi/LANGUAGE, locale/fi/admin, locale/fi/all, locale/fi/am,
+ locale/fi/ap, locale/fi/ar, locale/fi/arap, locale/fi/ca,
+ locale/fi/cp, locale/fi/ct, locale/fi/gl, locale/fi/ic,
+ locale/fi/io, locale/fi/ir, locale/fi/is, locale/fi/login,
+ locale/fi/menu, locale/fi/oe, locale/fi/pe, locale/fi/rc,
+ locale/fi/rp, locale/fr/COPYING, locale/fr/LANGUAGE,
+ locale/fr/admin, locale/fr/all, locale/fr/am, locale/fr/ap,
+ locale/fr/ar, locale/fr/arap, locale/fr/ca, locale/fr/cp,
+ locale/fr/ct, locale/fr/gl, locale/fr/ic, locale/fr/io,
+ locale/fr/ir, locale/fr/is, locale/fr/login, locale/fr/menu,
+ locale/fr/oe, locale/fr/pe, locale/fr/rc, locale/fr/rp,
+ locale/hu/COPYING, locale/hu/LANGUAGE, locale/hu/admin,
+ locale/hu/all, locale/hu/am, locale/hu/ap, locale/hu/ar,
+ locale/hu/arap, locale/hu/ca, locale/hu/cp, locale/hu/ct,
+ locale/hu/gl, locale/hu/ic, locale/hu/io, locale/hu/ir,
+ locale/hu/is, locale/hu/login, locale/hu/menu, locale/hu/oe,
+ locale/hu/pe, locale/hu/rc, locale/hu/rp, locale/is/COPYING,
+ locale/is/LANGUAGE, locale/is/admin, locale/is/all, locale/is/am,
+ locale/is/ap, locale/is/ar, locale/is/arap, locale/is/ca,
+ locale/is/cp, locale/is/ct, locale/is/gl, locale/is/ic,
+ locale/is/io, locale/is/ir, locale/is/is, locale/is/login,
+ locale/is/menu, locale/is/oe, locale/is/pe, locale/is/rc,
+ locale/is/rp, locale/it/COPYING, locale/it/LANGUAGE,
+ locale/it/Num2text, locale/it/admin, locale/it/all, locale/it/am,
+ locale/it/ap, locale/it/ar, locale/it/arap, locale/it/ca,
+ locale/it/cp, locale/it/ct, locale/it/gl, locale/it/ic,
+ locale/it/io, locale/it/ir, locale/it/is, locale/it/login,
+ locale/it/menu, locale/it/oe, locale/it/pe, locale/it/qe,
+ locale/it/rc, locale/it/rp, locale/lt/COPYING,
+ locale/lt/LANGUAGE, locale/lt/admin, locale/lt/all, locale/lt/am,
+ locale/lt/ap, locale/lt/ar, locale/lt/arap, locale/lt/ca,
+ locale/lt/cp, locale/lt/ct, locale/lt/gl, locale/lt/ic,
+ locale/lt/io, locale/lt/ir, locale/lt/is, locale/lt/login,
+ locale/lt/menu, locale/lt/oe, locale/lt/pe, locale/lt/rc,
+ locale/lt/rp, locale/mx/COPYING, locale/mx/LANGUAGE,
+ locale/mx/admin, locale/mx/all, locale/mx/am, locale/mx/ap,
+ locale/mx/ar, locale/mx/arap, locale/mx/ca, locale/mx/cp,
+ locale/mx/ct, locale/mx/gl, locale/mx/ic, locale/mx/io,
+ locale/mx/ir, locale/mx/is, locale/mx/login, locale/mx/menu,
+ locale/mx/oe, locale/mx/pe, locale/mx/rc, locale/mx/rp,
+ locale/nl/COPYING, locale/nl/LANGUAGE, locale/nl/Num2text,
+ locale/nl/admin, locale/nl/all, locale/nl/am, locale/nl/ap,
+ locale/nl/ar, locale/nl/arap, locale/nl/ca, locale/nl/cp,
+ locale/nl/ct, locale/nl/gl, locale/nl/ic, locale/nl/io,
+ locale/nl/ir, locale/nl/is, locale/nl/login, locale/nl/menu,
+ locale/nl/oe, locale/nl/pe, locale/nl/rc, locale/nl/rp,
+ locale/no/COPYING, locale/no/LANGUAGE, locale/no/admin,
+ locale/no/all, locale/no/am, locale/no/ap, locale/no/ar,
+ locale/no/arap, locale/no/ca, locale/no/cp, locale/no/ct,
+ locale/no/gl, locale/no/ic, locale/no/io, locale/no/ir,
+ locale/no/is, locale/no/login, locale/no/menu, locale/no/oe,
+ locale/no/pe, locale/no/rc, locale/no/rp, locale/pa/COPYING,
+ locale/pa/LANGUAGE, locale/pa/admin, locale/pa/all, locale/pa/am,
+ locale/pa/ap, locale/pa/ar, locale/pa/arap, locale/pa/ca,
+ locale/pa/cp, locale/pa/ct, locale/pa/gl, locale/pa/ic,
+ locale/pa/io, locale/pa/ir, locale/pa/is, locale/pa/login,
+ locale/pa/menu, locale/pa/oe, locale/pa/pe, locale/pa/rc,
+ locale/pa/rp, locale/pl/COPYING, locale/pl/LANGUAGE,
+ locale/pl/admin, locale/pl/all, locale/pl/am, locale/pl/ap,
+ locale/pl/ar, locale/pl/arap, locale/pl/ca, locale/pl/cp,
+ locale/pl/ct, locale/pl/gl, locale/pl/ic, locale/pl/io,
+ locale/pl/ir, locale/pl/is, locale/pl/login, locale/pl/menu,
+ locale/pl/oe, locale/pl/pe, locale/pl/rc, locale/pl/rp,
+ locale/pt/COPYING, locale/pt/LANGUAGE, locale/pt/admin,
+ locale/pt/all, locale/pt/am, locale/pt/ap, locale/pt/ar,
+ locale/pt/arap, locale/pt/ca, locale/pt/cp, locale/pt/ct,
+ locale/pt/gl, locale/pt/ic, locale/pt/io, locale/pt/ir,
+ locale/pt/is, locale/pt/login, locale/pt/menu, locale/pt/oe,
+ locale/pt/pe, locale/pt/rc, locale/pt/rp, locale/ru/COPYING,
+ locale/ru/LANGUAGE, locale/ru/admin, locale/ru/all, locale/ru/am,
+ locale/ru/ap, locale/ru/ar, locale/ru/arap, locale/ru/ca,
+ locale/ru/cp, locale/ru/ct, locale/ru/gl, locale/ru/ic,
+ locale/ru/io, locale/ru/ir, locale/ru/is, locale/ru/login,
+ locale/ru/menu, locale/ru/oe, locale/ru/pe, locale/ru/rc,
+ locale/ru/rp, locale/se/COPYING, locale/se/LANGUAGE,
+ locale/se/admin, locale/se/all, locale/se/am, locale/se/ap,
+ locale/se/ar, locale/se/arap, locale/se/ca, locale/se/cp,
+ locale/se/ct, locale/se/gl, locale/se/ic, locale/se/io,
+ locale/se/ir, locale/se/is, locale/se/login, locale/se/menu,
+ locale/se/oe, locale/se/pe, locale/se/rc, locale/se/rp,
+ locale/tr/COPYING, locale/tr/LANGUAGE, locale/tr/admin,
+ locale/tr/all, locale/tr/am, locale/tr/ap, locale/tr/ar,
+ locale/tr/arap, locale/tr/ca, locale/tr/cp, locale/tr/ct,
+ locale/tr/gl, locale/tr/ic, locale/tr/io, locale/tr/ir,
+ locale/tr/is, locale/tr/login, locale/tr/menu, locale/tr/oe,
+ locale/tr/pe, locale/tr/rc, locale/tr/rp, locale/tw/COPYING,
+ locale/tw/LANGUAGE, locale/tw/admin, locale/tw/all, locale/tw/am,
+ locale/tw/ap, locale/tw/ar, locale/tw/arap, locale/tw/ca,
+ locale/tw/cp, locale/tw/ct, locale/tw/gl, locale/tw/ic,
+ locale/tw/io, locale/tw/ir, locale/tw/is, locale/tw/login,
+ locale/tw/menu, locale/tw/oe, locale/tw/pe, locale/tw/rc,
+ locale/tw/rp, locale/ua/COPYING, locale/ua/LANGUAGE,
+ locale/ua/admin, locale/ua/all, locale/ua/am, locale/ua/ap,
+ locale/ua/ar, locale/ua/arap, locale/ua/ca, locale/ua/cp,
+ locale/ua/ct, locale/ua/gl, locale/ua/ic, locale/ua/io,
+ locale/ua/ir, locale/ua/is, locale/ua/login, locale/ua/menu,
+ locale/ua/oe, locale/ua/pe, locale/ua/rc, locale/ua/rp,
+ locale/ve/COPYING, locale/ve/LANGUAGE, locale/ve/admin,
+ locale/ve/all, locale/ve/am, locale/ve/ap, locale/ve/ar,
+ locale/ve/arap, locale/ve/ca, locale/ve/cp, locale/ve/ct,
+ locale/ve/gl, locale/ve/ic, locale/ve/io, locale/ve/ir,
+ locale/ve/is, locale/ve/login, locale/ve/menu, locale/ve/oe,
+ locale/ve/pe, locale/ve/rc, locale/ve/rp, sql/Austria-chart.sql,
+ sql/Austria-gifi.sql, sql/Brazil_General-chart.sql,
+ sql/Canada_General-chart.sql, sql/Canada-gifi.sql,
+ sql/Germany-DATEV-SKR03-chart.sql, sql/Czech_Republic-chart.sql,
+ sql/Danish_Default-chart.sql, sql/Default-chart.sql,
+ sql/Dutch_Default-chart.sql, sql/Dutch_Standard-chart.sql,
+ sql/France-chart.sql, sql/German-Sample-chart.sql,
+ sql/German-Sample-gifi.sql, sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ sql/Germany-DATEV-SKR03-gifi.sql, sql/Germany-SKR03-chart.sql,
+ sql/Germany-SKR03-gifi.sql, sql/Italy-chart.sql,
+ sql/Oracle-indices.sql, sql/Oracle-tables.sql,
+ sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ sql/Oracle-upgrade-2.0.0-2.0.8.sql, sql/Pg-indices.sql,
+ sql/Pg-tables.sql, sql/Pg-upgrade-1.2.6-1.2.7.sql,
+ sql/Simplified_Chinese_Default-chart.sql,
+ sql/Pg-upgrade-1.2.7-1.4.0.sql, sql/Pg-upgrade-1.4.0-1.6.0.sql,
+ sql/Pg-upgrade-1.6.0-1.8.0.sql, sql/Pg-upgrade-1.8.0-1.8.4.sql,
+ sql/Pg-upgrade-1.8.4-1.8.5.sql, sql/Pg-upgrade-1.8.5-2.0.0.sql,
+ sql/Pg-upgrade-2.0.0-2.0.8.sql, sql/Poland-chart.sql,
+ sql/Swiss-German-chart.sql, sql/Spain-chart.sql,
+ sql/Swiss-German-gifi.sql,
+ sql/Traditional_Chinese_Default-chart.sql,
+ sql/US_General-chart.sql,
+ templates/Brazilian_Portuguese-balance_sheet.html,
+ templates/Brazilian_Portuguese-check.tex,
+ templates/Brazilian_Portuguese-income_statement.html,
+ templates/Brazilian_Portuguese-invoice.html,
+ templates/Brazilian_Portuguese-packing_list.html,
+ templates/Brazilian_Portuguese-invoice.tex,
+ templates/Brazilian_Portuguese-packing_list.tex,
+ templates/Brazilian_Portuguese-purchase_order.html,
+ templates/Brazilian_Portuguese-purchase_order.tex,
+ templates/Brazilian_Portuguese-receipt.tex,
+ templates/Brazilian_Portuguese-sales_order.html,
+ templates/Danish-check.tex, templates/Danish-invoice.html,
+ templates/Brazilian_Portuguese-sales_order.tex,
+ templates/Brazilian_Portuguese-statement.html,
+ templates/Brazilian_Portuguese-statement.tex,
+ templates/Danish-balance_sheet.html,
+ templates/Danish-income_statement.html,
+ templates/Danish-invoice.tex, templates/Danish-packing_list.html,
+ templates/Danish-packing_list.tex,
+ templates/Danish-purchase_order.html,
+ templates/Default-income_statement.html,
+ templates/Danish-purchase_order.tex,
+ templates/Danish-receipt.tex, templates/Danish-sales_order.html,
+ templates/Danish-sales_order.tex,
+ templates/Danish-statement.html, templates/Danish-statement.tex,
+ templates/Default-balance_sheet.html,
+ templates/Default-check.tex, templates/Default-invoice.html,
+ templates/Default-invoice.tex,
+ templates/Default-packing_list.html,
+ templates/Default-packing_list.tex,
+ templates/Default-purchase_order.html,
+ templates/Default-purchase_order.tex,
+ templates/Default-receipt.tex,
+ templates/Default-sales_order.html,
+ templates/Default-sales_order.tex,
+ templates/Default-statement.html,
+ templates/Default-statement.tex,
+ templates/Dutch-balance_sheet.html, templates/Dutch-check.tex,
+ templates/Dutch-income_statement.html,
+ templates/Estonian-income_statement.html,
+ templates/Dutch-invoice.html, templates/Dutch-invoice.tex,
+ templates/Dutch-packing_list.html,
+ templates/Dutch-packing_list.tex,
+ templates/Dutch-purchase_order.html,
+ templates/Dutch-purchase_order.tex, templates/Dutch-receipt.tex,
+ templates/Dutch-sales_order.html,
+ templates/Dutch-sales_order.tex, templates/Dutch-statement.html,
+ templates/Dutch-statement.tex,
+ templates/Estonian-balance_sheet.html,
+ templates/Estonian-check.tex, templates/Estonian-invoice.html,
+ templates/Estonian-invoice.tex,
+ templates/Estonian-packing_list.html,
+ templates/Estonian-packing_list.tex,
+ templates/Estonian-purchase_order.html,
+ templates/Estonian-purchase_order.tex,
+ templates/Estonian-receipt.tex,
+ templates/Service-income_statement.html,
+ templates/Estonian-sales_order.html,
+ templates/Estonian-sales_order.tex,
+ templates/Estonian-statement.html,
+ templates/Estonian-statement.tex,
+ templates/French-balance_sheet.html, templates/French-check.tex,
+ templates/French-income_statement.html,
+ templates/French-invoice.html, templates/French-invoice.tex,
+ templates/French-packing_list.html,
+ templates/French-packing_list.tex,
+ templates/French-purchase_order.html,
+ templates/French-purchase_order.tex,
+ templates/French-receipt.tex, templates/French-sales_order.html,
+ templates/French-sales_order.tex,
+ templates/French-statement.html, templates/French-statement.tex,
+ templates/German-balance_sheet.html, templates/German-check.tex,
+ templates/German-income_statement.html,
+ templates/German-invoice.html, templates/German-invoice.tex,
+ templates/German-packing_list.html,
+ templates/German-packing_list.tex,
+ templates/German-purchase_order.html,
+ templates/German-purchase_order.tex,
+ templates/German-receipt.tex, templates/German-sales_order.html,
+ templates/German-sales_order.tex,
+ templates/German-statement.html, templates/German-statement.tex,
+ templates/Service-balance_sheet.html,
+ templates/Service-check.tex, templates/Service-invoice.html,
+ templates/Service-invoice.tex,
+ templates/Service-packing_list.html,
+ templates/Service-packing_list.tex,
+ templates/Service-purchase_order.html,
+ templates/Service-purchase_order.tex,
+ templates/Service-receipt.tex,
+ templates/Service-sales_order.html,
+ templates/Spanish_A4-balance_sheet.html,
+ templates/Service-sales_order.tex,
+ templates/Service-statement.html,
+ templates/Service-statement.tex, templates/Spanish_A4-check.tex,
+ templates/Spanish_A4-income_statement.html,
+ templates/Spanish_A4-invoice.html,
+ templates/Spanish_A4-invoice.tex,
+ templates/Spanish_A4-packing_list.html,
+ templates/Spanish_A4-packing_list.tex,
+ templates/Spanish_Letter-balance_sheet.html,
+ templates/Spanish_A4-purchase_order.html,
+ templates/Spanish_A4-purchase_order.tex,
+ templates/Spanish_A4-receipt.tex,
+ templates/Spanish_A4-sales_order.html,
+ templates/Spanish_A4-sales_order.tex,
+ templates/Spanish_A4-statement.html,
+ templates/Spanish_A4-statement.tex,
+ templates/Spanish_Letter-check.tex,
+ templates/Spanish_Letter-invoice.html,
+ templates/Spanish_Letter-income_statement.html,
+ templates/Spanish_Letter-invoice.tex,
+ templates/Spanish_Letter-packing_list.html,
+ templates/Spanish_Letter-packing_list.tex,
+ templates/Spanish_Letter-purchase_order.html,
+ templates/Spanish_Letter-purchase_order.tex,
+ templates/Spanish_Letter-receipt.tex,
+ templates/Spanish_Letter-sales_order.html,
+ templates/Spanish_Letter-sales_order.tex,
+ templates/Spanish_Letter-statement.html,
+ templates/Spanish_Letter-statement.tex, users/members.default:
+ Initial revision
+
+2004-11-13 04:47 ivan
+
+ * sql-ledger/: sql-ledger/locale/ru/arap, sql-ledger/locale/ru/bp,
+ sql-ledger/locale/ru/cp, sql-ledger/locale/ru/oe,
+ sql-ledger/locale/ru/pe, sql-ledger/locale/ru/pos,
+ sql-ledger/locale/ru/rc, sql-ledger/locale/ru/arapprn,
+ sql-ledger/locale/ru/hr, sql-ledger/locale/ru/ps,
+ sql-ledger/locale/ru/pw, sql-ledger/locale/ua/COPYING,
+ sql-ledger/locale/ua/LANGUAGE, sql-ledger/locale/ua/admin,
+ sql-ledger/locale/ua/all, sql-ledger/locale/ua/am,
+ sql-ledger/locale/ua/ap, sql-ledger/locale/ua/ar,
+ sql-ledger/locale/ua/ca, sql-ledger/locale/ua/ct,
+ sql-ledger/locale/ua/gl, sql-ledger/locale/ua/ic,
+ sql-ledger/locale/ua/ir, sql-ledger/locale/ua/io,
+ sql-ledger/locale/ua/login, sql-ledger/locale/ua/menu,
+ sql-ledger/locale/ua/rp, sql-ledger/locale/ua/arap,
+ sql-ledger/locale/ua/bp, sql-ledger/locale/ua/cp,
+ sql-ledger/locale/ua/is, sql-ledger/locale/ua/oe,
+ sql-ledger/locale/ua/pe, sql-ledger/locale/ua/pos,
+ sql-ledger/locale/ua/rc, sql-ledger/locale/ua/arapprn,
+ sql-ledger/locale/ua/hr, sql-ledger/locale/ua/ps,
+ sql-ledger/locale/ua/pw, sql-ledger/locale/se/COPYING,
+ sql-ledger/locale/se/LANGUAGE, sql-ledger/locale/se/all,
+ sql-ledger/locale/se/admin, sql-ledger/locale/se/am,
+ sql-ledger/locale/se/ap, sql-ledger/locale/se/ar,
+ sql-ledger/locale/se/ca, sql-ledger/locale/se/ct,
+ sql-ledger/locale/se/gl, sql-ledger/locale/se/ic,
+ sql-ledger/locale/se/io, sql-ledger/locale/se/ir,
+ sql-ledger/locale/se/login, sql-ledger/locale/se/menu,
+ sql-ledger/locale/se/rp, sql-ledger/locale/se/arap,
+ sql-ledger/locale/se/is, sql-ledger/locale/se/oe,
+ sql-ledger/locale/se/pe, sql-ledger/locale/se/arapprn,
+ sql-ledger/locale/se/bp, sql-ledger/locale/se/cp,
+ sql-ledger/locale/se/hr, sql-ledger/locale/se/pos,
+ sql-ledger/locale/se/ps, sql-ledger/locale/se/pw,
+ sql-ledger/locale/se/rc, sql-ledger/locale/hu/COPYING,
+ sql-ledger/locale/hu/LANGUAGE, sql-ledger/locale/hu/admin,
+ sql-ledger/locale/hu/all, sql-ledger/locale/hu/am,
+ sql-ledger/locale/hu/ap, sql-ledger/locale/hu/ar,
+ sql-ledger/locale/hu/ca, sql-ledger/locale/hu/ct,
+ sql-ledger/locale/hu/gl, sql-ledger/locale/hu/ic,
+ sql-ledger/locale/hu/io, sql-ledger/locale/hu/ir,
+ sql-ledger/locale/hu/is, sql-ledger/locale/hu/login,
+ sql-ledger/locale/hu/menu, sql-ledger/locale/hu/rp,
+ sql-ledger/locale/hu/arap, sql-ledger/locale/hu/cp,
+ sql-ledger/locale/hu/oe, sql-ledger/locale/hu/pe,
+ sql-ledger/locale/hu/rc, sql-ledger/locale/hu/Num2text,
+ sql-ledger/locale/hu/arapprn, sql-ledger/locale/hu/bp,
+ sql-ledger/locale/hu/hr, sql-ledger/locale/hu/pos,
+ sql-ledger/locale/hu/ps, sql-ledger/locale/hu/pw,
+ sql-ledger/locale/lt/COPYING, sql-ledger/locale/lt/LANGUAGE,
+ sql-ledger/locale/lt/admin, sql-ledger/locale/lt/all,
+ sql-ledger/locale/lt/am, sql-ledger/locale/lt/ap,
+ sql-ledger/locale/lt/ar, sql-ledger/locale/lt/ca,
+ sql-ledger/locale/lt/ct, sql-ledger/locale/lt/gl,
+ sql-ledger/locale/lt/ic, sql-ledger/locale/lt/ir,
+ sql-ledger/locale/lt/io, sql-ledger/locale/lt/is,
+ sql-ledger/locale/lt/login, sql-ledger/locale/lt/menu,
+ sql-ledger/locale/lt/rp, sql-ledger/locale/lt/arap,
+ sql-ledger/locale/lt/cp, sql-ledger/locale/lt/oe,
+ sql-ledger/locale/lt/pe, sql-ledger/locale/lt/rc,
+ sql-ledger/locale/is/COPYING, sql-ledger/locale/is/LANGUAGE,
+ sql-ledger/locale/lt/arapprn, sql-ledger/locale/lt/bp,
+ sql-ledger/locale/lt/hr, sql-ledger/locale/lt/pos,
+ sql-ledger/locale/lt/ps, sql-ledger/locale/lt/pw,
+ sql-ledger/locale/is/all, sql-ledger/locale/is/admin,
+ sql-ledger/locale/is/am, sql-ledger/locale/is/ap,
+ sql-ledger/locale/is/ar, sql-ledger/locale/is/ca,
+ sql-ledger/locale/is/ct, sql-ledger/locale/is/gl,
+ sql-ledger/locale/is/ic, sql-ledger/locale/is/io,
+ sql-ledger/locale/is/ir, sql-ledger/locale/is/login,
+ sql-ledger/locale/is/menu, sql-ledger/locale/is/rp,
+ sql-ledger/locale/is/arap, sql-ledger/locale/is/cp,
+ sql-ledger/locale/is/is, sql-ledger/locale/is/oe,
+ sql-ledger/locale/is/pe, sql-ledger/locale/is/bp,
+ sql-ledger/locale/is/pos, sql-ledger/locale/is/rc,
+ sql-ledger/locale/es_iso/admin, sql-ledger/locale/es_iso/login,
+ sql-ledger/locale/is/arapprn, sql-ledger/locale/is/hr,
+ sql-ledger/locale/is/ps, sql-ledger/locale/is/pw,
+ sql-ledger/locale/es_iso/all, sql-ledger/locale/es_iso/ar,
+ sql-ledger/locale/es_iso/ct, sql-ledger/locale/es_iso/gl,
+ sql-ledger/locale/es_iso/ic, sql-ledger/locale/es_iso/ir,
+ sql-ledger/locale/es_iso/ap, sql-ledger/locale/es_iso/ca,
+ sql-ledger/locale/es_iso/is, sql-ledger/locale/es_iso/menu,
+ sql-ledger/locale/es_iso/rp, sql-ledger/locale/es_iso/LANGUAGE,
+ sql-ledger/locale/es_iso/am, sql-ledger/locale/es_iso/io,
+ sql-ledger/locale/es_iso/COPYING,
+ sql-ledger/locale/es_iso/Num2text, sql-ledger/locale/es_iso/arap,
+ sql-ledger/locale/es_iso/bp, sql-ledger/locale/es_iso/cp,
+ sql-ledger/locale/es_iso/oe, sql-ledger/locale/es_iso/pe,
+ sql-ledger/locale/es_iso/pos, sql-ledger/locale/es_iso/rc,
+ sql-ledger/locale/es_iso/arapprn, sql-ledger/locale/es_iso/hr,
+ sql-ledger/locale/es_iso/ps, sql-ledger/locale/es_iso/pw,
+ sql-ledger/locale/lv/COPYING, sql-ledger/locale/lv/LANGUAGE,
+ sql-ledger/locale/lv/admin, sql-ledger/locale/lv/all,
+ sql-ledger/locale/lv/am, sql-ledger/locale/lv/ap,
+ sql-ledger/locale/lv/ar, sql-ledger/locale/lv/ca,
+ sql-ledger/locale/lv/ct, sql-ledger/locale/lv/gl,
+ sql-ledger/locale/lv/ic, sql-ledger/locale/lv/io,
+ sql-ledger/locale/lv/ir, sql-ledger/locale/lv/login,
+ sql-ledger/locale/lv/menu, sql-ledger/locale/lv/is,
+ sql-ledger/locale/lv/rp, sql-ledger/locale/lv/arap,
+ sql-ledger/locale/lv/bp, sql-ledger/locale/lv/cp,
+ sql-ledger/locale/lv/oe, sql-ledger/locale/lv/pe,
+ sql-ledger/locale/lv/pos, sql-ledger/locale/lv/rc,
+ sql-ledger/locale/es_utf/admin, sql-ledger/locale/es_utf/login,
+ sql-ledger/locale/lv/arapprn, sql-ledger/locale/lv/hr,
+ sql-ledger/locale/lv/ps, sql-ledger/locale/lv/pw,
+ sql-ledger/locale/es_utf/all, sql-ledger/locale/es_utf/ar,
+ sql-ledger/locale/es_utf/ct, sql-ledger/locale/es_utf/gl,
+ sql-ledger/locale/es_utf/ic, sql-ledger/locale/es_utf/ap,
+ sql-ledger/locale/es_utf/ir, sql-ledger/locale/es_utf/is,
+ sql-ledger/locale/es_utf/menu, sql-ledger/locale/es_utf/rp,
+ sql-ledger/locale/es_utf/LANGUAGE, sql-ledger/locale/es_utf/am,
+ sql-ledger/locale/es_utf/ca, sql-ledger/locale/es_utf/io,
+ sql-ledger/locale/es_utf/oe, sql-ledger/locale/es_utf/COPYING,
+ sql-ledger/locale/es_utf/Num2text, sql-ledger/locale/es_utf/arap,
+ sql-ledger/locale/es_utf/bp, sql-ledger/locale/es_utf/cp,
+ sql-ledger/locale/es_utf/pe, sql-ledger/locale/es_utf/pos,
+ sql-ledger/locale/es_utf/rc, sql-ledger/locale/en_GB/admin,
+ sql-ledger/locale/en_GB/am, sql-ledger/locale/es_utf/arapprn,
+ sql-ledger/locale/es_utf/hr, sql-ledger/locale/es_utf/ps,
+ sql-ledger/locale/es_utf/pw, sql-ledger/locale/en_GB/ap,
+ sql-ledger/locale/en_GB/ar, sql-ledger/locale/en_GB/ca,
+ sql-ledger/locale/en_GB/ct, sql-ledger/locale/en_GB/gl,
+ sql-ledger/locale/en_GB/ic, sql-ledger/locale/en_GB/io,
+ sql-ledger/locale/en_GB/ir, sql-ledger/locale/en_GB/is,
+ sql-ledger/locale/en_GB/login, sql-ledger/locale/en_GB/menu,
+ sql-ledger/locale/en_GB/rp, sql-ledger/locale/en_GB/COPYING,
+ sql-ledger/locale/en_GB/LANGUAGE, sql-ledger/locale/en_GB/arap,
+ sql-ledger/locale/en_GB/bp, sql-ledger/locale/en_GB/cp,
+ sql-ledger/locale/en_GB/oe, sql-ledger/locale/en_GB/pe,
+ sql-ledger/locale/en_GB/rc, sql-ledger/locale/eg/COPYING,
+ sql-ledger/locale/eg/LANGUAGE, sql-ledger/locale/en_GB/all,
+ sql-ledger/locale/en_GB/arapprn, sql-ledger/locale/en_GB/hr,
+ sql-ledger/locale/en_GB/pos, sql-ledger/locale/en_GB/ps,
+ sql-ledger/locale/en_GB/pw, sql-ledger/locale/eg/admin,
+ sql-ledger/locale/eg/all, sql-ledger/locale/eg/am,
+ sql-ledger/locale/eg/ap, sql-ledger/locale/eg/ar,
+ sql-ledger/locale/eg/arap, sql-ledger/locale/eg/bp,
+ sql-ledger/locale/eg/ca, sql-ledger/locale/eg/cp,
+ sql-ledger/locale/eg/ct, sql-ledger/locale/eg/gl,
+ sql-ledger/locale/eg/ic, sql-ledger/locale/eg/io,
+ sql-ledger/locale/eg/ir, sql-ledger/locale/eg/is,
+ sql-ledger/locale/eg/login, sql-ledger/locale/eg/menu,
+ sql-ledger/locale/eg/hr, sql-ledger/locale/eg/oe,
+ sql-ledger/locale/eg/arapprn, sql-ledger/locale/eg/pe,
+ sql-ledger/locale/eg/pos, sql-ledger/locale/eg/ps,
+ sql-ledger/locale/eg/pw, sql-ledger/locale/eg/rc,
+ sql-ledger/locale/eg/rp, sql-ledger/locale/sv/COPYING,
+ sql-ledger/locale/sv/LANGUAGE, sql-ledger/locale/sv/admin,
+ sql-ledger/locale/sv/all, sql-ledger/locale/sv/am,
+ sql-ledger/locale/sv/ap, sql-ledger/locale/sv/ar,
+ sql-ledger/locale/sv/ca, sql-ledger/locale/sv/ct,
+ sql-ledger/locale/sv/gl, sql-ledger/locale/sv/ic,
+ sql-ledger/locale/sv/io, sql-ledger/locale/sv/ir,
+ sql-ledger/locale/sv/login, sql-ledger/locale/sv/menu,
+ sql-ledger/locale/sv/is, sql-ledger/locale/sv/oe,
+ sql-ledger/locale/sv/rp, sql-ledger/locale/sv/arap,
+ sql-ledger/locale/sv/cp, sql-ledger/locale/sv/pe,
+ sql-ledger/locale/sv/pos, sql-ledger/locale/sv/rc,
+ sql-ledger/locale/nb/admin, sql-ledger/locale/sv/arapprn,
+ sql-ledger/locale/sv/bp, sql-ledger/locale/sv/hr,
+ sql-ledger/locale/sv/ps, sql-ledger/locale/sv/pw,
+ sql-ledger/locale/nb/all, sql-ledger/locale/nb/am,
+ sql-ledger/locale/nb/ap, sql-ledger/locale/nb/ar,
+ sql-ledger/locale/nb/ca, sql-ledger/locale/nb/ct,
+ sql-ledger/locale/nb/gl, sql-ledger/locale/nb/ic,
+ sql-ledger/locale/nb/ir, sql-ledger/locale/nb/COPYING,
+ sql-ledger/locale/nb/io, sql-ledger/locale/nb/is,
+ sql-ledger/locale/nb/login, sql-ledger/locale/nb/menu,
+ sql-ledger/locale/nb/rp, sql-ledger/locale/nb/LANGUAGE,
+ sql-ledger/locale/nb/arap, sql-ledger/locale/nb/bp,
+ sql-ledger/locale/nb/cp, sql-ledger/locale/nb/oe,
+ sql-ledger/locale/nb/pe, sql-ledger/locale/nb/rc,
+ sql-ledger/locale/nb/arapprn, sql-ledger/locale/nb/hr,
+ sql-ledger/locale/nb/pos, sql-ledger/locale/nb/ps,
+ sql-ledger/locale/nb/pw, sql-ledger/locale/tw_utf/admin,
+ sql-ledger/locale/tw_utf/all, sql-ledger/locale/tw_utf/COPYING,
+ sql-ledger/locale/tw_utf/am, sql-ledger/locale/tw_utf/ap,
+ sql-ledger/locale/tw_utf/ar, sql-ledger/locale/tw_utf/arap,
+ sql-ledger/locale/tw_utf/bp, sql-ledger/locale/tw_utf/ca,
+ sql-ledger/locale/tw_utf/cp, sql-ledger/locale/tw_utf/ct,
+ sql-ledger/locale/tw_utf/gl, sql-ledger/locale/tw_utf/hr,
+ sql-ledger/locale/tw_utf/ic, sql-ledger/locale/tw_utf/io,
+ sql-ledger/locale/tw_utf/ir, sql-ledger/locale/tw_utf/LANGUAGE,
+ sql-ledger/locale/tw_utf/is, sql-ledger/locale/tw_utf/login,
+ sql-ledger/locale/tw_utf/menu, sql-ledger/locale/tw_utf/oe,
+ sql-ledger/locale/tw_utf/pe, sql-ledger/locale/tw_utf/pos,
+ sql-ledger/locale/tw_utf/ps, sql-ledger/locale/tw_utf/rc,
+ sql-ledger/locale/tw_utf/rp, sql-ledger/locale/tw_big5/admin,
+ sql-ledger/locale/tw_utf/arapprn, sql-ledger/locale/tw_utf/pw,
+ sql-ledger/locale/tw_big5/all, sql-ledger/locale/tw_big5/am,
+ sql-ledger/locale/tw_big5/COPYING, sql-ledger/locale/tw_big5/ap,
+ sql-ledger/locale/tw_big5/ar, sql-ledger/locale/tw_big5/arap,
+ sql-ledger/locale/tw_big5/bp, sql-ledger/locale/tw_big5/ca,
+ sql-ledger/locale/tw_big5/cp, sql-ledger/locale/tw_big5/ct,
+ sql-ledger/locale/tw_big5/gl, sql-ledger/locale/tw_big5/hr,
+ sql-ledger/locale/tw_big5/ic, sql-ledger/locale/tw_big5/io,
+ sql-ledger/locale/tw_big5/LANGUAGE, sql-ledger/locale/tw_big5/ir,
+ sql-ledger/locale/tw_big5/is, sql-ledger/locale/tw_big5/login,
+ sql-ledger/locale/tw_big5/menu, sql-ledger/locale/tw_big5/oe,
+ sql-ledger/locale/tw_big5/pe, sql-ledger/locale/tw_big5/pos,
+ sql-ledger/locale/tw_big5/arapprn, sql-ledger/locale/tw_big5/ps,
+ sql-ledger/locale/tw_big5/pw, sql-ledger/locale/tw_big5/rc,
+ sql-ledger/locale/tw_big5/rp, sql-ledger/locale/tw_big5/temp,
+ sql-ledger/locale/be_nl/admin, sql-ledger/locale/be_nl/all,
+ sql-ledger/locale/be_nl/am, sql-ledger/locale/be_nl/ap,
+ sql-ledger/locale/be_nl/ar, sql-ledger/locale/be_nl/ca,
+ sql-ledger/locale/be_nl/ct, sql-ledger/locale/be_nl/gl,
+ sql-ledger/locale/be_nl/ic, sql-ledger/locale/be_nl/ir,
+ sql-ledger/locale/be_nl/is, sql-ledger/locale/be_nl/login,
+ sql-ledger/locale/be_nl/menu, sql-ledger/locale/be_nl/io,
+ sql-ledger/locale/be_nl/rp, sql-ledger/locale/be_nl/COPYING,
+ sql-ledger/locale/be_nl/LANGUAGE,
+ sql-ledger/locale/be_nl/Num2text, sql-ledger/locale/be_nl/arap,
+ sql-ledger/locale/be_nl/bp, sql-ledger/locale/be_nl/cp,
+ sql-ledger/locale/be_nl/oe, sql-ledger/locale/be_nl/pe,
+ sql-ledger/locale/be_nl/pos, sql-ledger/locale/be_nl/rc,
+ sql-ledger/locale/be_nl/hr, sql-ledger/locale/be_nl/ps,
+ sql-ledger/locale/be_nl/arapprn, sql-ledger/locale/be_nl/pw,
+ sql-ledger/locale/cn_utf/admin, sql-ledger/locale/cn_utf/all,
+ sql-ledger/locale/cn_utf/am, sql-ledger/locale/cn_utf/ap,
+ sql-ledger/locale/cn_utf/ar, sql-ledger/locale/cn_utf/COPYING,
+ sql-ledger/locale/cn_utf/arap, sql-ledger/locale/cn_utf/bp,
+ sql-ledger/locale/cn_utf/ca, sql-ledger/locale/cn_utf/cp,
+ sql-ledger/locale/cn_utf/ct, sql-ledger/locale/cn_utf/gl,
+ sql-ledger/locale/cn_utf/hr, sql-ledger/locale/cn_utf/ic,
+ sql-ledger/locale/cn_utf/io, sql-ledger/locale/cn_utf/LANGUAGE,
+ sql-ledger/locale/cn_utf/ir, sql-ledger/locale/cn_utf/is,
+ sql-ledger/locale/cn_utf/login, sql-ledger/locale/cn_utf/menu,
+ sql-ledger/locale/cn_utf/oe, sql-ledger/locale/cn_utf/pe,
+ sql-ledger/locale/cn_utf/pos, sql-ledger/locale/cn_utf/arapprn,
+ sql-ledger/locale/cn_utf/ps, sql-ledger/locale/cn_utf/pw,
+ sql-ledger/locale/cn_utf/rc, sql-ledger/locale/cn_utf/rp,
+ sql-ledger/locale/gr/COPYING, sql-ledger/locale/gr/LANGUAGE,
+ sql-ledger/locale/gr/all, sql-ledger/locale/gr/admin,
+ sql-ledger/locale/gr/am, sql-ledger/locale/gr/ap,
+ sql-ledger/locale/gr/ar, sql-ledger/locale/gr/ca,
+ sql-ledger/locale/gr/ct, sql-ledger/locale/gr/gl,
+ sql-ledger/locale/gr/ic, sql-ledger/locale/gr/ir,
+ sql-ledger/locale/gr/io, sql-ledger/locale/gr/is,
+ sql-ledger/locale/gr/login, sql-ledger/locale/gr/menu,
+ sql-ledger/locale/gr/rp, sql-ledger/locale/gr/arap,
+ sql-ledger/locale/gr/arapprn, sql-ledger/locale/gr/bp,
+ sql-ledger/locale/gr/cp, sql-ledger/locale/gr/hr,
+ sql-ledger/locale/gr/oe, sql-ledger/locale/gr/pe,
+ sql-ledger/locale/gr/pos, sql-ledger/locale/gr/ps,
+ sql-ledger/locale/gr/pw, sql-ledger/locale/gr/rc,
+ old/sql-ledger/VERSION, old/sql-ledger/am.pl,
+ old/sql-ledger/favicon.ico, old/sql-ledger/login.pl,
+ old/sql-ledger/menu.ini, old/sql-ledger/sql-ledger.png,
+ old/sql-ledger/setup.pl, old/sql-ledger/sql-ledger.conf.default,
+ old/sql-ledger/SL/AM.pm, old/sql-ledger/SL/Inifile.pm,
+ old/sql-ledger/SL/AP.pm, old/sql-ledger/SL/AR.pm,
+ old/sql-ledger/SL/CA.pm, old/sql-ledger/SL/CP.pm,
+ old/sql-ledger/SL/CT.pm, old/sql-ledger/SL/Form.pm,
+ old/sql-ledger/SL/GL.pm, old/sql-ledger/SL/IC.pm,
+ old/sql-ledger/SL/IR.pm, old/sql-ledger/SL/IS.pm,
+ old/sql-ledger/SL/Mailer.pm, old/sql-ledger/SL/Menu.pm,
+ old/sql-ledger/SL/Num2text.pm, old/sql-ledger/SL/OE.pm,
+ old/sql-ledger/SL/PE.pm, old/sql-ledger/SL/RC.pm,
+ old/sql-ledger/SL/RP.pm, old/sql-ledger/SL/User.pm,
+ old/sql-ledger/bin/lynx/menu.pl,
+ old/sql-ledger/bin/mozilla/admin.pl,
+ old/sql-ledger/bin/mozilla/am.pl,
+ old/sql-ledger/bin/mozilla/ap.pl,
+ old/sql-ledger/bin/mozilla/ar.pl,
+ old/sql-ledger/bin/mozilla/arap.pl,
+ old/sql-ledger/bin/mozilla/ca.pl,
+ old/sql-ledger/bin/mozilla/cp.pl,
+ old/sql-ledger/bin/mozilla/ct.pl,
+ old/sql-ledger/bin/mozilla/gl.pl,
+ old/sql-ledger/bin/mozilla/ic.pl,
+ old/sql-ledger/bin/mozilla/io.pl,
+ old/sql-ledger/bin/mozilla/ir.pl,
+ old/sql-ledger/bin/mozilla/is.pl,
+ old/sql-ledger/bin/mozilla/login.pl,
+ old/sql-ledger/bin/mozilla/menu.pl,
+ old/sql-ledger/bin/mozilla/oe.pl,
+ old/sql-ledger/bin/mozilla/pe.pl,
+ old/sql-ledger/bin/mozilla/rc.pl,
+ old/sql-ledger/bin/mozilla/rp.pl,
+ old/sql-ledger/css/sql-ledger.css, old/sql-ledger/doc/COPYING,
+ old/sql-ledger/doc/README, old/sql-ledger/doc/UPGRADE-1.6-1.8,
+ old/sql-ledger/doc/UPGRADE-1.8-1.8.3,
+ old/sql-ledger/doc/UPGRADE-1.8.3-1.8.4,
+ old/sql-ledger/doc/UPGRADE-1.8.4-1.8.5,
+ old/sql-ledger/doc/UPGRADE-1.8.5-1.8.7,
+ old/sql-ledger/doc/UPGRADE-1.8.7-2.0.0,
+ old/sql-ledger/doc/UPGRADE-2.0-2.0.8,
+ old/sql-ledger/doc/copyright, old/sql-ledger/doc/faq.html,
+ old/sql-ledger/locale/br/COPYING,
+ old/sql-ledger/locale/br/LANGUAGE,
+ old/sql-ledger/locale/br/admin, old/sql-ledger/locale/br/all,
+ old/sql-ledger/locale/br/am, old/sql-ledger/locale/br/ap,
+ old/sql-ledger/locale/br/ar, old/sql-ledger/locale/br/arap,
+ old/sql-ledger/locale/br/ca, old/sql-ledger/locale/br/cp,
+ old/sql-ledger/locale/br/ct, old/sql-ledger/locale/br/gl,
+ old/sql-ledger/locale/br/ic, old/sql-ledger/locale/br/io,
+ old/sql-ledger/locale/br/ir, old/sql-ledger/locale/br/is,
+ old/sql-ledger/locale/br/login, old/sql-ledger/locale/br/menu,
+ old/sql-ledger/locale/br/oe, old/sql-ledger/locale/br/pe,
+ old/sql-ledger/locale/br/rc, old/sql-ledger/locale/br/rp,
+ old/sql-ledger/locale/cn/COPYING,
+ old/sql-ledger/locale/cn/LANGUAGE,
+ old/sql-ledger/locale/cn/admin, old/sql-ledger/locale/cn/all,
+ old/sql-ledger/locale/cn/am, old/sql-ledger/locale/cn/ap,
+ old/sql-ledger/locale/cn/ar, old/sql-ledger/locale/cn/arap,
+ old/sql-ledger/locale/cn/ca, old/sql-ledger/locale/cn/cp,
+ old/sql-ledger/locale/cn/ct, old/sql-ledger/locale/cn/gl,
+ old/sql-ledger/locale/cn/ic, old/sql-ledger/locale/cn/io,
+ old/sql-ledger/locale/cn/ir, old/sql-ledger/locale/cn/is,
+ old/sql-ledger/locale/cn/login, old/sql-ledger/locale/cn/menu,
+ old/sql-ledger/locale/cn/oe, old/sql-ledger/locale/cn/pe,
+ old/sql-ledger/locale/cn/rc, old/sql-ledger/locale/cn/rp,
+ old/sql-ledger/locale/ct/COPYING,
+ old/sql-ledger/locale/ct/LANGUAGE,
+ old/sql-ledger/locale/ct/admin, old/sql-ledger/locale/ct/all,
+ old/sql-ledger/locale/ct/am, old/sql-ledger/locale/ct/ap,
+ old/sql-ledger/locale/ct/ar, old/sql-ledger/locale/ct/arap,
+ old/sql-ledger/locale/ct/ca, old/sql-ledger/locale/ct/cp,
+ old/sql-ledger/locale/ct/ct, old/sql-ledger/locale/ct/gl,
+ old/sql-ledger/locale/ct/ic, old/sql-ledger/locale/ct/io,
+ old/sql-ledger/locale/ct/ir, old/sql-ledger/locale/ct/is,
+ old/sql-ledger/locale/ct/login, old/sql-ledger/locale/ct/menu,
+ old/sql-ledger/locale/ct/oe, old/sql-ledger/locale/ct/pe,
+ old/sql-ledger/locale/ct/rc, old/sql-ledger/locale/ct/rp,
+ old/sql-ledger/locale/cz/COPYING,
+ old/sql-ledger/locale/cz/LANGUAGE,
+ old/sql-ledger/locale/cz/admin, old/sql-ledger/locale/cz/all,
+ old/sql-ledger/locale/cz/am, old/sql-ledger/locale/cz/ap,
+ old/sql-ledger/locale/cz/ar, old/sql-ledger/locale/cz/arap,
+ old/sql-ledger/locale/cz/ca, old/sql-ledger/locale/cz/cp,
+ old/sql-ledger/locale/cz/ct, old/sql-ledger/locale/cz/gl,
+ old/sql-ledger/locale/cz/ic, old/sql-ledger/locale/cz/io,
+ old/sql-ledger/locale/cz/ir, old/sql-ledger/locale/cz/is,
+ old/sql-ledger/locale/cz/login, old/sql-ledger/locale/cz/menu,
+ old/sql-ledger/locale/cz/oe, old/sql-ledger/locale/cz/pe,
+ old/sql-ledger/locale/cz/rc, old/sql-ledger/locale/cz/rp,
+ old/sql-ledger/locale/de/COPYING,
+ old/sql-ledger/locale/de/LANGUAGE,
+ old/sql-ledger/locale/de/Num2text,
+ old/sql-ledger/locale/de/admin,
+ old/sql-ledger/locale/de/locales.pl,
+ old/sql-ledger/locale/de/all, old/sql-ledger/locale/de/am,
+ old/sql-ledger/locale/de/ap, old/sql-ledger/locale/de/ar,
+ old/sql-ledger/locale/de/arap, old/sql-ledger/locale/de/ca,
+ old/sql-ledger/locale/de/cp, old/sql-ledger/locale/de/ct,
+ old/sql-ledger/locale/de/gl, old/sql-ledger/locale/de/ic,
+ old/sql-ledger/locale/de/io, old/sql-ledger/locale/de/ir,
+ old/sql-ledger/locale/de/is, old/sql-ledger/locale/de/login,
+ old/sql-ledger/locale/de/menu, old/sql-ledger/locale/de/oe,
+ old/sql-ledger/locale/de/pe, old/sql-ledger/locale/de/rc,
+ old/sql-ledger/locale/de/rp, old/sql-ledger/locale/dk/COPYING,
+ old/sql-ledger/locale/dk/LANGUAGE,
+ old/sql-ledger/locale/dk/admin, old/sql-ledger/locale/dk/all,
+ old/sql-ledger/locale/dk/am, old/sql-ledger/locale/dk/ap,
+ old/sql-ledger/locale/dk/ar, old/sql-ledger/locale/dk/arap,
+ old/sql-ledger/locale/dk/ca, old/sql-ledger/locale/dk/cp,
+ old/sql-ledger/locale/dk/ct, old/sql-ledger/locale/dk/gl,
+ old/sql-ledger/locale/dk/ic, old/sql-ledger/locale/dk/io,
+ old/sql-ledger/locale/dk/ir, old/sql-ledger/locale/dk/is,
+ old/sql-ledger/locale/dk/login, old/sql-ledger/locale/dk/menu,
+ old/sql-ledger/locale/dk/oe, old/sql-ledger/locale/dk/pe,
+ old/sql-ledger/locale/dk/rc, old/sql-ledger/locale/dk/rp,
+ old/sql-ledger/locale/ee/COPYING,
+ old/sql-ledger/locale/ee/LANGUAGE,
+ old/sql-ledger/locale/ee/admin, old/sql-ledger/locale/ee/all,
+ old/sql-ledger/locale/ee/am, old/sql-ledger/locale/ee/ap,
+ old/sql-ledger/locale/ee/ar, old/sql-ledger/locale/ee/arap,
+ old/sql-ledger/locale/ee/ca, old/sql-ledger/locale/ee/cp,
+ old/sql-ledger/locale/ee/ct, old/sql-ledger/locale/ee/gl,
+ old/sql-ledger/locale/ee/ic, old/sql-ledger/locale/ee/io,
+ old/sql-ledger/locale/ee/ir, old/sql-ledger/locale/ee/is,
+ old/sql-ledger/locale/ee/login, old/sql-ledger/locale/ee/menu,
+ old/sql-ledger/locale/ee/oe, old/sql-ledger/locale/ee/pe,
+ old/sql-ledger/locale/ee/rc, old/sql-ledger/locale/ee/rp,
+ old/sql-ledger/locale/en_GB/COPYING,
+ old/sql-ledger/locale/en_GB/LANGUAGE,
+ old/sql-ledger/locale/en_GB/admin,
+ old/sql-ledger/locale/en_GB/all, old/sql-ledger/locale/en_GB/am,
+ old/sql-ledger/locale/en_GB/ap, old/sql-ledger/locale/en_GB/ar,
+ old/sql-ledger/locale/en_GB/arap, old/sql-ledger/locale/en_GB/bp,
+ old/sql-ledger/locale/en_GB/ca, old/sql-ledger/locale/en_GB/cp,
+ old/sql-ledger/locale/en_GB/ct, old/sql-ledger/locale/en_GB/gl:
+ Initial revision
+
+2004-11-13 04:44 ivan
+
+ * sql-ledger/sql-ledger/: templates/Default-work_order.tex,
+ templates/Hungarian-purchase_order.html,
+ templates/Hungarian-purchase_order.tex,
+ templates/Hungarian-receipt.tex,
+ templates/Hungarian-sales_order.html,
+ templates/Hungarian-sales_order.tex,
+ templates/Hungarian-statement.html,
+ templates/Hungarian-statement.tex, templates/Danish-bin_list.tex,
+ templates/Danish-work_order.html,
+ templates/Danish-work_order.tex,
+ templates/Default-work_order.html,
+ templates/Dutch-work_order.html, templates/Dutch-work_order.tex,
+ templates/Estonian-pos_invoice.txt,
+ templates/French-pos_invoice.txt,
+ templates/Service-work_order.html,
+ templates/Service-work_order.tex,
+ templates/Estonian-work_order.html,
+ templates/Estonian-work_order.tex,
+ templates/French-work_order.html,
+ templates/French-work_order.tex,
+ templates/German-work_order.html,
+ templates/German-work_order.tex,
+ templates/Hungarian-work_order.html,
+ templates/Hungarian-work_order.tex,
+ templates/Italian-work_order.html,
+ templates/Italian-work_order.tex,
+ templates/Norwegian-work_order.html,
+ templates/Brazilian_Portuguese-bin_list.html,
+ templates/Brazilian_Portuguese-bin_list.tex,
+ templates/Brazilian_Portuguese-pick_list.html,
+ templates/Brazilian_Portuguese-pick_list.tex,
+ templates/Brazilian_Portuguese-pos_invoice.txt,
+ templates/Danish-pick_list.html,
+ templates/German-pos_invoice.txt,
+ templates/Italian-pos_invoice.txt,
+ templates/Norwegian-pos_invoice.txt,
+ templates/Norwegian-work_order.tex,
+ templates/Service-pos_invoice.txt,
+ templates/Spanish_A4-pos_invoice.txt,
+ templates/Spanish_A4-work_order.html,
+ templates/Spanish_A4-work_order.tex,
+ templates/Spanish_Letter-pos_invoice.txt,
+ templates/Spanish_Letter-work_order.html,
+ templates/Spanish_Letter-work_order.tex,
+ templates/Brazilian_Portuguese-request_quotation.html,
+ templates/Brazilian_Portuguese-request_quotation.tex,
+ templates/Brazilian_Portuguese-sales_quotation.html,
+ templates/Brazilian_Portuguese-sales_quotation.tex,
+ templates/Brazilian_Portuguese-work_order.html,
+ templates/Brazilian_Portuguese-work_order.tex,
+ templates/Danish-bin_list.html, templates/Danish-pick_list.tex,
+ templates/Danish-request_quotation.html,
+ templates/Danish-request_quotation.tex,
+ templates/Danish-sales_quotation.html,
+ templates/Danish-sales_quotation.tex,
+ templates/Dutch-bin_list.html, templates/Dutch-bin_list.tex,
+ templates/Dutch-pick_list.html, templates/Dutch-pick_list.tex,
+ templates/Dutch-request_quotation.html,
+ templates/Dutch-request_quotation.tex,
+ templates/Dutch-sales_quotation.html,
+ templates/Dutch-sales_quotation.tex,
+ templates/Estonian-bin_list.html,
+ templates/Estonian-bin_list.tex,
+ templates/Estonian-pick_list.html,
+ templates/Estonian-pick_list.tex,
+ templates/Estonian-request_quotation.html,
+ templates/Estonian-request_quotation.tex,
+ templates/French-bin_list.html, templates/French-bin_list.tex,
+ templates/French-pick_list.html, templates/French-pick_list.tex,
+ templates/French-request_quotation.html,
+ templates/French-request_quotation.tex,
+ templates/French-sales_quotation.html,
+ templates/French-sales_quotation.tex,
+ templates/German-bin_list.html, templates/German-bin_list.tex,
+ templates/German-pick_list.html, templates/German-pick_list.tex,
+ templates/German-request_quotation.html,
+ templates/German-request_quotation.tex,
+ templates/German-sales_quotation.html,
+ templates/German-sales_quotation.tex,
+ templates/Hungarian-bin_list.html,
+ templates/Hungarian-bin_list.tex,
+ templates/Hungarian-pick_list.html,
+ templates/Hungarian-pick_list.tex,
+ templates/Hungarian-request_quotation.html,
+ templates/Hungarian-request_quotation.tex,
+ templates/Hungarian-sales_quotation.html,
+ templates/Hungarian-sales_quotation.tex,
+ templates/Italian-bin_list.html, templates/Italian-bin_list.tex,
+ templates/Italian-pick_list.html,
+ templates/Italian-pick_list.tex,
+ templates/Italian-request_quotation.html,
+ templates/Italian-request_quotation.tex,
+ templates/Italian-sales_quotation.html,
+ templates/Italian-sales_quotation.tex,
+ templates/Norwegian-bin_list.html,
+ templates/Norwegian-bin_list.tex,
+ templates/Norwegian-pick_list.html,
+ templates/Norwegian-pick_list.tex,
+ templates/Norwegian-request_quotation.html,
+ templates/Norwegian-request_quotation.tex,
+ templates/Norwegian-sales_quotation.html,
+ templates/Norwegian-sales_quotation.tex,
+ templates/Service-bin_list.html, templates/Service-bin_list.tex,
+ templates/Service-pick_list.html,
+ templates/Service-pick_list.tex,
+ templates/Service-request_quotation.html,
+ templates/Service-request_quotation.tex,
+ templates/Service-sales_quotation.html,
+ templates/Service-sales_quotation.tex,
+ templates/Spanish_A4-bin_list.html,
+ templates/Spanish_A4-bin_list.tex,
+ templates/Spanish_A4-pick_list.html,
+ templates/Spanish_A4-pick_list.tex,
+ templates/Spanish_A4-request_quotation.html,
+ templates/Spanish_A4-request_quotation.tex,
+ templates/Spanish_A4-sales_quotation.html,
+ templates/Spanish_A4-sales_quotation.tex,
+ templates/Spanish_Letter-bin_list.html,
+ templates/Spanish_Letter-bin_list.tex,
+ templates/Spanish_Letter-pick_list.html,
+ templates/Spanish_Letter-pick_list.tex,
+ templates/Spanish_Letter-request_quotation.html,
+ templates/Spanish_Letter-request_quotation.tex,
+ templates/Spanish_Letter-sales_quotation.html,
+ templates/Spanish_Letter-sales_quotation.tex,
+ templates/Brazilian_Portuguese-ap_transaction.html,
+ templates/Brazilian_Portuguese-ap_transaction.tex,
+ templates/Brazilian_Portuguese-ar_transaction.html,
+ templates/Brazilian_Portuguese-ar_transaction.tex,
+ templates/Danish-ap_transaction.html,
+ templates/Danish-ap_transaction.tex,
+ templates/Danish-ar_transaction.html,
+ templates/Danish-ar_transaction.tex,
+ templates/Default-ap_transaction.html,
+ templates/Default-ap_transaction.tex,
+ templates/Default-ar_transaction.html,
+ templates/Default-ar_transaction.tex,
+ templates/Dutch-ap_transaction.html,
+ templates/Dutch-ap_transaction.tex,
+ templates/Dutch-ar_transaction.html,
+ templates/Dutch-ar_transaction.tex,
+ templates/Estonian-ap_transaction.html,
+ templates/Estonian-ap_transaction.tex,
+ templates/Estonian-ar_transaction.html,
+ templates/Estonian-ar_transaction.tex,
+ templates/French-ap_transaction.html,
+ templates/French-ap_transaction.tex,
+ templates/French-ar_transaction.html,
+ templates/French-ar_transaction.tex,
+ templates/German-ap_transaction.html,
+ templates/German-ap_transaction.tex,
+ templates/German-ar_transaction.html,
+ templates/German-ar_transaction.tex,
+ templates/Hungarian-ap_transaction.html,
+ templates/Hungarian-ap_transaction.tex,
+ templates/Hungarian-ar_transaction.html,
+ templates/Hungarian-ar_transaction.tex,
+ templates/Italian-ap_transaction.html,
+ templates/Italian-ap_transaction.tex,
+ templates/Italian-ar_transaction.html,
+ templates/Italian-ar_transaction.tex,
+ templates/Norwegian-ap_transaction.html,
+ templates/Norwegian-ap_transaction.tex,
+ templates/Norwegian-ar_transaction.html,
+ templates/Norwegian-ar_transaction.tex,
+ templates/Service-ap_transaction.html,
+ templates/Service-ap_transaction.tex,
+ templates/Service-ar_transaction.html,
+ templates/Service-ar_transaction.tex,
+ templates/Spanish_A4-ap_transaction.html,
+ templates/Spanish_A4-ap_transaction.tex,
+ templates/Spanish_A4-ar_transaction.html,
+ templates/Spanish_A4-ar_transaction.tex,
+ templates/Spanish_Letter-ap_transaction.html,
+ templates/Spanish_Letter-ap_transaction.tex, css/sql-ledger.css,
+ templates/Spanish_Letter-ar_transaction.html,
+ templates/Spanish_Letter-ar_transaction.tex,
+ users/sql-ledger.eps, users/sql-ledger.png, SL/AP.pm, SL/AR.pm,
+ SL/Form.pm, SL/User.pm, SL/GL.pm, SL/CT.pm, SL/IC.pm, SL/IR.pm,
+ SL/IS.pm, SL/AM.pm, SL/CA.pm, SL/RP.pm, SL/Menu.pm,
+ SL/Inifile.pm, SL/Mailer.pm, SL/OE.pm, SL/Num2text.pm, SL/PE.pm,
+ SL/BP.pm, SL/HR.pm, SL/CP.pm, SL/OP.pm, SL/RC.pm,
+ locale/de/admin, locale/de/am, locale/de/ap, locale/de/ar,
+ locale/de/arap, locale/de/bp, locale/de/ca, locale/de/cp,
+ locale/de/ct, locale/de/locales.pl, locale/de/gl, locale/de/hr,
+ locale/de/ic, locale/de/io, locale/de/COPYING,
+ locale/de/LANGUAGE, locale/de/ir, locale/de/is, locale/de/login,
+ locale/de/menu, locale/de/oe, locale/de/pe, locale/de/pos,
+ locale/de/ps, locale/de/rc, locale/de/Num2text,
+ locale/de/arapprn, locale/de/pw, locale/de/rp, locale/fr/admin,
+ locale/fr/am, locale/fr/io, locale/fr/all, locale/fr/ap,
+ locale/fr/ar, locale/fr/ca, locale/fr/ct, locale/fr/gl,
+ locale/fr/arap, locale/fr/ic, locale/fr/ir, locale/fr/is,
+ locale/fr/rp, locale/fr/COPYING, locale/fr/LANGUAGE,
+ locale/fr/login, locale/fr/menu, locale/fr/oe, locale/fr/pe,
+ locale/fr/bp, locale/fr/cp, locale/fr/pos, locale/fr/ps,
+ locale/fr/rc, locale/co/COPYING, locale/co/LANGUAGE,
+ locale/co/Num2text, locale/fr/Num2text, locale/fr/arapprn,
+ locale/fr/hr, locale/fr/pw, locale/co/admin, locale/co/all,
+ locale/co/am, locale/co/ap, locale/co/ar, locale/co/ca,
+ locale/co/ct, locale/co/gl, locale/co/ic, locale/co/io,
+ locale/co/ir, locale/co/login, locale/co/menu, locale/co/is,
+ locale/co/oe, locale/co/rp, locale/co/arap, locale/co/bp,
+ locale/co/cp, locale/co/pe, locale/co/pos, locale/co/rc,
+ locale/co/arapprn, locale/co/hr, locale/co/ps, locale/co/pw,
+ locale/dk/admin, locale/dk/ap, locale/dk/ar, locale/dk/ca,
+ locale/dk/menu, locale/dk/ct, locale/dk/gl, locale/dk/ic,
+ locale/dk/ir, locale/dk/is, locale/dk/login, locale/dk/LANGUAGE,
+ locale/dk/am, locale/dk/io, locale/dk/rp, locale/dk/COPYING,
+ locale/dk/arap, locale/dk/bp, locale/dk/cp, locale/dk/oe,
+ locale/dk/pe, locale/dk/rc, locale/dk/pos, locale/dk/hr,
+ locale/dk/ps, locale/br/ar, locale/dk/all, locale/dk/arapprn,
+ locale/dk/pw, locale/br/admin, locale/br/login, locale/br/all,
+ locale/br/am, locale/br/ct, locale/br/gl, locale/br/ic,
+ locale/br/ir, locale/br/is, locale/br/ap, locale/br/ca,
+ locale/br/menu, locale/br/rp, locale/br/COPYING,
+ locale/br/LANGUAGE, locale/br/arap, locale/br/cp, locale/br/io,
+ locale/br/oe, locale/br/pe, locale/br/bp, locale/br/pos,
+ locale/br/ps, locale/br/rc, locale/br/arapprn, locale/br/hr,
+ locale/br/pw, locale/it/admin, locale/it/ap, locale/it/ar,
+ locale/it/ca, locale/it/ct, locale/it/gl, locale/it/menu,
+ locale/it/ic, locale/it/ir, locale/it/is, locale/it/login,
+ locale/it/rp, locale/it/all, locale/it/am, locale/it/io,
+ locale/it/COPYING, locale/it/LANGUAGE, locale/it/Num2text,
+ locale/it/arap, locale/it/bp, locale/it/cp, locale/it/oe,
+ locale/it/pe, locale/it/rc, locale/it/pos, locale/it/qe,
+ locale/ct/COPYING, locale/ct/LANGUAGE, locale/it/arapprn,
+ locale/it/hr, locale/it/ps, locale/it/pw, locale/ct/all,
+ locale/ct/admin, locale/ct/am, locale/ct/ap, locale/ct/ar,
+ locale/ct/ca, locale/ct/ct, locale/ct/gl, locale/ct/ic,
+ locale/ct/io, locale/ct/ir, locale/ct/login, locale/ct/is,
+ locale/ct/menu, locale/ct/rp, locale/ct/arap, locale/ct/arapprn,
+ locale/ct/bp, locale/ct/cp, locale/ct/hr, locale/ct/oe,
+ locale/ct/pe, locale/ct/pos, locale/ct/ps, locale/ct/pw,
+ locale/ct/rc, locale/ee/admin, locale/ee/login, locale/ee/all,
+ locale/ee/ar, locale/ee/ct, locale/ee/gl, locale/ee/ic,
+ locale/ee/ir, locale/ee/am, locale/ee/ap, locale/ee/ca,
+ locale/ee/is, locale/ee/menu, locale/ee/rp, locale/ee/COPYING,
+ locale/ee/LANGUAGE, locale/ee/arap, locale/ee/io, locale/ee/oe,
+ locale/ee/pe, locale/ee/cp, locale/ee/rc, locale/ee/Num2text,
+ locale/ee/arapprn, locale/ee/bp, locale/ee/hr, locale/ee/pos,
+ locale/ee/ps, locale/ee/pw, locale/nl/admin, locale/nl/all,
+ locale/nl/am, locale/nl/ap, locale/nl/ar, locale/nl/ca,
+ locale/nl/ct, locale/nl/gl, locale/nl/ic, locale/nl/ir,
+ locale/nl/io, locale/nl/is, locale/nl/login, locale/nl/menu,
+ locale/nl/oe, locale/nl/rp, locale/nl/COPYING,
+ locale/nl/LANGUAGE, locale/nl/Num2text, locale/nl/arap,
+ locale/nl/bp, locale/nl/cp, locale/nl/pe, locale/nl/pos,
+ locale/nl/rc, locale/nl/arapprn, locale/nl/hr, locale/nl/ps,
+ locale/nl/pw, locale/tr/COPYING, locale/tr/admin, locale/tr/all,
+ locale/tr/am, locale/tr/ap, locale/tr/ar, locale/tr/ca,
+ locale/tr/ct, locale/tr/gl, locale/tr/ic, locale/tr/LANGUAGE,
+ locale/tr/arap, locale/tr/io, locale/tr/ir, locale/tr/is,
+ locale/tr/login, locale/tr/menu, locale/tr/oe, locale/tr/pe,
+ locale/tr/rp, locale/tr/arapprn, locale/tr/bp, locale/tr/cp,
+ locale/tr/hr, locale/tr/pos, locale/tr/ps, locale/tr/pw,
+ locale/tr/rc, locale/ve/COPYING, locale/ve/admin, locale/ve/all,
+ locale/ve/login, locale/ve/am, locale/ve/ar, locale/ve/ap,
+ locale/ve/ct, locale/ve/gl, locale/ve/ic, locale/ve/ir,
+ locale/ve/ca, locale/ve/is, locale/ve/rp, locale/ve/LANGUAGE,
+ locale/ve/arap, locale/ve/cp, locale/ve/io, locale/ve/menu,
+ locale/ve/oe, locale/ve/pe, locale/ve/arapprn, locale/ve/bp,
+ locale/ve/hr, locale/ve/pos, locale/ve/ps, locale/ve/pw,
+ locale/ve/rc, locale/pa/admin, locale/pa/all, locale/pa/am,
+ locale/pa/ap, locale/pa/ar, locale/pa/ca, locale/pa/ct,
+ locale/pa/gl, locale/pa/ic, locale/pa/ir, locale/pa/is,
+ locale/pa/login, locale/pa/menu, locale/pa/COPYING,
+ locale/pa/LANGUAGE, locale/pa/arap, locale/pa/io, locale/pa/oe,
+ locale/pa/pe, locale/pa/rp, locale/pa/arapprn, locale/pa/bp,
+ locale/pa/cp, locale/pa/hr, locale/pa/pos, locale/pa/ps,
+ locale/pa/pw, locale/pa/rc, locale/cz/all, locale/cz/admin,
+ locale/cz/am, locale/cz/ap, locale/cz/ar, locale/cz/ca,
+ locale/cz/ct, locale/cz/gl, locale/cz/ic, locale/cz/ir,
+ locale/cz/COPYING, locale/cz/LANGUAGE, locale/cz/arap,
+ locale/cz/io, locale/cz/is, locale/cz/login, locale/cz/menu,
+ locale/cz/oe, locale/cz/rp, locale/cz/arapprn, locale/cz/bp,
+ locale/cz/cp, locale/cz/hr, locale/cz/pe, locale/cz/pos,
+ locale/cz/ps, locale/cz/pw, locale/cz/rc, locale/pt/admin,
+ locale/pt/all, locale/pt/am, locale/pt/ap, locale/pt/ar,
+ locale/pt/ca, locale/pt/ct, locale/pt/gl, locale/pt/ic,
+ locale/pt/ir, locale/pt/is, locale/pt/login, locale/pt/COPYING,
+ locale/pt/LANGUAGE, locale/pt/arap, locale/pt/io, locale/pt/menu,
+ locale/pt/oe, locale/pt/rp, locale/pt/bp, locale/pt/cp,
+ locale/pt/pe, locale/pt/pos, locale/pt/rc, locale/ec/admin,
+ locale/pt/arapprn, locale/pt/hr, locale/pt/ps, locale/pt/pw,
+ locale/ec/all, locale/ec/am, locale/ec/ap, locale/ec/COPYING,
+ locale/ec/ar, locale/ec/arap, locale/ec/bp, locale/ec/ca,
+ locale/ec/cp, locale/ec/ct, locale/ec/gl, locale/ec/hr,
+ locale/ec/ic, locale/ec/LANGUAGE, locale/ec/io, locale/ec/ir,
+ locale/ec/is, locale/ec/login, locale/ec/Num2text,
+ locale/ec/menu, locale/ec/oe, locale/ec/pe, locale/ec/pos,
+ locale/ec/arapprn, locale/ec/ps, locale/ec/pw, locale/ec/rc,
+ locale/ec/rp, locale/pl/admin, locale/pl/all, locale/pl/am,
+ locale/pl/ap, locale/pl/ar, locale/pl/ca, locale/pl/ct,
+ locale/pl/gl, locale/pl/ic, locale/pl/ir, locale/pl/COPYING,
+ locale/pl/is, locale/pl/login, locale/pl/menu, locale/pl/rp,
+ locale/pl/LANGUAGE, locale/pl/arap, locale/pl/cp, locale/pl/io,
+ locale/pl/oe, locale/pl/pe, locale/pl/bp, locale/pl/pos,
+ locale/pl/rc, locale/mx/COPYING, locale/pl/arapprn, locale/pl/hr,
+ locale/pl/ps, locale/pl/pw, locale/mx/all, locale/mx/admin,
+ locale/mx/am, locale/mx/ap, locale/mx/ar, locale/mx/ca,
+ locale/mx/ct, locale/mx/gl, locale/mx/ic, locale/mx/ir,
+ locale/mx/is, locale/mx/login, locale/mx/menu, locale/mx/rp,
+ locale/mx/LANGUAGE, locale/mx/arap, locale/mx/cp, locale/mx/io,
+ locale/mx/oe, locale/mx/pe, locale/mx/bp, locale/mx/pos,
+ locale/mx/ps, locale/mx/rc, locale/fi/COPYING,
+ locale/fi/LANGUAGE, locale/mx/arapprn, locale/mx/hr,
+ locale/mx/pw, locale/fi/admin, locale/fi/all, locale/fi/am,
+ locale/fi/ap, locale/fi/ar, locale/fi/ca, locale/fi/ct,
+ locale/fi/gl, locale/fi/ic, locale/fi/ir, locale/fi/io,
+ locale/fi/login, locale/fi/menu, locale/fi/rp, locale/fi/arap,
+ locale/fi/bp, locale/fi/cp, locale/fi/is, locale/fi/oe,
+ locale/fi/pe, locale/fi/pos, locale/fi/rc, locale/fi/arapprn,
+ locale/fi/hr, locale/fi/ps, locale/fi/pw, locale/ru/COPYING,
+ locale/ru/LANGUAGE, locale/ru/all, locale/ru/admin, locale/ru/am,
+ locale/ru/ap, locale/ru/ar, locale/ru/ca, locale/ru/ct,
+ locale/ru/gl, locale/ru/ic, locale/ru/io, locale/ru/ir,
+ locale/ru/is, locale/ru/login, locale/ru/menu, locale/ru/rp:
+ Initial revision
+
+2004-11-13 04:41 ivan
+
+ * sql-ledger/: sql-ledger-2.0.8.tar.gz, sql-ledger-2.4.4.tar.gz,
+ sql-ledger/VERSION, sql-ledger/am.pl, sql-ledger/favicon.ico,
+ sql-ledger/index.html, sql-ledger/login.pl, sql-ledger/menu.ini,
+ sql-ledger/setup.pl, sql-ledger/sql-ledger.conf.default,
+ sql-ledger/sql-ledger.gif, sql-ledger/sql-ledger.png,
+ sql-ledger/bin/mozilla/admin.pl, sql-ledger/bin/mozilla/am.pl,
+ sql-ledger/bin/mozilla/ap.pl, sql-ledger/bin/mozilla/ar.pl,
+ sql-ledger/bin/mozilla/ca.pl, sql-ledger/bin/mozilla/ct.pl,
+ sql-ledger/bin/mozilla/gl.pl, sql-ledger/bin/mozilla/ic.pl,
+ sql-ledger/bin/mozilla/ir.pl, sql-ledger/bin/mozilla/io.pl,
+ sql-ledger/bin/mozilla/login.pl, sql-ledger/bin/mozilla/menu.pl,
+ sql-ledger/bin/mozilla/rp.pl, sql-ledger/bin/mozilla/is.pl,
+ sql-ledger/bin/mozilla/oe.pl, sql-ledger/bin/mozilla/arap.pl,
+ sql-ledger/bin/mozilla/pe.pl, sql-ledger/bin/mozilla/bp.pl,
+ sql-ledger/bin/mozilla/cp.pl, sql-ledger/bin/mozilla/rc.pl,
+ sql-ledger/bin/mozilla/pos.pl, sql-ledger/bin/mozilla/ps.pl,
+ sql-ledger/bin/lynx/menu.pl, sql-ledger/bin/mozilla/arapprn.pl,
+ sql-ledger/bin/mozilla/hr.pl, sql-ledger/bin/mozilla/pw.pl,
+ sql-ledger/bin/js/menu.pl, sql-ledger/doc/COPYING,
+ sql-ledger/doc/README, sql-ledger/doc/COPYRIGHT,
+ sql-ledger/doc/README.DB2, sql-ledger/doc/UPGRADE-1.6-1.8,
+ sql-ledger/doc/UPGRADE-1.8-1.8.3,
+ sql-ledger/doc/UPGRADE-1.8.3-1.8.4,
+ sql-ledger/doc/UPGRADE-1.8.4-1.8.5,
+ sql-ledger/doc/UPGRADE-1.8.5-1.8.7,
+ sql-ledger/doc/UPGRADE-1.8.7-2.0.0,
+ sql-ledger/doc/UPGRADE-2.0-2.0.8,
+ sql-ledger/doc/UPGRADE-2.0.8-2.0.9,
+ sql-ledger/doc/UPGRADE-2.0.9-2.2.0,
+ sql-ledger/doc/UPGRADE-2.2.0-2.2.7, sql-ledger/doc/faq.html,
+ sql-ledger/doc/UPGRADE-2.2.7-2.4.0,
+ sql-ledger/doc/UPGRADE-2.4.0-2.4.1,
+ sql-ledger/doc/UPGRADE-2.4.1-2.4.2,
+ sql-ledger/doc/UPGRADE-2.4.2-2.4.3,
+ sql-ledger/doc/UPGRADE-2.4.3-2.4.4,
+ sql-ledger/sql/Default-chart.sql,
+ sql-ledger/sql/Oracle-tables.sql,
+ sql-ledger/sql/France-chart.sql,
+ sql-ledger/sql/Pg-upgrade-1.6.0-1.8.0.sql,
+ sql-ledger/sql/Dutch_Default-chart.sql,
+ sql-ledger/sql/Poland-chart.sql,
+ sql-ledger/sql/Danish_Default-chart.sql,
+ sql-ledger/sql/Italy-gifi.sql,
+ sql-ledger/sql/Czech-Republic-chart.sql,
+ sql-ledger/sql/Simplified-Chinese_Default-chart.sql,
+ sql-ledger/sql/Traditional-Chinese_Default-chart.sql,
+ sql-ledger/sql/Oracle-indices.sql, sql-ledger/sql/Pg-indices.sql,
+ sql-ledger/sql/Austria-chart.sql,
+ sql-ledger/sql/Pg-upgrade-1.2.6-1.2.7.sql,
+ sql-ledger/sql/Pg-upgrade-1.2.7-1.4.0.sql,
+ sql-ledger/sql/Pg-upgrade-1.4.0-1.6.0.sql,
+ sql-ledger/sql/Pg-upgrade-1.8.0-1.8.4.sql,
+ sql-ledger/sql/US_General-chart.sql,
+ sql-ledger/sql/Dutch_Standard-chart.sql,
+ sql-ledger/sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ sql-ledger/sql/Swiss-German-gifi.sql,
+ sql-ledger/sql/Canada-English_General-chart.sql,
+ sql-ledger/sql/German-Sample-gifi.sql,
+ sql-ledger/sql/Pg-upgrade-1.8.4-1.8.5.sql,
+ sql-ledger/sql/Austria-gifi.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.0-2.3.1.sql,
+ sql-ledger/sql/DB2-create.sql, sql-ledger/sql/Swedish-chart.sql,
+ sql-ledger/sql/German-Sample-chart.sql,
+ sql-ledger/sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ sql-ledger/sql/Swiss-German-chart.sql,
+ sql-ledger/sql/Germany-SKR03-gifi.sql,
+ sql-ledger/sql/Germany-SKR03-chart.sql,
+ sql-ledger/sql/Germany-DATEV-SKR03-gifi.sql,
+ sql-ledger/sql/Pg-upgrade-1.8.5-2.0.0.sql,
+ sql-ledger/sql/Germany-DATEV-SKR03-chart.sql,
+ sql-ledger/sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ sql-ledger/sql/Oracle-upgrade-2.0.8-2.2.0.sql,
+ sql-ledger/sql/Pg-upgrade-2.0.8-2.2.0.sql,
+ sql-ledger/sql/Brazil_General-chart.sql,
+ sql-ledger/sql/Hungary-chart.sql,
+ sql-ledger/sql/Italy_General-chart.sql,
+ sql-ledger/sql/Pg-upgrade-2.2.0-2.3.0.sql,
+ sql-ledger/sql/Norwegian_Default-chart.sql,
+ sql-ledger/sql/Pg-upgrade-2.0.0-2.0.8.sql,
+ sql-ledger/sql/Belgium-chart.sql,
+ sql-ledger/sql/Belgium-gifi.sql, sql-ledger/sql/Hungary-gifi.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.1-2.3.3.sql,
+ sql-ledger/sql/Canada-English-gifi.sql,
+ sql-ledger/sql/Italy_cc2424-chart.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.3-2.3.4.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.4-2.3.5.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.5-2.3.6.sql,
+ sql-ledger/sql/Spain-ISO-chart.sql,
+ sql-ledger/sql/Spain-UTF8-chart.sql,
+ sql-ledger/sql/Canada-French-gifi.sql,
+ sql-ledger/sql/DB2-set.sql, sql-ledger/sql/DB2-indices.sql,
+ sql-ledger/sql/DB2-remove.sql, sql-ledger/sql/DB2-tables.sql,
+ sql-ledger/sql/DB2-sql-ledger.order,
+ sql-ledger/sql/Latvia-chart.sql,
+ sql-ledger/sql/Oracle-upgrade-2.0.0-2.0.8.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.6-2.3.7.sql,
+ sql-ledger/sql/NAICS.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.7-2.3.8.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.8-2.3.9.sql,
+ sql-ledger/sql/Colombia-PUC-chart.sql,
+ sql-ledger/sql/Colombia-PUC-gifi.sql,
+ sql-ledger/sql/Pg-functions.sql, sql-ledger/sql/Pg-tables.sql,
+ sql-ledger/sql/Egypt-chart.sql,
+ sql-ledger/sql/US_Manufacturing-chart.sql,
+ sql-ledger/sql/US_Service_Company-chart.sql,
+ sql-ledger/sql/Pg-upgrade-2.3.9-2.4.2.sql,
+ sql-ledger/sql/Pg-upgrade-2.4.2-2.4.3.sql,
+ sql-ledger/sql/Pg-upgrade-2.4.3-2.4.4.sql,
+ sql-ledger/sql/Simplified-Chinese_Default-UTF8-chart.sql,
+ sql-ledger/sql/Traditional-Chinese_Default-UTF8-chart.sql,
+ sql-ledger/templates/Danish-invoice.html,
+ sql-ledger/templates/Default-invoice.html,
+ sql-ledger/templates/Service-income_statement.html,
+ sql-ledger/templates/Service-invoice.html,
+ sql-ledger/templates/Service-packing_list.tex,
+ sql-ledger/templates/Service-purchase_order.tex,
+ sql-ledger/templates/Spanish_A4-invoice.html,
+ sql-ledger/templates/Spanish_A4-packing_list.html,
+ sql-ledger/templates/Spanish_A4-sales_order.html,
+ sql-ledger/templates/Danish-balance_sheet.html,
+ sql-ledger/templates/Danish-income_statement.html,
+ sql-ledger/templates/Danish-invoice.tex,
+ sql-ledger/templates/Default-income_statement.html,
+ sql-ledger/templates/Default-pos_invoice.txt,
+ sql-ledger/templates/French-invoice.html,
+ sql-ledger/templates/Spanish_A4-invoice.tex,
+ sql-ledger/templates/Spanish_A4-packing_list.tex,
+ sql-ledger/templates/Spanish_A4-purchase_order.tex,
+ sql-ledger/templates/Danish-packing_list.tex,
+ sql-ledger/templates/Default-balance_sheet.html,
+ sql-ledger/templates/French-packing_list.html,
+ sql-ledger/templates/Service-invoice.tex,
+ sql-ledger/templates/Service-sales_order.tex,
+ sql-ledger/templates/Spanish_A4-sales_order.tex,
+ sql-ledger/templates/Spanish_Letter-balance_sheet.html,
+ sql-ledger/templates/Spanish_Letter-income_statement.html,
+ sql-ledger/templates/Spanish_Letter-invoice.html,
+ sql-ledger/templates/Spanish_Letter-invoice.tex,
+ sql-ledger/templates/Spanish_Letter-packing_list.html,
+ sql-ledger/templates/French-balance_sheet.html,
+ sql-ledger/templates/French-income_statement.html,
+ sql-ledger/templates/Spanish_A4-balance_sheet.html,
+ sql-ledger/templates/Spanish_Letter-packing_list.tex,
+ sql-ledger/templates/Spanish_Letter-purchase_order.html,
+ sql-ledger/templates/Spanish_Letter-purchase_order.tex,
+ sql-ledger/templates/Spanish_Letter-sales_order.html,
+ sql-ledger/templates/Spanish_Letter-sales_order.tex,
+ sql-ledger/templates/Danish-packing_list.html,
+ sql-ledger/templates/Danish-purchase_order.html,
+ sql-ledger/templates/Danish-purchase_order.tex,
+ sql-ledger/templates/Danish-sales_order.html,
+ sql-ledger/templates/Danish-sales_order.tex,
+ sql-ledger/templates/Estonian-balance_sheet.html,
+ sql-ledger/templates/Estonian-income_statement.html,
+ sql-ledger/templates/Estonian-invoice.html,
+ sql-ledger/templates/Service-balance_sheet.html,
+ sql-ledger/templates/Service-packing_list.html,
+ sql-ledger/templates/Spanish_A4-income_statement.html,
+ sql-ledger/templates/Spanish_A4-purchase_order.html,
+ sql-ledger/templates/Default-packing_list.html,
+ sql-ledger/templates/Default-sales_order.html,
+ sql-ledger/templates/Estonian-invoice.tex,
+ sql-ledger/templates/Estonian-packing_list.html,
+ sql-ledger/templates/Estonian-packing_list.tex,
+ sql-ledger/templates/Estonian-purchase_order.html,
+ sql-ledger/templates/Service-purchase_order.html,
+ sql-ledger/templates/Default-purchase_order.html,
+ sql-ledger/templates/Dutch-balance_sheet.html,
+ sql-ledger/templates/Dutch-income_statement.html,
+ sql-ledger/templates/Dutch-invoice.html,
+ sql-ledger/templates/Estonian-purchase_order.tex,
+ sql-ledger/templates/Estonian-sales_order.html,
+ sql-ledger/templates/Estonian-sales_order.tex,
+ sql-ledger/templates/Service-sales_order.html,
+ sql-ledger/templates/Dutch-invoice.tex,
+ sql-ledger/templates/Dutch-packing_list.html,
+ sql-ledger/templates/Dutch-packing_list.tex,
+ sql-ledger/templates/Dutch-purchase_order.html,
+ sql-ledger/templates/Dutch-purchase_order.tex,
+ sql-ledger/templates/Dutch-sales_order.html,
+ sql-ledger/templates/Dutch-sales_order.tex,
+ sql-ledger/templates/French-invoice.tex,
+ sql-ledger/templates/French-packing_list.tex,
+ sql-ledger/templates/French-purchase_order.tex,
+ sql-ledger/templates/German-packing_list.html,
+ sql-ledger/templates/Default-invoice.tex,
+ sql-ledger/templates/Default-packing_list.tex,
+ sql-ledger/templates/Default-purchase_order.tex,
+ sql-ledger/templates/French-purchase_order.html,
+ sql-ledger/templates/French-sales_order.html,
+ sql-ledger/templates/French-sales_order.tex,
+ sql-ledger/templates/Default-sales_order.tex,
+ sql-ledger/templates/German-balance_sheet.html,
+ sql-ledger/templates/German-income_statement.html,
+ sql-ledger/templates/German-invoice.html,
+ sql-ledger/templates/German-invoice.tex,
+ sql-ledger/templates/German-packing_list.tex,
+ sql-ledger/templates/German-purchase_order.html,
+ sql-ledger/templates/German-purchase_order.tex,
+ sql-ledger/templates/German-sales_order.html,
+ sql-ledger/templates/Brazilian_Portuguese-check.tex,
+ sql-ledger/templates/Danish-check.tex,
+ sql-ledger/templates/Danish-receipt.tex,
+ sql-ledger/templates/Default-check.tex,
+ sql-ledger/templates/Default-receipt.tex,
+ sql-ledger/templates/Dutch-check.tex,
+ sql-ledger/templates/Dutch-receipt.tex,
+ sql-ledger/templates/Estonian-check.tex,
+ sql-ledger/templates/French-receipt.tex,
+ sql-ledger/templates/German-check.tex,
+ sql-ledger/templates/German-receipt.tex,
+ sql-ledger/templates/German-sales_order.tex,
+ sql-ledger/templates/Norwegian-balance_sheet.html,
+ sql-ledger/templates/Service-check.tex,
+ sql-ledger/templates/Service-receipt.tex,
+ sql-ledger/templates/Spanish_A4-check.tex,
+ sql-ledger/templates/Spanish_A4-receipt.tex,
+ sql-ledger/templates/Spanish_Letter-check.tex,
+ sql-ledger/templates/Spanish_Letter-receipt.tex,
+ sql-ledger/templates/Brazilian_Portuguese-balance_sheet.html,
+ sql-ledger/templates/Danish-statement.html,
+ sql-ledger/templates/Danish-statement.tex,
+ sql-ledger/templates/Default-statement.html,
+ sql-ledger/templates/Default-statement.tex,
+ sql-ledger/templates/Dutch-statement.html,
+ sql-ledger/templates/Dutch-statement.tex,
+ sql-ledger/templates/Estonian-statement.html,
+ sql-ledger/templates/Estonian-statement.tex,
+ sql-ledger/templates/French-statement.html,
+ sql-ledger/templates/French-statement.tex,
+ sql-ledger/templates/German-statement.html,
+ sql-ledger/templates/German-statement.tex,
+ sql-ledger/templates/Brazilian_Portuguese-income_statement.html,
+ sql-ledger/templates/Dutch-pos_invoice.txt,
+ sql-ledger/templates/Estonian-receipt.tex,
+ sql-ledger/templates/French-check.tex,
+ sql-ledger/templates/Service-statement.html,
+ sql-ledger/templates/Service-statement.tex,
+ sql-ledger/templates/Spanish_A4-statement.html,
+ sql-ledger/templates/Spanish_A4-statement.tex,
+ sql-ledger/templates/Spanish_Letter-statement.html,
+ sql-ledger/templates/Spanish_Letter-statement.tex,
+ sql-ledger/templates/Brazilian_Portuguese-invoice.html,
+ sql-ledger/templates/Brazilian_Portuguese-invoice.tex,
+ sql-ledger/templates/Brazilian_Portuguese-packing_list.html,
+ sql-ledger/templates/Brazilian_Portuguese-packing_list.tex,
+ sql-ledger/templates/Brazilian_Portuguese-purchase_order.html,
+ sql-ledger/templates/Brazilian_Portuguese-purchase_order.tex,
+ sql-ledger/templates/Brazilian_Portuguese-receipt.tex,
+ sql-ledger/templates/Brazilian_Portuguese-sales_order.html,
+ sql-ledger/templates/Brazilian_Portuguese-sales_order.tex,
+ sql-ledger/templates/Brazilian_Portuguese-statement.html,
+ sql-ledger/templates/Brazilian_Portuguese-statement.tex,
+ sql-ledger/templates/Danish-pos_invoice.txt,
+ sql-ledger/templates/Norwegian-check.tex,
+ sql-ledger/templates/Norwegian-income_statement.html,
+ sql-ledger/templates/Norwegian-invoice.html,
+ sql-ledger/templates/Norwegian-invoice.tex,
+ sql-ledger/templates/Norwegian-packing_list.html,
+ sql-ledger/templates/Norwegian-packing_list.tex,
+ sql-ledger/templates/Italian-balance_sheet.html,
+ sql-ledger/templates/Italian-check.tex,
+ sql-ledger/templates/Italian-income_statement.html,
+ sql-ledger/templates/Norwegian-purchase_order.html,
+ sql-ledger/templates/Norwegian-purchase_order.tex,
+ sql-ledger/templates/Norwegian-receipt.tex,
+ sql-ledger/templates/Norwegian-sales_order.html,
+ sql-ledger/templates/Norwegian-sales_order.tex,
+ sql-ledger/templates/Norwegian-statement.html,
+ sql-ledger/templates/Norwegian-statement.tex,
+ sql-ledger/templates/Italian-invoice.html,
+ sql-ledger/templates/Italian-invoice.tex,
+ sql-ledger/templates/Italian-packing_list.html,
+ sql-ledger/templates/Italian-packing_list.tex,
+ sql-ledger/templates/Italian-purchase_order.html,
+ sql-ledger/templates/Italian-purchase_order.tex,
+ sql-ledger/templates/Italian-receipt.tex,
+ sql-ledger/templates/Italian-sales_order.html,
+ sql-ledger/templates/Italian-sales_order.tex,
+ sql-ledger/templates/Italian-statement.html,
+ sql-ledger/templates/Default-bin_list.html,
+ sql-ledger/templates/Default-bin_list.tex,
+ sql-ledger/templates/Default-pick_list.html,
+ sql-ledger/templates/Default-pick_list.tex,
+ sql-ledger/templates/Default-request_quotation.html,
+ sql-ledger/templates/Default-request_quotation.tex,
+ sql-ledger/templates/Hungarian-balance_sheet.html,
+ sql-ledger/templates/Italian-statement.tex,
+ sql-ledger/templates/Default-sales_quotation.html,
+ sql-ledger/templates/Default-sales_quotation.tex,
+ sql-ledger/templates/Hungarian-check.tex,
+ sql-ledger/templates/Hungarian-income_statement.html,
+ sql-ledger/templates/Hungarian-invoice.html,
+ sql-ledger/templates/Hungarian-invoice.tex,
+ sql-ledger/templates/Hungarian-packing_list.html,
+ sql-ledger/templates/Hungarian-packing_list.tex,
+ sql-ledger/templates/Hungarian-pos_invoice.txt: Initial revision
+
+2004-11-12 21:37 ivan
+
+ * FS/FS/svc_acct.pm: oops, that's better
+
+2004-11-12 21:32 ivan
+
+ * FS/FS/svc_acct.pm: fix problem with dup checking manifesting as
+ Argument isn't numeric errors
+
+2004-11-11 04:18 ivan
+
+ * rt/sbin/rt-setup-database.in: merge in changes to
+ rt-setup-database
+
+2004-11-11 04:11 ivan
+
+ * rt/: html/Ticket/Elements/LoadTextAttachments,
+ html/Ticket/Elements/FindAttachments, html/Elements/QueryString,
+ lib/t/data/rt-send-cc, lib/RT/I18N/hu.po, lib/RT/I18N/da.po:
+ Initial revision
+
+2004-11-11 00:16 ivan
+
+ * install/fedora/fc2/INSTALL: last wo
+
+2004-11-11 00:13 ivan
+
+ * install/fedora/fc2/INSTALL: cats help alot
+
+2004-11-10 23:44 ivan
+
+ * install/fedora/fc2/: INSTALL, sources.list: adding fc2 install
+
+2004-11-09 03:42 ivan
+
+ * httemplate/search/report_tax.cgi: add handling for texas tax
+ exemption and warning that report might not make sense for
+ partial months other than the current one
+
+2004-11-09 03:00 ivan
+
+ * httemplate/search/report_tax.cgi: add handling for texas tax
+ exemption and warning that report might not make sense for
+ partial months other than the current one
+
+2004-11-09 01:31 ivan
+
+ * httemplate/search/report_tax.cgi: parenthesis help alot
+
+2004-11-09 01:13 ivan
+
+ * httemplate/search/report_tax.cgi: fix for correct reporting of
+ generic taxes
+
+2004-11-09 00:14 ivan
+
+ * FS/FS/cust_main.pm: don't generate invoices for COMP customers
+
+2004-11-08 23:23 ivan
+
+ * httemplate/search/report_tax.cgi: fixes to run under the mason
+ strictness
+
+2004-11-08 01:24 ivan
+
+ * FS/FS/part_pkg.pm: bypass plandata warning; we're accessing it on
+ purpose
+
+2004-11-08 01:16 ivan
+
+ * FS/FS/part_pkg.pm: fix bug that could cause mis-billing on
+ upgrades! (new installs ok)
+
+2004-11-07 21:33 ivan
+
+ * bin/rollback: adding in case this is needed again
+
+2004-11-07 14:58 ivan
+
+ * ANNOUNCE.1.5.0, httemplate/docs/install.html: update install
+ documentation for 1.5 HTML::Mason or Apache::ASP install
+
+2004-11-04 01:45 ivan
+
+ * install/debian/3.0/INSTALL: and the last two runtime ones
+
+2004-11-04 01:26 ivan
+
+ * install/debian/3.0/INSTALL: few additional dependancies
+
+2004-10-30 17:01 ivan
+
+ * httemplate/search/cust_main-quickpay.html: quick pay shouldnt
+ default to exact search
+
+2004-10-26 05:43 ivan
+
+ * install/redhat/es3/: INSTALL, httpd-init: adding rh es3 files
+
+2004-10-26 05:36 ivan
+
+ * Makefile: 1.5.0pre6!
+
+2004-10-26 05:33 ivan
+
+ * ANNOUNCE.1.5.0, httemplate/docs/billing.html,
+ httemplate/docs/export.html, httemplate/docs/index.html,
+ httemplate/docs/overview-new.dia,
+ httemplate/docs/overview-new.png, httemplate/docs/schema.html,
+ httemplate/docs/selfservice.html: slightly more up-to-date docs
+
+2004-10-26 05:07 ivan
+
+ * FS/FS/part_export.pm: allow an empty exporttype so you can create
+ new objects
+
+2004-10-26 04:51 ivan
+
+ * FS/FS/part_bill_event.pm: last thing for bug#901, 1.5.0pre6 and
+ webdemo!
+
+2004-10-26 04:26 ivan
+
+ * FS/FS/CGI.pm, FS/FS/Conf.pm, FS/FS/Record.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pkg.pm, FS/FS/part_export.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_pkg_option.pm, ANNOUNCE.1.5.0, README.1.5.0pre6,
+ SCHEMA_CHANGE, FS/FS.pm, FS/MANIFEST, FS/bin/freeside-setup,
+ FS/t/part_pkg-flat.t, FS/t/part_pkg-flat_comission.t,
+ FS/t/part_pkg-flat_comission_cust.t,
+ FS/t/part_pkg-flat_comission_pkg.t, FS/t/part_pkg-flat_delayed.t,
+ FS/t/part_pkg-prorate.t, FS/t/part_pkg-sesmon_hour.t,
+ FS/t/part_pkg-sesmon_minute.t, FS/t/part_pkg-sql_external.t,
+ FS/t/part_pkg-sql_generic.t, FS/t/part_pkg-sqlradacct_hour.t,
+ FS/t/part_pkg-subscription.t, FS/t/part_pkg_option.t,
+ httemplate/browse/part_pkg.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html, httemplate/edit/part_pkg.cgi,
+ httemplate/view/cust_main.cgi, FS/FS/part_pkg/flat.pm,
+ FS/FS/part_pkg/flat_comission.pm,
+ FS/FS/part_pkg/flat_comission_cust.pm,
+ FS/FS/part_pkg/flat_comission_pkg.pm,
+ FS/FS/part_pkg/flat_delayed.pm, FS/FS/part_pkg/prorate.pm,
+ FS/FS/part_pkg/sesmon_hour.pm, FS/FS/part_pkg/sesmon_minute.pm,
+ FS/FS/part_pkg/sql_external.pm, FS/FS/part_pkg/sql_generic.pm,
+ FS/FS/part_pkg/sqlradacct_hour.pm,
+ FS/FS/part_pkg/subscription.pm: modular price plans!
+
+2004-10-25 23:33 ivan
+
+ * httemplate/search/report_tax.cgi: and one last case with named
+ and not named taxes in the same region, ack
+
+2004-10-25 23:04 ivan
+
+ * httemplate/search/report_tax.cgi: taxes are hard
+
+2004-10-25 16:47 ivan
+
+ * httemplate/search/report_tax.cgi: hopefully fix tax report for
+ taxclass & named tax edge cases
+
+2004-10-25 16:39 ivan
+
+ * httemplate/search/report_tax.cgi: hopefully fix tax report for
+ taxclass & named tax edge cases
+
+2004-10-25 15:48 ivan
+
+ * httemplate/search/report_tax.cgi: hopefully fix tax report for
+ taxclass & named tax edge cases
+
+2004-10-25 14:35 ivan
+
+ * httemplate/search/report_tax.cgi: fix joins for proper tax
+ reporting
+
+2004-10-23 04:45 ivan
+
+ * conf/: alerter_template, invoice_latexfooter, invoice_template:
+ better
+
+2004-10-23 04:34 ivan
+
+ * conf/: invoice_latexfooter, invoice_latexnotes: update default
+ notes and footer
+
+2004-10-23 03:36 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: add debug flag
+
+2004-10-22 03:31 ivan
+
+ * httemplate/view/cust_main.cgi: add svc_external-skip_manual
+ support to main customer view, for artera turbo
+
+2004-10-22 03:14 ivan
+
+ * FS/FS/part_export/artera_turbo.pm: add option to specify a static
+ aid
+
+2004-10-21 01:54 ivan
+
+ * httemplate/browse/part_pkg.cgi: remove tiny formatting glitch
+
+2004-10-21 01:33 ivan
+
+ * httemplate/browse/part_pkg.cgi: if enabled, show taxclass on
+ package definition browse
+
+2004-10-21 00:07 ivan
+
+ * httemplate/search/report_tax.cgi: fix tax report edge cases when
+ using taxclasses in some regions but not others
+
+2004-10-20 01:28 ivan
+
+ * bin/artera.import: back to id
+
+2004-10-20 01:20 ivan
+
+ * bin/artera.import: locate existing ones by title, warn on errors
+
+2004-10-20 01:16 ivan
+
+ * httemplate/index.html: add external browse
+
+2004-10-20 01:14 ivan
+
+ * bin/artera.import: adding artera import
+
+2004-10-20 01:08 ivan
+
+ * bin/artera.import: adding artera import
+
+2004-10-20 01:07 ivan
+
+ * httemplate/: search/svc_external.cgi, index.html: add
+ svc_external search
+
+2004-10-19 17:44 ivan
+
+ * conf/logo.eps: new logo!
+
+2004-10-19 16:52 ivan
+
+ * conf/logo.eps: new logo!
+
+2004-10-19 04:50 ivan
+
+ * FS/bin/freeside-sqlradius-reset: isn't run with elevated
+ privledges, so -T not necessary
+
+2004-10-19 01:44 ivan
+
+ * Makefile: sleep long enough to be worthwhile
+
+2004-10-18 05:37 ivan
+
+ * httemplate/: index.html, images/mid-logo.png,
+ images/small-logo.png: that's right, a new logo
+
+2004-10-17 07:01 ivan
+
+ * FS/FS/part_export/artera_turbo.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/process_svc_external.html,
+ fs_selfservice/FS-SelfService/cgi/provision_list.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: add artera
+ turbo handling to self-service and reseller interfaces
+
+2004-10-17 02:54 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html: use
+ templated svc_acct provisioner, from agent interface
+
+2004-10-17 02:19 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_svc.pm, bin/populate-msgcat,
+ README.1.5.0pre6, FS/FS/part_export/artera_turbo.pm,
+ httemplate/docs/upgrade10.html, httemplate/view/svc_external.cgi:
+ add options to adjust UI for artera turbo as svc_export
+
+2004-10-16 03:15 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_export/artera_turbo.pm,
+ README.1.5.0pre6, FS/FS/svc_external.pm, FS/bin/freeside-setup,
+ httemplate/docs/upgrade10.html: add artera turbo export
+
+2004-10-12 22:46 ivan
+
+ * Makefile: apachectl sucks ass
+
+2004-10-12 14:59 ivan
+
+ * httemplate/view/svc_acct.cgi: fix edit link! oops
+
+2004-10-11 23:08 ivan
+
+ * httemplate/search/sqlradius.cgi: more info in error message for
+ unknown export type, fix test for sqlradius_withdomain export,
+ woo!
+
+2004-10-11 22:54 ivan
+
+ * Makefile: update apache restart line for local apache
+
+2004-10-09 03:57 ivan
+
+ * httemplate/view/svc_acct.cgi: rearrange things a bit and clean up
+ the RADIUS session data, link to the detail search
+
+2004-10-06 06:39 ivan
+
+ * httemplate/search/: sqlradius.cgi: more formatting updates to
+ RADIUS report
+
+2004-10-06 06:33 ivan
+
+ * httemplate/search/sqlradius.cgi: small formatting updates to
+ RADIUS report
+
+2004-10-06 06:27 ivan
+
+ * httemplate/search/sqlradius.cgi: small formatting updates to
+ RADIUS report
+
+2004-10-06 05:37 ivan
+
+ * FS/FS/part_export/sqlradius.pm: fix big in RADIUS session viewing
+ when using an ignored-accounting export
+
+2004-10-05 09:28 ivan
+
+ * httemplate/search/sqlradius.cgi,
+ httemplate/search/sqlradius.html, FS/FS/cust_svc.pm,
+ FS/FS/part_export/sqlradius.pm, httemplate/index.html,
+ httemplate/elements/header.html, httemplate/view/svc_acct.cgi:
+ RADIUS session viewing
+
+2004-10-05 07:16 ivan
+
+ * httemplate/view/cust_bill.cgi: links to show alternate invoices
+ also
+
+2004-10-05 06:52 ivan
+
+ * httemplate/view/cust_bill.cgi: links to show alternate invoices
+ also
+
+2004-10-05 06:43 ivan
+
+ * httemplate/view/: cust_bill-pdf.cgi, cust_bill-ps.cgi,
+ cust_bill.cgi: links to show alternate invoices also
+
+2004-10-05 06:35 ivan
+
+ * httemplate/view/: cust_bill-pdf.cgi, cust_bill-ps.cgi,
+ cust_bill.cgi: links to show alternate invoices also
+
+2004-10-05 05:17 ivan
+
+ * FS/bin/freeside-selfservice-server: DO open a database connection
+ in the parent process, this cached the $dbdef and speeds things
+ up significantly
+
+2004-10-05 04:38 ivan
+
+ * ANNOUNCE.1.5.0: [no log message]
+
+2004-09-30 18:38 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: -w flag spewing too
+ much to STDOUT
+
+2004-09-27 16:17 ivan
+
+ * install/redhat/8/INSTALL: please don't use rh8
+
+2004-09-27 13:42 ivan
+
+ * install/redhat/8/INSTALL: apachetoolbox instead i guess
+
+2004-09-27 13:37 ivan
+
+ * install/redhat/8/: INSTALL, README.insecure, sources.list: adding
+ rh8 install foo and warning
+
+2004-09-22 04:28 ivan
+
+ * httemplate/search/: cust_bill_event.html,
+ report_cust_credit.html, report_cust_pay.html, report_tax.html:
+ add missing <TR> tags
+
+2004-09-22 04:04 ivan
+
+ * httemplate/elements/: calendar-en.js, calendar-setup.js,
+ calendar-win2k-2.css, calendar.js, calendar_stripped.js: update
+ jscalendar
+
+2004-09-21 00:57 ivan
+
+ * httemplate/view/cust_main.cgi: and for refunds too
+
+2004-09-21 00:50 ivan
+
+ * httemplate/view/cust_main.cgi: better display of echeck
+ payments/refunds/etc.
+
+2004-09-16 06:22 ivan
+
+ * FS/FS/export_svc.pm, httemplate/edit/part_svc.cgi: add uid to
+ mass duplicate checking on export changes, fix bug in new export
+ editing, error message includes the number of duplicate customers
+ also
+
+2004-09-16 00:19 ivan
+
+ * FS/FS/cust_main.pm: allow blank auth for echeck refunds
+
+2004-09-15 18:47 ivan
+
+ * FS/FS/svc_acct.pm: don't re-my var, quiet warning
+
+2004-09-15 08:31 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add option for global username or
+ username@domain uniqueness, closes: Bug#980
+
+2004-09-15 01:57 ivan
+
+ * FS/bin/freeside-selfservice-server: it would help to set the
+ permissions on the lockfile right, so the kids can open it...
+
+2004-09-15 01:45 ivan
+
+ * fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ obtain a new descriptor for the lock in kids, this should fix
+ locking problems
+
+2004-09-15 01:30 ivan
+
+ * FS/bin/freeside-selfservice-server: obtain a new descriptor for
+ the lock in kids, this should fix locking problems
+
+2004-09-14 06:00 ivan
+
+ * httemplate/view/cust_main.cgi, FS/FS/cust_main.pm,
+ httemplate/edit/cust_refund.cgi,
+ httemplate/edit/process/cust_refund.cgi: echeck/ACH refunds
+
+2004-09-13 23:47 ivan
+
+ * FS/bin/freeside-selfservice-server,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ selfservice: - server: don't reconnect again if we've already
+ been signalled to shutdown - server: add kid reaping to shutdown
+ sequence - server: add another optional logging level to response
+ sending - server: acquire write mutex for keepalives
+
+2004-09-09 05:04 ivan
+
+ * FS/FS/part_svc.pm, httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi: rework edit/part_svc.cgi so
+ it doesn't use a separate process/ file, this allows large error
+ messages to be displayed properly
+
+2004-09-06 05:44 ivan
+
+ * FS/bin/freeside-selfservice-server,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ self-service keepalives
+
+2004-09-06 02:44 ivan
+
+ * FS/bin/freeside-selfservice-server: don't open a database
+ connection in the parent process
+
+2004-09-06 02:28 ivan
+
+ * FS/bin/freeside-queued: don't die off even on database failures
+
+2004-09-05 16:21 ivan
+
+ * httemplate/edit/cust_main.cgi: fixed duplicate checking will
+ catch it, but add client-side protection against
+ double-submission also.
+
+2004-09-05 15:42 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/signup.html,
+ fs_signup/FS-SignupClient/cgi/signup-agentselect.html,
+ fs_signup/FS-SignupClient/cgi/signup.html: fixed duplicate
+ checking will catch it, but add client-side protection against
+ double-submission also.
+
+2004-09-05 02:42 ivan
+
+ * test/dup-test: adding duplicate test
+
+2004-09-05 02:41 ivan
+
+ * FS/FS/svc_acct.pm: acquire a database lock to prevent race
+ conditions in duplicate checking
+
+2004-09-04 03:02 ivan
+
+ * FS/FS/export_svc.pm: first try at duplicate checking on new
+ export associations
+
+2004-08-27 04:33 ivan
+
+ * FS/bin/freeside-sqlradius-reset: oops use @ARGV not @_
+
+2004-08-27 04:16 ivan
+
+ * FS/bin/freeside-sqlradius-reset: add option to specify exports
+
+2004-08-24 05:22 ivan
+
+ * Makefile: small Makefile update
+
+2004-08-24 04:16 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/agent_customer_menu.html,
+ fs_selfservice/FS-SelfService/cgi/agent_delete_svc.html,
+ fs_selfservice/FS-SelfService/cgi/agent_logout.html,
+ fs_selfservice/FS-SelfService/cgi/agent_main.html,
+ fs_selfservice/FS-SelfService/cgi/agent_menu.html,
+ fs_selfservice/FS-SelfService/cgi/agent_order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/agent_provision.html,
+ fs_selfservice/FS-SelfService/cgi/agent_provision_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/list_customers.html,
+ fs_selfservice/FS-SelfService/cgi/order_pkg.html,
+ fs_selfservice/FS-SelfService/cgi/provision.html,
+ fs_selfservice/FS-SelfService/cgi/provision_list.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/view_customer.html,
+ FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/ClientAPI/Agent.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ httemplate/search/cust_main.cgi: big update for reseller
+ interface
+
+2004-08-20 01:58 ivan
+
+ * bin/ispman.ldap.import: adding
+
+2004-08-19 09:35 ivan
+
+ * httemplate/search/cust_credit.html: add customer # to credit
+ reports too
+
+2004-08-19 03:53 ivan
+
+ * httemplate/edit/part_svc.cgi: shell field is now a dropdown of
+ legal shells, closes: Bug#118
+
+2004-08-18 17:22 ivan
+
+ * httemplate/search/: cust_pay.cgi, elements/search.html: add
+ customer # to payment reports, add table cell alignment option to
+ general search component
+
+2004-08-17 06:14 ivan
+
+ * FS/FS/cust_main.pm: prevent realtime_bop CVV removal from messing
+ up cust_main records, also don't pollute the original object when
+ used with override options, closes: Bug#982
+
+2004-08-17 00:43 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/: passwd.cgi, passwd.html: fix
+ path to passwd.cgi!
+
+2004-08-14 05:26 ivan
+
+ * FS/FS/: export_svc.pm, part_svc.pm, svc_acct.pm: first try at
+ duplicate checking on new export associations
+
+2004-08-11 16:56 ivan
+
+ * FS/FS/cust_bill.pm: fix bank name showing up on invoices
+
+2004-08-09 12:03 ivan
+
+ * init.d/freeside-init: add /usr/local/bin to PATH
+
+2004-08-06 19:49 ivan
+
+ * httemplate/view/cust_main.cgi: disable order package button until
+ a package has been selected
+
+2004-08-05 11:47 ivan
+
+ * FS/FS.pm: fix pod typo
+
+2004-08-02 02:43 ivan
+
+ * httemplate/index.html: fix link to virtual host browse
+
+2004-08-01 17:41 ivan
+
+ * FS/FS/part_export/vpopmail.pm: no maintainer, use
+ shellcommands_withdomain instead
+
+2004-07-30 00:12 ivan
+
+ * FS/FS/svc_Common.pm: set fixed values from an explicitly
+ specified svcpart on replace too
+
+2004-07-29 21:54 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_svc.pm, FS/FS/svc_Common.pm,
+ conf/cust_pkg-change_svcpart,
+ httemplate/edit/process/cust_svc.cgi,
+ httemplate/misc/process/link.cgi, httemplate/view/svc_acct.cgi:
+ svcpart changes now trigger all necessary export actions, manual
+ svcpart changing on svc_acct view, linking changes svcpart if you
+ ask it to, closes: Bug#671, Bug#644
+
+2004-07-29 14:49 ivan
+
+ * FS/bin/freeside-setup: add index on cust_main.refnum, speeds up
+ advertising source list
+
+2004-07-15 15:40 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/delete_svc.html,
+ fs_selfservice/FS-SelfService/cgi/logout.html,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount_menu.html,
+ fs_selfservice/FS-SelfService/cgi/payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/process_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/provision.html,
+ fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_invoice.html,
+ httemplate/view/cust_main.cgi: big update for customer
+ self-service: add provisioning/unprovisioning of purchased
+ services, like fs_selfadmin
+
+2004-07-12 06:51 ivan
+
+ * httemplate/view/cust_main.cgi: DEL out voided payments to
+ distinguish them visually better
+
+2004-07-10 07:46 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix edge case avoiding erronous
+ decline/cancel when customer has a negative balance & purchases
+ stuff with it
+
+2004-07-10 07:30 ivan
+
+ * FS/FS/: cust_svc.pm, part_pkg.pm, ClientAPI/MyAccount.pm: tyop;
+
+2004-07-10 06:30 ivan
+
+ * httemplate/: index.html, search/cust_bill_event.cgi,
+ search/cust_bill_event.html: add calendar to cust_bill_event
+ search page, make ending date default to open-ended like other
+ reports
+
+2004-07-10 06:21 ivan
+
+ * FS/FS/Record.pm: fix FS::Record::qsearch to (hopefully) work as
+ before and cluck loudly when the FS::tablename class isn't
+ loaded, rather than throw exceptions
+
+2004-07-10 06:08 ivan
+
+ * FS/FS/cust_svc.pm: use FS::svc_external so the label method
+ doesn't bomb out in FS::Record::qsearch with Can't locate object
+ method virtual_fields via package FS::svc_external
+
+2004-07-09 04:45 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/agent.cgi: add debugging to
+ agent.cgi, make sure warnings are turned off when parsing
+ templates to avoid too much output to STDERR triggering obscure
+ apache hang bug. thanks dean you rule.
+
+2004-07-09 02:29 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/agent_main.html: new style ;
+ param separator
+
+2004-07-08 04:15 ivan
+
+ * httemplate/edit/process/cust_main.cgi: don't change otaker when
+ just editing account, closes: Bug#921
+
+2004-07-07 09:06 ivan
+
+ * FS/FS/cust_pay.pm: allow payment modification so we can import
+ order_number info
+
+2004-07-06 12:10 ivan
+
+ * FS/FS/Record.pm: better error message for missing tables
+
+2004-07-06 10:27 ivan
+
+ * ANNOUNCE.1.5.0: new features
+
+2004-07-06 10:26 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ httemplate/edit/cust_refund.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_refund.cgi,
+ httemplate/view/cust_main.cgi: payment voiding part deux & credit
+ card refunds!
+
+2004-07-06 07:22 ivan
+
+ * FS/FS/cust_refund.pm: document and check refund reasons
+
+2004-07-06 06:26 ivan
+
+ * README.1.5.0pre1, README.1.5.0pre6, FS/FS.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_pay_void.pm, FS/t/cust_pay_void.t,
+ FS/bin/freeside-setup, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html,
+ httemplate/misc/void-cust_pay.cgi: add cust_pay_void table and
+ payment voiding web ui part one
+
+2004-07-06 01:43 ivan
+
+ * htetc/: global.asa, handler.pl: 0.32 (and then some) released
+
+2004-07-06 01:31 ivan
+
+ * install/5.005/Net-Whois-Raw/: COPYRIGHT, Changes, MANIFEST,
+ META.yml, Makefile.PL, README, pwhois, lib/Net/Whois/Raw.pm,
+ lib/Net/Whois/Raw/Data.pm, t/01.t: 0.32 (and then some) released
+
+2004-07-01 06:49 ivan
+
+ * FS/FS/: ClientAPI/MyAccount.pm, cust_main.pm: credit out
+ self-service
+
+2004-07-01 05:45 ivan
+
+ * FS/FS/agent.pm: fix silly bug editing agents
+
+2004-07-01 05:42 ivan
+
+ * FS/FS/Record.pm: show a full stack backtrace if we wind up in the
+ hash method with an empty Hash attribute, wtf?
+
+2004-06-30 11:19 ivan
+
+ * FS/FS/cust_pay.pm, conf/payment_receipt_email: payyment receipts
+ template fixes
+
+2004-06-30 11:12 ivan
+
+ * FS/FS/cust_pay.pm: payyment receipts: pass body has an arrayref,
+ also fill in name filed
+
+2004-06-30 11:01 ivan
+
+ * FS/FS/cust_pay.pm: typo
+
+2004-06-30 10:57 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill_pay.pm, FS/FS/cust_credit_bill.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pay_refund.pm,
+ conf/payment_receipt_email: payment receipts!
+
+2004-06-30 07:33 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ httemplate/misc/payment.cgi: forgot october! closes: Bug#880
+
+2004-06-30 03:02 ivan
+
+ * FS/: FS/Conf.pm, bin/freeside-daily: add option to pgp/gpg
+ encrypt scp dumps
+
+2004-06-30 02:56 ivan
+
+ * FS/FS/cust_bill.pm: fix warning message when agent-specific
+ plandata cannot be found
+
+2004-06-29 00:57 ivan
+
+ * httemplate/docs/schema.html: cust_pay_refund
+
+2004-06-28 21:02 ivan
+
+ * ANNOUNCE.1.5.0, README.1.5.0pre6, FS/FS.pm, FS/MANIFEST,
+ FS/FS/cust_bill_pay.pm, FS/FS/cust_credit_bill.pm,
+ FS/FS/cust_credit_refund.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_pay_refund.pm, FS/FS/cust_refund.pm,
+ FS/bin/freeside-setup, httemplate/docs/upgrade10.html,
+ httemplate/view/cust_main.cgi, FS/t/cust_pay_refund.t,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_bill_pay.cgi: add cust_pay_refund
+ table to refund payments
+
+2004-06-25 11:28 ivan
+
+ * FS/FS/cust_main.pm: fix Pg date parsing of expdate and thus
+ paydate_monthyear method and thus bug#862 and i need some sleep
+
+2004-06-25 10:57 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ httemplate/misc/payment.cgi: fix one-time card charging not
+ pulling in exp date?
+
+2004-06-25 10:26 ivan
+
+ * httemplate/misc/payment.cgi: set defaults so as to not change the
+ billing type when entering a one time payment
+
+2004-06-25 03:25 ivan
+
+ * FS/: FS/UID.pm, bin/freeside-queued: ping the database and retry
+ rather before doing anything
+
+2004-06-25 03:16 ivan
+
+ * FS/FS/cust_bill.pm: really fix latex printing when datasrc
+ contains a ;
+
+2004-06-25 03:07 ivan
+
+ * FS/FS/cust_bill.pm: fix latex printing when datasrc contains a ;
+
+2004-06-25 01:44 ivan
+
+ * FS/FS/cust_pkg.pm: move up next bill date on unsuspend
+
+2004-06-22 19:13 ivan
+
+ * FS/FS/cust_bill.pm: forgotten space in typeset invoice credit
+ lines
+
+2004-06-22 18:23 ivan
+
+ * httemplate/docs/upgrade10.html: escape html
+
+2004-06-21 20:12 ivan
+
+ * Makefile: snapshot before schema changes
+
+2004-06-21 20:11 ivan
+
+ * FS/FS.pm: small doc update
+
+2004-06-21 20:10 ivan
+
+ * bin/sqlradius.import: fix attribute importing bugs that borked
+ the passwords
+
+2004-06-21 07:24 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/agent.cgi: fix dup password
+ checking on add'l package order
+
+2004-06-21 07:20 ivan
+
+ * fs_signup/FS-SignupClient/SignupClient.pm: export popselector and
+ expselect
+
+2004-06-21 06:36 ivan
+
+ * FS/MANIFEST: removing old report from MANIFEST
+
+2004-06-21 05:27 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: fix harmless typo, closes; Bug#872
+
+2004-06-21 03:58 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/agent.cgi: check password match
+ on agent add'l package order
+
+2004-06-21 03:45 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: field name is primary_svc, not
+ primary
+
+2004-06-21 03:26 ivan
+
+ * FS/FS/: Conf.pm, cust_svc.pm, ClientAPI/MyAccount.pm: option to
+ only allow primary users access to the self-service server
+
+2004-06-18 03:28 ivan
+
+ * bin/masonize, httemplate/search/cust_main-otaker.cgi: masonize
+ fix: avoid newline prepend fix from borking indented first <%,
+ fixes customer search by otaker under mason, closes: Bug#830
+
+2004-06-18 03:07 ivan
+
+ * httemplate/docs/install.html: recommend HTML::Mason
+
+2004-06-17 05:32 ivan
+
+ * FS/FS/part_export/: www_shellcommands.pm, apache.pm: add
+ frontpage extensions to www_shellcommands export
+
+2004-06-16 16:59 ivan
+
+ * FS/FS/svc_acct.pm: fix deletion of accounts connected to virtual
+ hosts
+
+2004-06-16 07:07 ivan
+
+ * httemplate/search/report_tax.cgi: update tax report for taxclass
+
+2004-06-15 06:27 ivan
+
+ * fs_passwd/fs_passwd.cgi, fs_passwd/fs_passwd.html,
+ fs_selfservice/FS-SelfService/cgi/passwd.cgi,
+ fs_selfservice/FS-SelfService/cgi/passwd.html: moving passwd cgi
+ to self-service
+
+2004-06-15 03:59 ivan
+
+ * FS/FS/Record.pm: add stack backtrace to fatal problems in virtual
+ field check
+
+2004-06-11 09:44 ivan
+
+ * httemplate/search/report_tax.cgi: fix date range for old perl,
+ count tax exempt and COMP customers correctly
+
+2004-06-11 07:57 ivan
+
+ * httemplate/search/report_tax.cgi: fix to find all customer
+ scorrectly
+
+2004-06-11 07:25 ivan
+
+ * httemplate/search/report_tax.cgi: tax report fix sort
+
+2004-06-11 07:03 ivan
+
+ * FS/FS/Conf.pm, httemplate/index.html: tax report!
+
+2004-06-11 06:44 ivan
+
+ * FS/bin/freeside-tax-report, httemplate/search/report_tax.cgi: tax
+ report!
+
+2004-06-11 00:37 ivan
+
+ * Makefile: add update-selfservice target
+
+2004-06-10 05:58 ivan
+
+ * httemplate/browse/agent.cgi: now available as methods
+
+2004-06-10 05:31 ivan
+
+ * FS/FS/CGI.pm, FS/FS/agent.pm, FS/FS/cust_main.pm,
+ FS/FS/ClientAPI/Agent.pm, FS/FS/ClientAPI/MyAccount.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_selfservice/FS-SelfService/cgi/agent.cgi,
+ fs_selfservice/FS-SelfService/cgi/agent_login.html,
+ fs_selfservice/FS-SelfService/cgi/agent_main.html,
+ fs_selfservice/FS-SelfService/cgi/cvv2.html,
+ fs_selfservice/FS-SelfService/cgi/cvv2.png,
+ fs_selfservice/FS-SelfService/cgi/cvv2_amex.png,
+ fs_selfservice/FS-SelfService/cgi/list_customers.html,
+ fs_selfservice/FS-SelfService/cgi/signup.html,
+ fs_selfservice/FS-SelfService/cgi/view_customer.html,
+ httemplate/browse/agent.cgi, httemplate/search/cust_main.cgi,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi: agent interface
+
+2004-06-10 04:28 ivan
+
+ * httemplate/search/cust_main-otaker.cgi: tyop
+
+2004-06-09 01:59 ivan
+
+ * Makefile: need this entry for myself though!
+
+2004-06-09 00:17 ivan
+
+ * httemplate/docs/install.html: explicitly specify Apache
+ httpd.conf. fear.
+
+2004-06-05 05:01 ivan
+
+ * Makefile: AND set its owner. whew.
+
+2004-06-05 04:55 ivan
+
+ * Makefile: and don't forget to make the dir
+
+2004-06-05 04:47 ivan
+
+ * Makefile: fix path and make var substitution
+
+2004-06-05 04:37 ivan
+
+ * Makefile: oops fix line endings in automated self-service lib
+ install
+
+2004-06-05 04:34 ivan
+
+ * Makefile: automated self-service lib install
+
+2004-06-05 02:34 ivan
+
+ * bin/: sqlradius-norealm.reimport, sqlradius.import,
+ sqlradius.reimport: sqlradius import updates
+
+2004-06-04 20:00 ivan
+
+ * Makefile: self-service installer?
+
+2004-06-03 03:09 ivan
+
+ * httemplate/misc/email-invoice.cgi: also fix agent-specific From:
+ address on "re-email" link
+
+2004-06-03 02:55 ivan
+
+ * FS/FS/cust_bill.pm: fix agent-specific template on "invoice view"
+ screen and "re-email/re-print" links, also fix agent-specific
+ From: address on "re-email" link
+
+2004-06-03 00:00 ivan
+
+ * FS/FS/cust_bill.pm: better error message for non-applicable
+ invoice events
+
+2004-06-02 14:27 ivan
+
+ * fs_selfservice/DEPLOY: simple kludge for testing
+
+2004-06-01 03:56 ivan
+
+ * httemplate/edit/part_bill_event.cgi: html table fix
+
+2004-06-01 03:53 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/edit/part_bill_event.cgi:
+ per-agent invoice_from addresses
+
+2004-06-01 02:23 ivan
+
+ * bin/postfix_courierimap.import: typo in sql
+
+2004-05-31 18:49 ivan
+
+ * FS/FS/cust_bill.pm: typo in error message
+
+2004-05-28 16:26 ivan
+
+ * bin/sqlradius.reimport: adding password/finger correction tool
+ too
+
+2004-05-28 06:48 ivan
+
+ * bin/postfix_courierimap.import: adding
+
+2004-05-28 04:33 ivan
+
+ * httemplate/misc/upload-batch.cgi: not entirely sure why we're
+ checking the filename at all... to catch empty form submissions?
+
+2004-05-28 04:21 ivan
+
+ * httemplate/misc/upload-batch.cgi: better error reporting on
+ unparsable filenames
+
+2004-05-28 03:38 ivan
+
+ * httemplate/search/elements/search.html: show a better message
+ when no results are found
+
+2004-05-28 03:17 ivan
+
+ * httemplate/search/cust_bill.html: correct count statement when
+ searching for individual invoices by #
+
+2004-05-28 01:40 ivan
+
+ * bin/sqlradius.import: really.
+
+2004-05-28 01:37 ivan
+
+ * bin/sqlradius.import: fixed up and working?
+
+2004-05-28 00:02 ivan
+
+ * FS/FS/svc_domain.pm: report value passed for illegal action
+ pseudo-field
+
+2004-05-27 02:30 ivan
+
+ * bin/sqlradius.import: fixup domain svcpart selection
+
+2004-05-27 02:14 ivan
+
+ * bin/sqlradius.import: adding sqlradius.import
+
+2004-05-26 11:59 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/docs/upgrade-1.4.2.html: require
+ the version of File::Temp with the OO interface
+
+2004-05-26 06:07 ivan
+
+ * FS/FS/part_export/acct_sql.pm: fix table name
+
+2004-05-26 06:02 ivan
+
+ * FS/FS/: part_export/acct_sql.pm, svc_acct.pm: update acct_sql
+ export some more to export to alias table also and in general be
+ more configurable
+
+2004-05-26 04:11 ivan
+
+ * FS/FS/cust_bill.pm: comma
+
+2004-05-26 04:11 ivan
+
+ * FS/FS/cust_bill.pm: use File::Temp for filenames and store the
+ temp files in cache.datasrc instead of /tmp
+
+2004-05-26 03:36 ivan
+
+ * FS/FS/cust_bill.pm: better error checking/reporting for latex
+ setup problems
+
+2004-05-26 02:14 ivan
+
+ * FS/FS/part_export/www_shellcommands.pm: default commands now keep
+ web content in user homedirs and link to /var/www
+
+2004-05-19 07:34 ivan
+
+ * FS/FS/part_export/acct_sql.pm: really fixing deletions in
+ acct_sql export
+
+2004-05-19 07:29 ivan
+
+ * FS/FS/part_export/acct_sql.pm: fixing deletions in acct_sql
+ export
+
+2004-05-19 07:22 ivan
+
+ * FS/FS/part_export/acct_sql.pm: fixing acct_sql export
+
+2004-05-19 06:41 ivan
+
+ * FS/: MANIFEST, FS/part_export/acct_sql.pm,
+ t/part_export-acct_sql.t: adding acct_sql export
+
+2004-05-19 05:31 ivan
+
+ * httemplate/edit/part_pkg.cgi: continue making
+ hours/input/output/total display on invoices conditional on there
+ being any charge for overages
+
+2004-05-19 05:30 ivan
+
+ * httemplate/edit/part_pkg.cgi: finish making
+ hours/input/output/total display on invoices conditional on there
+ being any charge for overages
+
+2004-05-19 05:28 ivan
+
+ * httemplate/edit/part_pkg.cgi: make hours/input/output/total
+ display on invoices conditional on there being any charge for
+ overages
+
+2004-05-17 17:20 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: patch from randell lucas for
+ order_pkg to return pkgnum also
+
+2004-05-14 05:25 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ FS/FS/part_bill_event.pm, httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/process/part_bill_event.cgi: add per-agent
+ invoice templates, add per-package suspend invoice events, fix
+ automatic creation of invoice_latex alternate templates
+
+2004-05-12 11:07 ivan
+
+ * bin/sequences.reset: easier this way
+
+2004-05-12 11:02 ivan
+
+ * bin/: sequences.reset, freeside.import: adding
+
+2004-05-12 05:38 ivan
+
+ * install/redhat/9/: INSTALL, sources.list: that wasn't pleasant
+
+2004-05-12 03:03 ivan
+
+ * Makefile: for native apache installs
+
+2004-05-11 05:01 ivan
+
+ * httemplate/edit/svc_www.cgi: i'm not usually like this.
+
+2004-05-11 04:58 ivan
+
+ * httemplate/edit/svc_www.cgi: this has been an evening of logical
+ negation
+
+2004-05-11 04:54 ivan
+
+ * httemplate/edit/svc_www.cgi: so close
+
+2004-05-11 04:52 ivan
+
+ * httemplate/edit/svc_www.cgi: clean this up a bit, fix
+ svc_www-usersvc_svcpart and hopefully simplified zone select too
+
+2004-05-11 04:22 ivan
+
+ * httemplate/edit/svc_www.cgi: need to pull in $conf
+
+2004-05-11 04:19 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/svc_www.cgi: one reasonable
+ default and one kludge, to improve webhosting UI
+
+2004-05-11 02:50 ivan
+
+ * FS/FS/part_export/www_shellcommands.pm: fix commands
+
+2004-05-10 17:46 ivan
+
+ * httemplate/: index.html, search/svc_www.cgi: vary basic virtual
+ host browse
+
+2004-05-10 16:16 ivan
+
+ * httemplate/docs/upgrade10.html: fix sequences in upgrade docs?
+
+2004-05-10 06:46 ivan
+
+ * FS/FS/part_export/shellcommands_withdomain.pm: fix ISPMan
+ password changing command
+
+2004-05-10 06:17 ivan
+
+ * FS/FS/part_export/shellcommands.pm: fall back to password
+ changing in the case of blank suspension/unsuspension commands,
+ like some exports
+
+2004-05-10 04:10 ivan
+
+ * FS/FS/part_export/postfix.pm, bin/postfix.export: make postfix
+ export commands configrable
+
+2004-05-10 03:01 ivan
+
+ * bin/sendmail.import: properly nested greps
+
+2004-05-10 02:59 ivan
+
+ * bin/sendmail.import: allow for multiple svc_acct svcparts
+
+2004-05-10 02:40 ivan
+
+ * bin/sendmail.import: 5.005!
+
+2004-05-10 02:38 ivan
+
+ * bin/sendmail.import: ach 5.005
+
+2004-05-10 01:38 ivan
+
+ * CREDITS: rt and sql-ledger
+
+2004-05-08 00:46 ivan
+
+ * FS/FS/svc_acct.pm: default finger to first+last
+
+2004-05-06 15:37 ivan
+
+ * httemplate/edit/svc_www.cgi: brainfart
+
+2004-05-06 15:34 ivan
+
+ * httemplate/edit/svc_www.cgi: tyop
+
+2004-05-06 15:29 ivan
+
+ * FS/FS/part_export/apache.pm, bin/apache.export: add option to
+ change the restart command in apache exports
+
+2004-05-06 15:29 ivan
+
+ * FS/FS/svc_acct.pm: protect properly against deleting users linked
+ to virtual web sites
+
+2004-05-06 15:18 ivan
+
+ * httemplate/edit/svc_www.cgi: show service name and
+ fully-qualified address on service add
+
+2004-05-04 11:44 ivan
+
+ * FS/FS/queue.pm: don't truncate job args for display
+
+2004-05-03 08:40 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: 1. order_pkg accepts svcpart +
+ (svc_external: id, title / svc_acct: domain)
+
+2004-05-03 07:32 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/shellcommands.pm,
+ part_export/shellcommands_withdomain.pm: make RADIUS groups
+ available to shellcommands exports
+
+2004-05-01 15:49 ivan
+
+ * httemplate/search/: cust_bill.html, elements/search.html: don't
+ display links to missing customers
+
+2004-05-01 14:40 ivan
+
+ * httemplate/search/cust_bill.html: I'm slow this morning
+
+2004-05-01 14:38 ivan
+
+ * httemplate/search/cust_bill.html: oops tyop
+
+2004-05-01 14:05 ivan
+
+ * httemplate/search/cust_bill.html: handle missing customer records
+ without erroring out
+
+2004-05-01 03:43 ivan
+
+ * install/redhat/9/INSTALL: update for some new atrpms package
+ versions
+
+2004-04-30 20:54 ivan
+
+ * htetc/global.asa: very weird 5.005 problem
+
+2004-04-30 14:58 ivan
+
+ * FS/FS/Record.pm: accept empty zips for non-US countries...
+
+2004-04-30 13:22 ivan
+
+ * FS/FS/cust_main.pm: eliminate spurious "multiple records in
+ scalar search" warning
+
+2004-04-30 12:08 ivan
+
+ * httemplate/index.html: 15 day open invoice reports for qis
+
+2004-04-29 06:08 ivan
+
+ * fs_signup/FS-SignupClient/cgi/: map.gif, stateselect.html:
+ imagemap for state selection
+
+2004-04-29 02:24 ivan
+
+ * install/5.005/Net-Whois-Raw/lib/Net/Whois/Raw/Data.pm: 5.005 fix
+
+2004-04-29 02:21 ivan
+
+ * install/5.005/: DBIx-DBSchema-0.23-5.005kludge/Changes,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema.pm,
+ DBIx-DBSchema-0.23-5.005kludge/MANIFEST,
+ DBIx-DBSchema-0.23-5.005kludge/MANIFEST.SKIP,
+ DBIx-DBSchema-0.23-5.005kludge/Makefile.PL,
+ DBIx-DBSchema-0.23-5.005kludge/README,
+ DBIx-DBSchema-0.23-5.005kludge/TODO,
+ DBD-Pg-1.22-fixvercmp/Changes, DBD-Pg-1.22-fixvercmp/MANIFEST,
+ DBD-Pg-1.22-fixvercmp/Makefile.PL, DBD-Pg-1.22-fixvercmp/Pg.h,
+ DBD-Pg-1.22-fixvercmp/Pg.pm, DBD-Pg-1.22-fixvercmp/Pg.xs,
+ DBD-Pg-1.22-fixvercmp/README, DBD-Pg-1.22-fixvercmp/README.win32,
+ DBD-Pg-1.22-fixvercmp/dbd-pg.pod, DBD-Pg-1.22-fixvercmp/dbdimp.c,
+ DBD-Pg-1.22-fixvercmp/dbdimp.h,
+ DBD-Pg-1.22-fixvercmp/eg/ApacheDBI.pl,
+ DBD-Pg-1.22-fixvercmp/eg/lotest.pl,
+ DBD-Pg-1.22-fixvercmp/eg/notify_test.patch,
+ DBD-Pg-1.22-fixvercmp/t/00basic.t,
+ DBD-Pg-1.22-fixvercmp/t/01connect.t,
+ DBD-Pg-1.22-fixvercmp/t/01constants.t,
+ DBD-Pg-1.22-fixvercmp/t/01setup.t,
+ DBD-Pg-1.22-fixvercmp/t/02prepare.t,
+ DBD-Pg-1.22-fixvercmp/t/03bind.t,
+ DBD-Pg-1.22-fixvercmp/t/04execute.t,
+ DBD-Pg-1.22-fixvercmp/t/05fetch.t,
+ DBD-Pg-1.22-fixvercmp/t/06disconnect.t,
+ DBD-Pg-1.22-fixvercmp/t/07reuse.t,
+ DBD-Pg-1.22-fixvercmp/t/08txn.t,
+ DBD-Pg-1.22-fixvercmp/t/09autocommit.t,
+ DBD-Pg-1.22-fixvercmp/t/11quoting.t,
+ DBD-Pg-1.22-fixvercmp/t/12placeholders.t,
+ DBD-Pg-1.22-fixvercmp/t/13pgtype.t,
+ DBD-Pg-1.22-fixvercmp/t/15funct.t,
+ DBD-Pg-1.22-fixvercmp/t/99cleanup.t,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Handler.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/RDBMS.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Request.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Util.pm,
+ DBIx-DBSchema-0.23-5.005kludge/t/load-mysql.t,
+ DBIx-DBSchema-0.23-5.005kludge/t/load-pg.t,
+ DBIx-DBSchema-0.23-5.005kludge/t/load.t,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/Handler/Prompt.pm,
+ DBD-Pg-1.22-fixvercmp/t/lib/App/Info/RDBMS/PostgreSQL.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/Column.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/Table.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup/Index.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/ColGroup/Unique.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/Pg.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/Sybase.pm,
+ DBIx-DBSchema-0.23-5.005kludge/DBSchema/DBD/mysql.pm: adding
+ DBD::Pg and DBIx::DBSchema for 5.005. argh freebsd and solaris!
+
+2004-04-23 06:15 ivan
+
+ * FS/MANIFEST, FS/bin/freeside-cc-receipts-report,
+ FS/bin/freeside-credit-report, httemplate/index.html,
+ httemplate/search/report_cc.cgi,
+ httemplate/search/report_cc.html,
+ httemplate/search/report_credit.cgi,
+ httemplate/search/report_credit.html: add link to new credit
+ report on main menu, remove old obsolete shell-out reports
+
+2004-04-23 05:50 ivan
+
+ * Makefile, htetc/global.asa: fix up includes with Apache::ASP
+
+2004-04-23 05:19 ivan
+
+ * FS/FS/cust_credit.pm, FS/FS/Report/Table/Monthly.pm,
+ httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_credit.html,
+ httemplate/search/cust_pay.cgi,
+ httemplate/search/report_cust_credit.html,
+ httemplate/search/elements/search.html: credit report, add some
+ links to sales/credits/receipts summary, move payment search to
+ template
+
+2004-04-22 19:32 ivan
+
+ * httemplate/: search/cust_bill.html, search/sql.html, index.html,
+ search/elements/search.html: working templated invoice search!
+
+2004-04-22 00:38 ivan
+
+ * httemplate/elements/pager.html: silly pager fix
+
+2004-04-22 00:27 ivan
+
+ * httemplate/docs/: install.html, upgrade10.html: minor doc updates
+
+2004-04-22 00:07 ivan
+
+ * httemplate/search/report_cust_credit.html: initial copy from
+ report_cust_pay.html
+
+2004-04-21 13:52 ivan
+
+ * FS/FS/cust_bill.pm: as an invoice event, emailing/printing
+ problems should be fatal and trigger retry
+
+2004-04-20 18:49 ivan
+
+ * FS/FS/cust_main.pm: respect country default for batch import
+
+2004-04-20 13:24 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: silly bug noticed by matthewd
+
+2004-04-19 18:23 ivan
+
+ * FS/FS/cust_main.pm: accept expiration dates in the same format
+ they are output...
+
+2004-04-19 17:58 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_refund.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ httemplate/view/cust_main.cgi: add methods for masking credit
+ cards, add payment info modification to self-service
+
+2004-04-13 20:20 ivan
+
+ * install/fedora/fc1/: INSTALL, sources.list: adding preliminary
+ install script for fedora core 1
+
+2004-04-13 18:00 ivan
+
+ * rt/FREESIDE_MODIFIED: keeping track of what's been changed to
+ make life easier when importing new upstream versions
+
+2004-04-13 17:48 khoff
+
+ * rt/lib/RT/URI/freeside.pm: Freeside's URI handler for RT3.
+
+2004-04-13 15:30 ivan
+
+ * FS/FS/svc_domain.pm: remove dependancy on Net::Whois that wasn't
+ being used anyway
+
+2004-04-13 13:01 ivan
+
+ * FS/t/part_export-communigate_pro.t: adding forgotten test
+
+2004-04-13 11:27 ivan
+
+ * Makefile: adding comments for fedora
+
+2004-04-10 18:50 ivan
+
+ * httemplate/search/: report_prepaid_income.cgi,
+ report_prepaid_income.html: update unearned revenue report based
+ on feedback from kevin
+
+2004-04-09 15:35 ivan
+
+ * Makefile: thank goodness its friday
+
+2004-04-09 15:34 ivan
+
+ * Makefile: really properly disable RT where not using
+
+2004-04-09 15:33 ivan
+
+ * Makefile: properly disable RT where not using
+
+2004-04-09 15:29 ivan
+
+ * fs_passwd/fs_passwd.cgi: oops, this one too
+
+2004-04-09 15:28 ivan
+
+ * fs_passwd/fs_passwd.html: fs_passwd.cgi
+
+2004-04-08 05:37 ivan
+
+ * Makefile: fix psql command line options for older pg
+
+2004-04-08 05:23 ivan
+
+ * Makefile: fix quotes
+
+2004-04-08 05:07 ivan
+
+ * Makefile: don't enable by default
+
+2004-04-08 05:05 ivan
+
+ * rt/sbin/: rt-setup-database, rt-setup-database.in: remove
+ accidentally doubled lines in usage inst
+
+2004-04-08 05:00 ivan
+
+ * Makefile, htetc/handler.pl, rt/FREESIDE_MODIFIED,
+ rt/etc/RT_SiteConfig.pm, rt/sbin/rt-setup-database,
+ rt/sbin/rt-setup-database.in: beginning of RT integration
+
+2004-04-07 22:53 ivan
+
+ * fs_selfservice/FS-SelfService/Makefile.PL: comment out xmlrpc
+ server until it is ready
+
+2004-04-07 06:12 ivan
+
+ * FS/bin/freeside-reexport: oops, update the usage too
+
+2004-04-07 06:11 ivan
+
+ * FS/bin/freeside-reexport: added options to select username,
+ svcnum, svcpart
+
+2004-04-07 04:39 ivan
+
+ * FS/FS/: Conf.pm, domain_record.pm: automatically update
+ reverse-ARPA records (Bug#462) / recognize SOA records with the
+ fqdn as well as @
+
+2004-04-07 04:04 ivan
+
+ * httemplate/view/svc_domain.cgi: javascript confirm when slaving a
+ domain
+
+2004-04-07 02:08 ivan
+
+ * install/5.005/Net-Whois-Raw/: COPYRIGHT, Changes, MANIFEST,
+ META.yml, Makefile.PL, README, pwhois, t/01.t,
+ lib/Net/Whois/Raw.pm, lib/Net/Whois/Raw/Data.pm: Initial revision
+
+2004-04-07 01:34 ivan
+
+ * FS/FS/part_export.pm: argh, the glob itself is tainted under
+ 5.005
+
+2004-04-07 01:07 ivan
+
+ * FS/FS/part_export.pm: make -T happy (under old perl?)
+
+2004-04-05 19:03 ivan
+
+ * FS/FS/part_export/www_shellcommands.pm: update ISPMan commands
+
+2004-04-05 07:05 ivan
+
+ * httemplate/misc/link.cgi, FS/FS/Conf.pm,
+ httemplate/misc/process/link.cgi: add a domain pulldown to
+ svc_acct linking, closes: Bug#277 / prevent "stealing" services
+ with link unless you set legacy_link-steal config option, closes:
+ Bug#321
+
+2004-04-05 04:55 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/view/cust_main.cgi: apply some
+ heuristics to transfer ordering: primaries first, then sorted by
+ quantity
+
+2004-04-05 02:08 ivan
+
+ * htetc/global.asa, htetc/handler.pl, httemplate/docs/install.html,
+ httemplate/docs/upgrade-1.4.2.html, httemplate/misc/whois.cgi,
+ httemplate/view/svc_domain.cgi: add whois functionality
+ internally instead of linking to geektools
+
+2004-04-04 15:20 ivan
+
+ * FS/FS/: Conf.pm, cust_pkg.pm: add cust_pkg-change_svcpart option
+ to optionally allow non-matching svcparts to be moved during
+ package changes, closes: Bug#667
+
+2004-04-04 15:14 ivan
+
+ * httemplate/view/cust_main.cgi: comment out extraneous warning
+
+2004-04-02 16:45 ivan
+
+ * httemplate/search/cust_bill.cgi: UI: stop making things small for
+ no reason
+
+2004-04-02 05:44 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/view/cust_bill-pdf.cgi: remove Pragma:no-cache header,
+ and set Content-Length and Cache-Control for viewing .pdf
+ invoices with IE over SSL.
+ http://support.microsoft.com/default.aspx?scid=kb;en-us;323308
+
+2004-04-02 03:23 ivan
+
+ * httemplate/view/: cust_bill-pdf.cgi, cust_bill.cgi: add a fake
+ .pdf extension to placate some versions of IE. yay IE.
+
+2004-04-01 18:09 ivan
+
+ * bin/bind.export, FS/FS/part_export/bind.pm: add option to set
+ (r)ndc command
+
+2004-04-01 06:50 ivan
+
+ * FS/FS/part_export/www_shellcommands.pm: fix paths to ispman
+ commands
+
+2004-04-01 03:14 ivan
+
+ * httemplate/browse/part_referral.cgi: remove extraneous html
+
+2004-04-01 03:09 ivan
+
+ * httemplate/browse/part_referral.cgi: oops!
+
+2004-04-01 02:56 ivan
+
+ * httemplate/browse/part_referral.cgi: add a yesterday column and a
+ total row, closes: Bug#797
+
+2004-03-31 16:44 ivan
+
+ * FS/: FS/cust_main_county.pm, bin/freeside-setup: get
+ sub-countries from Locale::SubCountry now
+
+2004-03-30 09:13 ivan
+
+ * httemplate/docs/upgrade10.html: little more explanation about
+ editing Pg dumps
+
+2004-03-30 08:43 ivan
+
+ * FS/FS/cust_main.pm: mutex the bill and collect functions
+ per-customer
+
+2004-03-30 01:20 ivan
+
+ * bin/bind.import: add -s and -c flags, add ipv6 default zones to
+ list of ignored zones, add nameservice records to existing
+ domains, update for API change inDNS::ZoneParse 0.84
+
+2004-03-29 13:49 ivan
+
+ * FS/FS/part_export/shellcommands.pm: freebsd pw(1) fixed in 4.10
+ also
+
+2004-03-28 22:03 ivan
+
+ * FS/FS/part_export.pm: fix export_info sub to return an empty
+ hashref instead of undef
+
+2004-03-26 17:05 khoff
+
+ * FS/FS/: Conf.pm, cust_pkg.pm, svc_acct.pm, svc_domain.pm: Cancel
+ services in a particular order to get around certain
+ inter-service dependancies
+
+2004-03-25 20:54 ivan
+
+ * fs_selfservice/FS-SelfService/Makefile.PL: depend on Storable
+ 2.09
+
+2004-03-25 20:46 ivan
+
+ * FS/FS/part_export/router.pm: don't depend on Net::Telnet unless
+ necessary
+
+2004-03-25 03:00 ivan
+
+ * FS/FS/part_export/: domain_shellcommands.pm,
+ www_shellcommands.pm: typo from refactoring
+
+2004-03-25 00:55 ivan
+
+ * FS/FS/part_export/: domain_shellcommands.pm,
+ forward_shellcommands.pm, shellcommands.pm,
+ shellcommands_withdomain.pm, www_shellcommands.pm: first pass at
+ ISPMan integration
+
+2004-03-24 22:42 ivan
+
+ * FS/FS/part_export/shellcommands.pm: freebsd fix will be in 5.3
+ and later only so far, still waiting to hear about 4.10
+
+2004-03-24 07:38 ivan
+
+ * httemplate/edit/part_export.cgi: catch misconfigured exports
+
+2004-03-24 06:28 ivan
+
+ * FS/FS/: part_export.pm, part_export/apache.pm,
+ part_export/bind.pm, part_export/bind_slave.pm,
+ part_export/bsdshell.pm, part_export/communigate_pro.pm,
+ part_export/communigate_pro_singledomain.pm, part_export/cp.pm,
+ part_export/cyrus.pm, part_export/domain_shellcommands.pm,
+ part_export/forward_shellcommands.pm, part_export/http.pm,
+ part_export/infostreet.pm, part_export/ldap.pm,
+ part_export/postfix.pm, part_export/shellcommands.pm,
+ part_export/shellcommands_withdomain.pm, part_export/sqlmail.pm,
+ part_export/sqlradius.pm, part_export/sqlradius_withdomain.pm,
+ part_export/sysvshell.pm, part_export/textradius.pm,
+ part_export/vpopmail.pm, part_export/www_shellcommands.pm: move
+ export info to the modules themselves
+
+2004-03-24 06:23 ivan
+
+ * FS/FS/part_export/router.pm: move export info to the modules
+ themselves
+
+2004-03-24 06:21 ivan
+
+ * FS/: MANIFEST, FS/part_export/passwdfile.pm,
+ t/part_export-passwdfile.t: adding passwdfile export base class
+
+2004-03-24 06:17 ivan
+
+ * eg/export_template.pm: update example export for the new world of
+ export data in themodule files
+
+2004-03-24 01:35 ivan
+
+ * FS/: MANIFEST, t/part_export-communigate_pro_singledomain.t,
+ t/part_export-postfix.t, t/part_export-router.t: add missing
+ compile tests
+
+2004-03-23 11:57 ivan
+
+ * httemplate/view/: cust_main.cgi: small UI fix for unapplied
+ partial credits
+
+2004-03-22 19:36 ivan
+
+ * htetc/global.asa: make Apache::ASP includes work as expected
+
+2004-03-22 19:31 ivan
+
+ * htetc/global.asa: includes fix
+
+2004-03-22 19:29 ivan
+
+ * htetc/global.asa, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: includes with Apache::ASP
+
+2004-03-22 16:06 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/ClientAPI/MyAccount.pm,
+ htetc/global.asa, htetc/handler.pl,
+ httemplate/elements/small_custview.html,
+ httemplate/misc/payment.cgi, httemplate/misc/process/payment.cgi,
+ httemplate/view/cust_main.cgi: one-time credit card and ACH
+ payments (like self-service) closes: Bug#648
+
+2004-03-22 16:06 ivan
+
+ * httemplate/search/report_receivables.cgi: fix sorting of NULL
+ companies differently than empty companies
+
+2004-03-22 11:02 ivan
+
+ * httemplate/elements/header.html, FS/FS/CGI.pm: consistant title
+ size of 6
+
+2004-03-22 09:13 ivan
+
+ * httemplate/: docs/ach.html, edit/cust_main.cgi, images/ach.png:
+ add ACH help graphic
+
+2004-03-22 07:18 ivan
+
+ * FS/FS/CGI.pm: tone down the titles
+
+2004-03-22 07:04 ivan
+
+ * httemplate/edit/cust_main.cgi: s/routing code/routing number/
+
+2004-03-22 04:50 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/make_payment.html: credit card
+ expiration selection now -> 15 years instead of hardcoded
+
+2004-03-22 03:05 ivan
+
+ * httemplate/: edit/process/REAL_cust_pkg.cgi,
+ edit/process/quick-cust_pkg.cgi, misc/cancel-unaudited.cgi,
+ misc/unprovision.cgi, misc/process/link.cgi,
+ search/cust_main.cgi, search/cust_pkg.cgi, view/cust_main.cgi,
+ view/svc_acct.cgi, view/svc_broadband.cgi, view/svc_domain.cgi,
+ view/svc_external.cgi, view/svc_forward.cgi, view/svc_www.cgi:
+ remove everything that links to package view also, closes:
+ Bug#569
+
+2004-03-22 02:36 ivan
+
+ * httemplate/view/cust_main.cgi: further small UI tweaks
+
+2004-03-22 02:16 ivan
+
+ * httemplate/: misc/expire_pkg.cgi, misc/process/expire_pkg.cgi,
+ view/cust_main.cgi: yay! remove package view entirely (closes:
+ Bug#569)
+
+2004-03-21 18:59 ivan
+
+ * httemplate/view/cust_main.cgi: much easier to understand listing
+ of credits/payments that get split up, closes: Bug#773, 762
+
+2004-03-19 04:36 ivan
+
+ * FS/FS/ClientAPI/passwd.pm: use FS::svc_domain explicitly
+
+2004-03-18 14:35 ivan
+
+ * FS/FS/part_export/shellcommands.pm: quote already-crypted
+ passwords to prevent variable substitution
+
+2004-03-18 14:32 ivan
+
+ * FS/FS/part_export/shellcommands.pm: don't re-encrypt password on
+ replace also
+
+2004-03-18 14:00 ivan
+
+ * bin/shadow.reimport: add -b option
+
+2004-03-18 12:58 ivan
+
+ * FS/FS/part_export/shellcommands.pm: don't re-crypt encrypted
+ passwords
+
+2004-03-17 17:46 ivan
+
+ * FS/bin/freeside-selfservice-server,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ require Storable minimum 2.09
+
+2004-03-17 15:16 ivan
+
+ * FS/FS/svc_acct.pm: fixup password checking to understand
+ old-style *SUSPENDED* accounts and not to allow access for * ! !!
+ passwords
+
+2004-03-17 15:08 ivan
+
+ * bin/shadow.reimport: skip root user and anyone with *LK* or NP
+ accounts
+
+2004-03-17 14:55 ivan
+
+ * bin/shadow.reimport: fix multiple svcparts
+
+2004-03-17 14:53 ivan
+
+ * bin/shadow.reimport: allow multiple svcparts
+
+2004-03-17 14:49 ivan
+
+ * bin/shadow.reimport: re-enable prompting
+
+2004-03-17 14:45 ivan
+
+ * bin/shadow.reimport: add -d and -r options
+
+2004-03-17 13:47 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm, FS/FS/svc_acct.pm,
+ FS/FS/ClientAPI/passwd.pm, httemplate/docs/install.html,
+ httemplate/docs/upgrade-1.4.2.html: proper self-service login
+ supporting plaintext, crypt and MD5 passwords
+
+2004-03-16 12:41 ivan
+
+ * Makefile: rt-setup-database, not rt-initialize-database
+
+2004-03-15 23:06 ivan
+
+ * Makefile, rt/config.layout.in: masonstatedir can't be configured
+ form ./configure either, must use layout
+
+2004-03-15 23:04 ivan
+
+ * Makefile: and finally, run the ./configure
+
+2004-03-15 23:03 ivan
+
+ * Makefile: use a proper delimter
+
+2004-03-15 23:00 ivan
+
+ * Makefile: transposition
+
+2004-03-15 22:59 ivan
+
+ * Makefile: autogenerate rt/config.layout file
+
+2004-03-15 22:58 ivan
+
+ * rt/: FREESIDE_MODIFIED, config.layout, config.layout.in:
+ config.layout needs to be generated
+
+2004-03-15 22:45 ivan
+
+ * Makefile: initial RT targets
+
+2004-03-15 22:43 ivan
+
+ * rt/: FREESIDE_MODIFIED, sbin/rt-setup-database: initial
+ (hopefully rather unobtrusive) patch
+
+2004-03-15 20:36 ivan
+
+ * FS/FS/cust_svc.pm: recognize DBD::mysqlPP
+
+2004-03-15 16:34 ivan
+
+ * Makefile: dont want to error out here
+
+2004-03-15 11:22 ivan
+
+ * fs_signup/FS-SignupClient/: MANIFEST, Makefile.PL, fs_signupd:
+ signup is now just a wrapper around self-service
+
+2004-03-12 17:27 ivan
+
+ * Makefile: really add the necessary backslashes this time, fix
+ s/// delimteres
+
+2004-03-12 16:53 ivan
+
+ * Makefile: oops
+
+2004-03-12 16:50 ivan
+
+ * Makefile, htetc/handler.pl: automatically set Mason comp_root in
+ Makefile
+
+2004-03-12 16:16 ivan
+
+ * Makefile: fix suse document root
+
+2004-03-12 04:39 ivan
+
+ * FS/FS/Conf.pm, httemplate/misc/unapply-cust_credit.cgi,
+ httemplate/view/cust_main.cgi: add unapplycredits configuration
+ option
+
+2004-03-12 04:11 ivan
+
+ * httemplate/graph/money_time.cgi: fix title
+
+2004-03-12 04:10 ivan
+
+ * httemplate/docs/upgrade10.html: add history tables to field
+ change upgrade instructions, add hints for pre-5.6 perl, add
+ index on cust_pay._date
+
+2004-03-12 02:22 ivan
+
+ * httemplate/index.html: add badly-named new report
+
+2004-03-12 02:19 ivan
+
+ * httemplate/docs/upgrade-1.4.2.html: few more 1.4.2 upgrade hints
+
+2004-03-12 00:56 ivan
+
+ * FS/FS/Report/Table/Monthly.pm: don't run my local expenses kludge
+ by default; horrible performance
+
+2004-03-12 00:17 ivan
+
+ * FS/FS/cust_main.pm: emaildecline-exclude skips any errors that
+ contain the strings now, not just match exactly
+
+2004-03-11 21:58 ivan
+
+ * httemplate/docs/upgrade10.html: document trouble schema changes
+ backported to 1.4.2
+
+2004-03-11 21:49 ivan
+
+ * httemplate/docs/upgrade10.html: remove comment
+
+2004-03-11 13:35 ivan
+
+ * httemplate/docs/upgrade10.html: add info for ancient Pg versions
+
+2004-03-11 13:19 ivan
+
+ * conf/logo.eps: oops, wrong logo
+
+2004-03-11 13:07 ivan
+
+ * conf/: invoice_latex, logo.eps: add typeset logo to conf dir and
+ point invoice_latex at it by default
+
+2004-03-11 00:54 ivan
+
+ * FS/bin/freeside-selfservice-server: turn down logging level
+
+2004-03-10 23:33 ivan
+
+ * fs_passwd/: fs_passwd, fs_passwd.cgi, fs_passwd_server,
+ fs_passwdd: update fs_passwd stuff as wrappers around
+ self-service
+
+2004-03-10 20:17 ivan
+
+ * FS/MANIFEST: incorrect listing in MANIFEST
+
+2004-03-10 19:53 ivan
+
+ * install/redhat/7.3/INSTALL: 1.5 stuff
+
+2004-03-10 18:21 ivan
+
+ * install/suse/9.0/INSTALL: suse install script
+
+2004-03-10 18:03 ivan
+
+ * rt/lib/: RT/I18N/it.po, RT/Interface/REST.pm,
+ t/data/crashes-file-based-parser, t/data/multipart-report,
+ t/data/notes-uuencoded: Initial revision
+
+2004-03-10 17:59 ivan
+
+ * rt/: README.Oracle, UPGRADING, bin/rt.in,
+ docs/rt3-schema-relationships.dot, etc/acl.Informix,
+ etc/drop.Informix, etc/drop.Oracle, etc/schema.Informix,
+ html/Admin/Elements/SelectStage, html/Elements/SelectLang,
+ html/REST/1.0/autohandler, html/REST/1.0/dhandler,
+ html/REST/1.0/logout, html/REST/1.0/Forms/queue/default,
+ html/REST/1.0/Forms/queue/ns,
+ html/REST/1.0/Forms/ticket/attachments,
+ html/REST/1.0/Forms/ticket/default,
+ html/REST/1.0/Forms/ticket/history,
+ html/REST/1.0/Forms/ticket/links,
+ html/REST/1.0/Forms/user/default, html/REST/1.0/Forms/user/ns,
+ html/REST/1.0/search/dhandler, html/REST/1.0/search/ticket,
+ html/REST/1.0/ticket/comment, html/REST/1.0/ticket/link,
+ html/REST/1.0/ticket/merge, lib/RT/StyleGuide.pod: Initial
+ revision
+
+2004-03-10 17:05 ivan
+
+ * Makefile: update for suse
+
+2004-03-10 14:27 khoff
+
+ * httemplate/edit/svc_broadband.cgi: Excluded virtual fields
+ weren't being properly masked on errors. The router/block select
+ box wasn't being generated on errors.
+
+2004-03-10 13:47 ivan
+
+ * install/suse/: INSTALL, 9.0/INSTALL: move to versioned dir
+
+2004-03-10 13:44 ivan
+
+ * install/: redhat/9/INSTALL, suse/INSTALL: adding preliminary suse
+ install script
+
+2004-03-10 11:06 khoff
+
+ * httemplate/browse/router.cgi: Added hide/show customer router
+ link.
+
+2004-03-09 18:37 khoff
+
+ * httemplate/browse/router.cgi: UI cleanup.
+
+2004-03-05 16:57 ivan
+
+ * httemplate/docs/upgrade10.html: doc
+
+2004-03-05 06:34 ivan
+
+ * FS/MANIFEST, FS/FS/Report.pm, FS/FS/Report/Table.pm,
+ FS/FS/Report/Table/Monthly.pm, FS/t/Report-Table-Monthly.t,
+ FS/t/Report-Table.t, FS/t/Report.t, htetc/global.asa,
+ htetc/handler.pl, httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi: beginning of OO reporting
+ interface, create acadia-requested crosstab reports
+
+2004-03-04 21:59 ivan
+
+ * FS/bin/freeside-daily: fix -v
+
+2004-03-03 08:32 ivan
+
+ * bin/create-fetchmailrc: fix for case where no .fetchmailrc should
+ be create and fetchmail should not be run
+
+2004-03-03 05:42 ivan
+
+ * FS/FS/: cust_main.pm, cust_pkg.pm, queue.pm, svc_Common.pm,
+ svc_acct.pm, svc_broadband.pm, svc_domain.pm, svc_external.pm,
+ svc_forward.pm, svc_www.pm, ClientAPI/Signup.pm: fix welcome
+ emails being sent to signup server declined accounts, closes:
+ Bug#743
+
+2004-03-02 22:20 ivan
+
+ * httemplate/edit/svc_forward.cgi: grey out inactive text boxes as
+ well as disable them (IE doesn't grey out disabled text dialogs)
+
+2004-02-28 15:06 ivan
+
+ * httemplate/docs/ieak.html: for now
+
+2004-02-28 14:57 ivan
+
+ * Makefile: s/cleanwhisker/pouncequick/
+
+2004-02-28 14:49 ivan
+
+ * FS/t/acct_snarf.t: adding
+
+2004-02-28 14:48 ivan
+
+ * FS/FS/cust_pkg.pm: minor fixes
+
+2004-02-28 14:47 ivan
+
+ * CREDITS: credit where the typeset invoices came from!
+
+2004-02-28 14:43 ivan
+
+ * htetc/global.asa, httemplate/docs/install.html,
+ httemplate/docs/upgrade-1.4.2.html: Apache::ASP 2.55 required
+
+2004-02-28 14:40 ivan
+
+ * httemplate/edit/process/cust_main_county-collapse.cgi: style
+
+2004-02-28 14:40 ivan
+
+ * httemplate/edit/process/cust_main_county.cgi: new setuptax and
+ recurtax fields
+
+2004-02-28 14:36 ivan
+
+ * install/redhat/7.3/INSTALL: update
+
+2004-02-28 14:26 ivan
+
+ * FS/FS/Record.pm: depend on DBIx::DBSchema 0.23 and thus DBD::Pg
+ 1.32, finally closes Bug#639
+
+2004-02-27 13:21 khoff
+
+ * FS/FS/svc_broadband.pm: When next_free_addr returned undef, we
+ were trying to call addr on an undefined object. That's not
+ good.
+
+2004-02-26 11:21 ivan
+
+ * httemplate/view/svc_forward.cgi: correct cancel link
+ s/account/mail forward/
+
+2004-02-25 20:01 ivan
+
+ * httemplate/edit/svc_forward.cgi: double quotes are not ASP
+
+2004-02-25 19:32 ivan
+
+ * FS/FS/Record.pm: allow replace with no arguments
+
+2004-02-25 02:37 ivan
+
+ * httemplate/edit/svc_forward.cgi, FS/FS/cust_svc.pm: fix up
+ forward editing for new svc_forward.src field
+
+2004-02-24 21:11 ivan
+
+ * FS/FS/CGI.pm: kludge around it completely
+
+2004-02-24 21:04 ivan
+
+ * FS/FS/CGI.pm: third time's the charm
+
+2004-02-24 21:00 ivan
+
+ * FS/FS/CGI.pm: oops, not the right way to blank them
+
+2004-02-24 20:56 ivan
+
+ * FS/FS/CGI.pm: query strings get passed through sometimes?
+
+2004-02-24 19:50 ivan
+
+ * httemplate/docs/install.html: formatting
+
+2004-02-23 00:12 ivan
+
+ * FS/FS/: svc_acct.pm, part_export.pm, svc_Common.pm: implement
+ fallback suspension code
+
+2004-02-13 10:58 ivan
+
+ * bin/postfix.export: postfix export
+
+2004-02-13 06:04 ivan
+
+ * FS/FS/part_export.pm, bin/postfix.export: add postfix export
+
+2004-02-13 05:53 ivan
+
+ * httemplate/edit/part_svc.cgi: typo
+
+2004-02-13 04:27 ivan
+
+ * FS/FS/part_export/postfix.pm: adding postfix export
+
+2004-02-13 03:47 ivan
+
+ * bin/sendmail.import: it lives!
+
+2004-02-13 03:44 ivan
+
+ * httemplate/docs/upgrade10.html: workaround for older Pg
+
+2004-02-13 03:28 ivan
+
+ * httemplate/: index.html, search/svc_forward.cgi,
+ view/svc_forward.cgi: add mail alias browse to main menu and fix
+ mail alias view to recognize new schema also
+
+2004-02-13 02:57 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/upgrade10.html: continue
+ adding svc_forward.src: make svc_forward.srcsvc nullable
+
+2004-02-13 02:35 ivan
+
+ * FS/FS/svc_forward.pm, FS/bin/freeside-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade10.html: add
+ svc_forward.src
+
+2004-02-13 00:02 ivan
+
+ * bin/sendmail.import: initial import
+
+2004-02-12 20:01 ivan
+
+ * FS/FS/part_export/: router.pm, domain_shellcommands.pm,
+ forward_shellcommands.pm, shellcommands.pm, www_shellcommands.pm:
+ depend on Net::SSH 0.08 for non-blocking STDERR read
+
+2004-02-12 14:40 ivan
+
+ * install/redhat/9/INSTALL: doc
+
+2004-02-12 02:44 ivan
+
+ * bin/bind.import: fix usage msg
+
+2004-02-11 22:31 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/misc/email-invoice.cgi,
+ httemplate/misc/print-invoice.cgi, httemplate/view/cust_bill.cgi:
+ re-email invoice, closes: bug#526 and have print and email
+ invoice links redirect back to top of customer view page instead
+ of #history tag
+
+2004-02-07 14:13 ivan
+
+ * FS/FS/part_export.pm: add link to FreeBSD patch for pw(1) problem
+
+2004-02-07 00:24 ivan
+
+ * FS/FS/: cust_svc.pm, part_export.pm: add ignore_accounting flag
+ to sqlradius and sqlradius_withdomain exports
+
+2004-02-05 17:00 ivan
+
+ * FS/FS/Conf.pm: add "Net 0" invoice_default_terms
+
+2004-02-02 16:19 ivan
+
+ * bin/shadow.reimport: adding shadow.reimport
+
+2004-02-01 16:23 ivan
+
+ * install/redhat/9/INSTALL: add 1.5 dependancies
+
+2004-02-01 13:07 ivan
+
+ * install/redhat/9/INSTALL: add addl dependancies, should work now?
+
+2004-02-01 13:05 ivan
+
+ * install/redhat/9/INSTALL: rar rar
+
+2004-02-01 13:00 ivan
+
+ * install/redhat/9/INSTALL: rar
+
+2004-02-01 01:43 ivan
+
+ * install/debian/3.0/INSTALL: add libcache-cache-perl
+
+2004-02-01 01:29 ivan
+
+ * Makefile: use install to make all components of FREESIDE_CONF dir
+
+2004-02-01 01:23 ivan
+
+ * install/debian/3.0/INSTALL: s/cleanwhisker/pouncequick/
+
+2004-01-30 22:33 ivan
+
+ * FS/FS/part_pkg.pm, FS/FS/pkg_svc.pm,
+ httemplate/browse/part_pkg.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi, FS/bin/freeside-setup,
+ htetc/global.asa, htetc/handler.pl, httemplate/docs/schema.html,
+ httemplate/docs/upgrade-1.4.2.html,
+ httemplate/docs/upgrade10.html: add pkg_svc.primary_svc flag to
+ enable an explicit first package flag
+
+2004-01-30 22:20 ivan
+
+ * FS/FS/Record.pm: add ut_snumber, fix replacement of records with
+ empty values in non-primary-keyed tables
+
+2004-01-30 12:40 ivan
+
+ * httemplate/docs/upgrade-1.4.2.html: not appropriate
+
+2004-01-29 19:58 ivan
+
+ * FS/FS/part_export.pm: add default freebsd and linux
+ suspension/unsuspension commands, work around FreeBSD pw(1) lack
+ of locking, and don't prepend "*SUSPENDED* " to suspend an
+ account anymore
+
+2004-01-29 19:05 ivan
+
+ * FS/FS/svc_acct.pm: don't prepend *SUSPENDED* to passwords to
+ suspend an account
+
+2004-01-29 17:27 ivan
+
+ * Makefile: multiple self-service machines aren't enclosed in
+ quotes
+
+2004-01-29 17:10 ivan
+
+ * Makefile, FS/FS/ClientAPI/MyAccount.pm,
+ FS/bin/freeside-selfservice-server, init.d/freeside-init: add
+ support for running selfservice server against multiple machines
+
+2004-01-27 17:45 ivan
+
+ * httemplate/search/svc_acct.cgi: fix link from service definition
+ browse to services
+
+2004-01-27 17:39 ivan
+
+ * httemplate/: index.html, browse/part_svc.cgi,
+ search/svc_acct.cgi, search/svc_domain.cgi: add service
+ definition browse by number of active services
+
+2004-01-23 03:20 ivan
+
+ * httemplate/: index.html, search/report_prepaid_income.cgi,
+ search/report_prepaid_income.html: add prepaid income to main
+ menu and allow arbitrary dates
+
+2004-01-23 01:04 ivan
+
+ * httemplate/search/report_prepaid_income.cgi: tidy up look
+
+2004-01-23 00:58 ivan
+
+ * httemplate/search/report_prepaid_income.cgi: oops
+
+2004-01-23 00:55 ivan
+
+ * httemplate/search/report_prepaid_income.cgi: first try at prepaid
+ income report
+
+2004-01-22 19:22 ivan
+
+ * FS/FS/cust_bill.pm: undo debugging change
+
+2004-01-22 19:21 ivan
+
+ * FS/FS/cust_bill.pm: consolidate large numbers of accounts to
+ avoid gigantic line items
+
+2004-01-22 19:01 ivan
+
+ * httemplate/edit/cust_main.cgi: and the same for ship_
+
+2004-01-22 18:53 ivan
+
+ * httemplate/edit/cust_main.cgi: fix state default and set min year
+ to this year, patch from <matthewd>, thanks!
+
+2004-01-22 16:49 ivan
+
+ * debian/control: update ideas about package splitup
+
+2004-01-21 16:21 ivan
+
+ * FS/FS/cust_main.pm: fix cancel method
+
+2004-01-21 16:11 ivan
+
+ * httemplate/misc/cust_main-cancel.cgi: report cancellation errors
+ properly
+
+2004-01-21 15:45 ivan
+
+ * httemplate/misc/dump.cgi: fix newline problem in dump
+
+2004-01-21 14:10 ivan
+
+ * FS/FS/cust_bill.pm: clean up all temp files!
+
+2004-01-21 14:00 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, conf/invoice_latex,
+ conf/invoice_latexsmallfooter: fix multi-page typeset invoices
+
+2004-01-20 16:04 ivan
+
+ * httemplate/search/: cust_bill_event.cgi, cust_pay.cgi,
+ cust_pkg.cgi: don't include the _next_ day, just the full ending
+ day
+
+2004-01-20 12:30 ivan
+
+ * httemplate/: index.html, misc/dump.cgi: add database dump from
+ web interface
+
+2004-01-19 15:21 ivan
+
+ * httemplate/docs/upgrade-1.4.2.html: typeset invoice doc update
+
+2004-01-18 13:03 ivan
+
+ * FS/FS/Record.pm: revert bind_param change _again_. passing not
+ as a hashref causes too many other problems. please leave as is.
+ DBD::Pg needs to be fixed. 1.31 is a lost cause.
+
+2004-01-16 13:45 ivan
+
+ * FS/FS/cust_bill.pm: apply variable substitutions in latex notes
+ also
+
+2004-01-12 12:52 ivan
+
+ * httemplate/docs/upgrade10.html: add IPC::ShareLite and
+ Locale::SubCountry
+
+2004-01-12 12:52 ivan
+
+ * httemplate/docs/upgrade-1.4.2.html: add IPC::ShareLite
+
+2004-01-12 12:40 khoff
+
+ * httemplate/edit/part_virtual_field.cgi: Lists are just better
+ sorted.
+
+2004-01-12 12:34 khoff
+
+ * httemplate/browse/part_virtual_field.cgi: $pvf isn't a global.
+
+2004-01-11 16:03 ivan
+
+ * httemplate/view/cust_bill.cgi: only display "view typeset
+ invoice" when there is an invoice_latex template
+
+2004-01-11 15:59 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/view/cust_bill.cgi: typeset
+ invoice view in web UI uses pdf instead of postscript, closes
+ Bug#614
+
+2004-01-11 15:38 ivan
+
+ * httemplate/view/cust_bill-pdf.cgi: fix for pdf
+
+2004-01-11 15:37 ivan
+
+ * httemplate/view/cust_bill-pdf.cgi: adding
+
+2004-01-10 03:32 ivan
+
+ * install/redhat/9/INSTALL: update paths
+
+2004-01-10 03:17 ivan
+
+ * Makefile: workaround stubborn shells globbing [a-z] to include
+ CVS/
+
+2004-01-09 20:19 ivan
+
+ * FS/FS/cust_main.pm: don't require payname for DCHK either
+
+2004-01-09 19:50 ivan
+
+ * httemplate/edit/part_bill_event.cgi: fix UI: displaying "Add" on
+ invoice event edits
+
+2004-01-09 14:46 ivan
+
+ * httemplate/search/report_receivables.cgi: add customer number
+
+2004-01-09 14:39 ivan
+
+ * FS/FS/cust_credit.pm, httemplate/view/cust_main.cgi: credit
+ deletions: need to use Date::Format and FS::Misc qw(send_email)
+ in cust_credit.pm, need a link to delete unapplied credits too
+
+2004-01-09 14:15 ivan
+
+ * FS/FS/Conf.pm: correct tyop
+
+2004-01-09 14:11 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_credit.pm, FS/FS/cust_credit_bill.pm,
+ httemplate/view/cust_main.cgi,
+ httemplate/misc/delete-cust_credit.cgi: add deletecredits config
+ value to enable deletion of credits
+
+2004-01-09 13:09 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: adding system_usernames config
+ value
+
+2004-01-06 22:10 khoff
+
+ * httemplate/edit/part_pkg.cgi: Added billing plan sql_external for
+ billing services in an external sql database.
+
+2004-01-05 12:24 ivan
+
+ * httemplate/index.html: fix other packages by next bill date link
+
+2004-01-03 20:44 ivan
+
+ * fs_signup/FS-SignupClient/Makefile.PL: no more
+ HTTP::Headers::UserAgent!
+
+2004-01-03 19:54 ivan
+
+ * httemplate/docs/signup.html: remove obsolete netscape CCK
+ supportsignup.cgi
+
+ depend on HTTP::BrowserDetect directly instead of via deprecated
+ HTTP::Headers::UserAgent (closes: Bug#578)
+
+2004-01-03 19:52 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: remove obsolete
+ netscape CCK support
+
+ depend on HTTP::BrowserDetect directly instead of via deprecated
+ HTTP::Headers::UserAgent (closes: Bug#578)
+
+2004-01-03 00:42 ivan
+
+ * httemplate/browse/agent.cgi: fix heading colspan when there is no
+ agent.disabled column
+
+2004-01-01 12:40 ivan
+
+ * FS/FS/cust_bill.pm: escape stuff from latex
+
+2003-12-29 22:02 khoff
+
+ * FS/FS/Record.pm: Pass type as scalar instead of a hashref to work
+ around a bug in DBD::Pg version 1.31.
+
+2003-12-27 00:23 ivan
+
+ * httemplate/: index.html, search/cust_pkg.cgi,
+ search/cust_pkg.html, search/cust_pkg_report.cgi: package reports
+ by agent
+
+2003-12-24 10:18 khoff
+
+ * FS/bin/freeside-setup: tyop
+
+2003-12-22 18:36 ivan
+
+ * FS/MANIFEST, FS/FS/part_export.pm, FS/t/svc_broadband.t,
+ FS/t/svc_external.t, htetc/global.asa, htetc/handler.pl,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_external.cgi,
+ httemplate/edit/process/svc_external.cgi,
+ httemplate/view/svc_external.cgi: add svc_external
+
+2003-12-22 17:46 ivan
+
+ * FS/FS.pm, FS/FS/svc_external.pm, FS/bin/freeside-setup,
+ httemplate/docs/upgrade10.html, FS/FS/cust_svc.pm: add
+ svc_external
+
+2003-12-22 17:10 ivan
+
+ * eg/table_template-svc.pm: update svc template for 1.5
+
+2003-12-22 17:06 ivan
+
+ * eg/table_template-svc.pm: fix path to svc_Common in example table
+
+2003-12-22 16:51 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: add edit_info to
+ selfservice API
+
+2003-12-22 16:41 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: allow_negative_charges config
+ option
+
+2003-12-22 13:37 ivan
+
+ * httemplate/browse/cust_pay_batch.cgi: add total cards & amount to
+ pending batch screen
+
+2003-12-22 13:22 ivan
+
+ * FS/FS/cust_main.pm: default to the whole-country tax rate if
+ states aren't defined
+
+2003-12-22 13:18 ivan
+
+ * FS/FS/cust_bill.pm: quiet warning
+
+2003-12-22 13:01 ivan
+
+ * FS/FS/cust_credit.pm: allow credits to be modified at API level
+
+2003-12-22 09:50 ivan
+
+ * FS/FS/cust_main.pm: add cust_credit, cust_pay and cust_refund
+ subs
+
+2003-12-21 15:16 ivan
+
+ * httemplate/browse/agent_type.cgi: work even if there are stray
+ type_pkgs records around
+
+2003-12-21 15:13 ivan
+
+ * FS/FS/Record.pm: cache virtual_fields method results to help
+ performance
+
+2003-12-21 13:12 ivan
+
+ * FS/bin/freeside-addoutsourceuser: add outsourced databases with
+ both addresses by default
+
+2003-12-19 19:47 ivan
+
+ * httemplate/browse/part_referral.cgi: fix inflated advertising
+ source numbers
+
+2003-12-15 00:08 ivan
+
+ * conf/invoice_latex: line up w/window envelopes
+
+2003-12-15 00:07 ivan
+
+ * httemplate/misc/print-invoice.cgi: print_ps returns ths invoice
+ now, do not count on latex printing it, oops
+
+2003-12-14 22:42 ivan
+
+ * FS/FS/: cust_main.pm, cust_bill.pm: fix bug that charged full
+ amounts of all open invoices as soon as balance went positive
+ (only manifests when any cust_bill->owed somehow got to be
+ negative)
+
+2003-12-14 19:41 ivan
+
+ * FS/FS/cust_bill.pm: add _latex_escape sub
+
+2003-12-14 09:53 ivan
+
+ * httemplate/view/cust_main.cgi: non-breaking spaces in custoemr
+ view field names
+
+2003-12-10 15:53 ivan
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html: signup page
+ w/advertising source dropdown
+
+2003-12-10 14:51 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/upgrade10.html: add
+ part_referral.disabled, add disabled indices to agent and
+ part_bill_event
+
+2003-12-10 14:50 ivan
+
+ * FS/FS/part_referral.pm: add part_referral.disabled
+
+2003-11-30 00:06 ivan
+
+ * FS/FS/cust_bill.pm: explicitly tell dvips to write output to a
+ file
+
+2003-11-29 23:52 ivan
+
+ * httemplate/view/cust_bill.cgi: add link to view typeset invoice
+
+2003-11-29 23:41 ivan
+
+ * conf/invoice_latex: move to the left to line up with window
+ envelopes
+
+2003-11-29 02:50 ivan
+
+ * FS/FS/cust_credit_bill.pm: missing cut
+
+2003-11-29 02:48 ivan
+
+ * FS/FS/cust_bill.pm: use the latex template for normal printing
+ when available
+
+2003-11-29 02:39 ivan
+
+ * httemplate/edit/part_pkg.cgi: adding sql_generic price plan
+
+2003-11-29 00:32 ivan
+
+ * FS/FS/: Conf.pm, cust_bill_pay.pm, cust_credit_bill.pm: option to
+ send statements when a payment or credit is applied
+
+2003-11-29 00:18 ivan
+
+ * FS/FS/part_bill_event.pm: also set default latex template for
+ late bill templates
+
+2003-11-29 00:08 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, conf/invoice_latex,
+ conf/invoice_latexfooter, conf/invoice_latexnotes,
+ httemplate/misc/print-invoice.cgi,
+ httemplate/view/cust_bill-ps.cgi: postscript invoice redux
+
+2003-11-26 07:37 ivan
+
+ * FS/FS/cust_bill.pm: remove spurious Setup on one-time package
+ charges
+
+2003-11-26 06:25 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm: add invoice_default_terms config
+ value to control explicit due date printing on invoices
+
+2003-11-24 06:29 ivan
+
+ * httemplate/edit/part_export.cgi: fix html quoting problems
+
+2003-11-24 05:01 ivan
+
+ * httemplate/browse/part_export.cgi: fix html quoting of export
+ options
+
+2003-11-21 10:55 ivan
+
+ * FS/FS/Record.pm: revert bind_param change!
+
+2003-11-21 07:32 ivan
+
+ * httemplate/search/report_receivables.cgi: precedence helps alot
+
+2003-11-21 07:25 ivan
+
+ * httemplate/search/report_receivables.cgi: precedence helps alot
+
+2003-11-21 07:20 ivan
+
+ * httemplate/search/report_receivables.cgi: show customer status on
+ receivables report
+
+2003-11-20 04:48 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: don't error out when not
+ actually changing domain
+
+2003-11-19 10:13 ivan
+
+ * FS/FS/Record.pm: work around DBD::Pg problems with bind_param
+
+2003-11-19 04:21 ivan
+
+ * httemplate/: edit/REAL_cust_pkg.cgi, search/cust_pkg.html,
+ search/report_cc.html, search/report_credit.html,
+ search/report_cust_pay.html, search/report_tax.html: fix
+ jscalendar date ifFormat
+
+2003-11-18 17:37 ivan
+
+ * FS/FS/cust_bill.pm: reversing accidental commit of
+ work-in-progress
+
+2003-11-18 17:29 ivan
+
+ * FS/FS/: cust_bill.pm, cust_main.pm: disable debugging by default
+
+2003-11-18 07:14 ivan
+
+ * FS/FS/part_export.pm: fix communigate pro export descriptions
+
+2003-11-18 07:04 ivan
+
+ * FS/: FS/part_export/communigate_pro.pm,
+ FS/part_export/communigate_pro_singledomain.pm, MANIFEST,
+ FS/part_export.pm: add communigate_pro_singledomain export
+
+2003-11-18 03:17 ivan
+
+ * httemplate/docs/install.html: remove thread/PerlIO warning -
+ standard in 5.8.x and working fine
+
+2003-11-14 23:28 ivan
+
+ * FS/bin/freeside-selfservice-server: kill off ssh process when
+ re-opening connection
+
+2003-11-14 23:18 ivan
+
+ * fs_selfservice/FS-SelfService/freeside-selfservice-clientd: add
+ trailing newline to supress useless error messages in log
+
+2003-11-14 00:43 ivan
+
+ * FS/bin/freeside-selfservice-server: hopefully recover better from
+ lost ssh connections
+
+2003-11-13 18:52 ivan
+
+ * httemplate/search/report_receivables.cgi: sort these
+ case-insensitive
+
+2003-11-13 03:23 ivan
+
+ * install/debian/3.0/INSTALL: fix path in questionable section
+
+2003-11-12 04:29 ivan
+
+ * FS/FS/: svc_Common.pm, svc_acct.pm: allow provisioning of
+ unaudited services with a svcnum for imports
+
+2003-11-12 03:22 ivan
+
+ * FS/FS/cust_pkg.pm: better error msg
+
+2003-11-11 07:03 ivan
+
+ * FS/FS/svc_Common.pm: also make setx behave when setting svcnum
+ during an import
+
+2003-11-11 06:39 ivan
+
+ * FS/FS/svc_Common.pm: fix up virtual field reprucussions
+
+2003-11-11 06:21 ivan
+
+ * FS/FS/svc_Common.pm: simple change to cust_svc creation to help
+ imports with svcnums
+
+2003-11-11 00:35 ivan
+
+ * httemplate/browse/part_referral.cgi: really fix advertising
+ source edit links
+
+2003-11-11 00:01 ivan
+
+ * httemplate/search/report_receivables.cgi: remove spaces between
+ parens and contact name
+
+2003-11-10 23:51 ivan
+
+ * httemplate/browse/: part_referral.cgi, svc_acct_pop.cgi:
+ part_referral.cgi
+
+2003-11-10 05:54 ivan
+
+ * httemplate/misc/process/meta-import.cgi: hmm forgot to check this
+ in?
+
+2003-11-08 08:36 ivan
+
+ * FS/FS/: cust_main.pm, ClientAPI/MyAccount.pm: add order_pkg and
+ cancel_pkg functions to self-service
+
+2003-11-08 08:31 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: documentation for
+ self-service functions!
+
+2003-11-08 04:59 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: pass paybatch field to realtime_bop
+ so we can prevent double-charges
+
+2003-11-07 02:53 ivan
+
+ * httemplate/elements/: calendar-en.js, calendar-setup.js,
+ calendar-win2k-2.css, calendar.js, calendar_stripped.js: update
+ jscalendar
+
+2003-11-07 00:39 ivan
+
+ * FS/FS/cust_svc.pm: also fix attribute_since_sqlradacct for data
+ charging
+
+2003-11-07 00:36 ivan
+
+ * FS/FS/cust_svc.pm: finish fixing sqlradius_withdomain time
+ calculations
+
+2003-11-06 23:56 ivan
+
+ * httemplate/view/svc_acct.cgi: also show RADIUS usage information
+ for sqlradius_withdomain exports
+
+2003-11-06 06:45 ivan
+
+ * httemplate/search/report_receivables.cgi: add totals & simplify
+ expressions
+
+2003-11-06 06:08 ivan
+
+ * httemplate/search/report_receivables.cgi: ack! count credits,
+ not payments twice
+
+2003-11-06 06:00 ivan
+
+ * httemplate/search/report_receivables.cgi: typo
+
+2003-11-06 05:56 ivan
+
+ * httemplate/search/report_receivables.cgi: link to customer, don't
+ show custnum
+
+2003-11-06 05:40 ivan
+
+ * FS/MANIFEST: removing bin/freeside-receivables-report
+
+2003-11-06 05:39 ivan
+
+ * httemplate/: index.html, search/report_receivables.cgi: "current
+ receivables" -> A/R Aging summary
+
+2003-11-06 05:37 ivan
+
+ * FS/bin/freeside-receivables-report: removing (rewritten as a
+ proper html report)
+
+2003-11-05 03:13 ivan
+
+ * bin/create-fetchmailrc: fixup
+
+2003-11-05 02:26 ivan
+
+ * FS/FS/svc_acct.pm: allow letters in quota for use with edquota -p
+
+2003-11-04 10:01 ivan
+
+ * FS/FS/cust_main.pm: don't overwrite otaker on cust_main!
+
+2003-11-04 09:57 ivan
+
+ * bin/create-fetchmailrc: adding
+
+2003-11-04 09:30 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/shellcommands.pm: make snarf
+ info available to exports
+
+2003-11-04 02:56 ivan
+
+ * FS/FS/Record.pm: finish treating serials as ints!
+
+2003-11-04 02:55 ivan
+
+ * FS/FS/Record.pm: treat serial columns as ints too!
+
+2003-11-03 03:42 ivan
+
+ * FS/FS/svc_Common.pm, httemplate/edit/part_svc.cgi: does this fix
+ Bug#590??
+
+2003-11-03 03:30 ivan
+
+ * httemplate/edit/part_svc.cgi: kludge around this so i can add
+ service definitions for now
+
+2003-11-02 21:57 ivan
+
+ * httemplate/: index.html, browse/part_pkg.cgi,
+ search/cust_pkg.cgi: add suspended/canceled browse, fix the old
+ suspended browse
+
+2003-11-02 21:48 ivan
+
+ * httemplate/search/cust_pkg.cgi: add suspended/canceled package
+ browse
+
+2003-11-02 21:40 ivan
+
+ * httemplate/index.html: formatting
+
+2003-11-02 21:34 ivan
+
+ * httemplate/index.html: remove duplicate items from "Reports"
+ section
+
+2003-11-02 21:25 ivan
+
+ * httemplate/browse/part_pkg.cgi: tyops
+
+2003-11-02 21:21 ivan
+
+ * httemplate/browse/part_pkg.cgi: also show suspended and canceled
+ counts on active package browse
+
+2003-10-26 09:30 ivan
+
+ * httemplate/search/cust_main-quickpay.html: default quickpay to
+ exact search
+
+2003-10-25 17:39 ivan
+
+ * httemplate/search/: cust_pay.cgi, report_cust_pay.html: payment
+ reports broken down by Visa/MC / Amex / Discover
+
+2003-10-24 19:05 ivan
+
+ * FS/FS/acct_snarf.pm, FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi: signups with snarf
+ info!
+
+2003-10-24 19:05 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-snarf.html: adding signup
+ with snarf input
+
+2003-10-24 18:06 ivan
+
+ * httemplate/docs/signup.html: better link to .INS files
+ documentation
+
+2003-10-24 13:38 ivan
+
+ * FS/FS/: cust_main.pm, Conf.pm: add cvv-save configuration value
+ to save the cvv data for specific card types
+
+2003-10-24 12:28 ivan
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/process/cust_main.cgi, httemplate/docs/cvv2.html,
+ httemplate/docs/upgrade10.html, FS/FS/cust_main.pm,
+ FS/bin/freeside-setup, fs_signup/FS-SignupClient/cgi/cvv2.html,
+ fs_signup/FS-SignupClient/cgi/cvv2.png,
+ fs_signup/FS-SignupClient/cgi/cvv2_amex.png,
+ httemplate/docs/schema.html: cvv!
+
+2003-10-23 22:51 ivan
+
+ * httemplate/images/: cvv2.png, cvv2_amex.png: adding cvv2 images
+
+2003-10-23 17:50 ivan
+
+ * httemplate/browse/part_referral.cgi: UI: adjust alignment of
+ stats
+
+2003-10-23 17:39 ivan
+
+ * httemplate/browse/part_referral.cgi: referral listing now shows
+ customer signups today and past week/30/60/90/6months/year/total
+
+2003-10-23 15:37 ivan
+
+ * bin/dbdef-create: require DBIx::DBSchema 0.22 to deal with Pg
+ version problems
+
+2003-10-23 02:02 ivan
+
+ * httemplate/docs/legacy.html: fix cranky verbitage at the top
+
+2003-10-23 00:49 ivan
+
+ * FS/FS/cust_pay_batch.pm: Declined results from batches should now
+ suspend the relevant customer.
+
+2003-10-22 12:10 khoff
+
+ * httemplate/edit/process/router.cgi: dbh is a global.
+
+2003-10-20 18:28 ivan
+
+ * install/redhat/9/INSTALL: more rh9 install foo
+
+2003-10-20 17:07 ivan
+
+ * install/redhat/9/INSTALL: update rh9 install foo
+
+2003-10-20 11:59 ivan
+
+ * install/redhat/: 7.3/INSTALL, 9/INSTALL: add passive flag to wget
+
+2003-10-19 22:01 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/part_pkg.cgi,
+ httemplate/view/cust_main.cgi: finish up weekly billing
+
+2003-10-19 21:25 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ httemplate/edit/part_pkg.cgi, httemplate/docs/upgrade10.html,
+ FS/bin/freeside-setup: daily/weekly billing
+
+2003-10-19 19:35 ivan
+
+ * install/redhat/9/: INSTALL, sources.list: update for rh9
+
+2003-10-19 19:28 ivan
+
+ * install/: openbsd/INSTALL, openbsd/cpan, openbsd/ports,
+ redhat/9/INSTALL, redhat/9/sources.list: adding openbsd and red
+ hat installs
+
+2003-10-19 11:08 ivan
+
+ * httemplate/docs/install.html: fix CPAN link
+
+2003-10-16 15:57 khoff
+
+ * FS/FS/part_export/router.pm: Telnet/SSH router export for
+ svc_broadband.
+
+2003-10-16 06:48 ivan
+
+ * httemplate/docs/billing.html: fix Text::Template link
+
+2003-10-15 16:17 khoff
+
+ * httemplate/browse/router.cgi: $router isn't a global.
+
+2003-10-15 15:59 khoff
+
+ * httemplate/edit/router.cgi: More changes that got lost in the
+ merge somehow.
+
+2003-10-15 15:48 khoff
+
+ * httemplate/view/svc_broadband.cgi: File got munged during
+ svc_broadband merge. Added ability to create a 'customer
+ router'.
+
+2003-10-15 08:03 ivan
+
+ * FS/bin/freeside-selfservice-server,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/freeside-selfservice-clientd: add
+ tagging ability so we can run multiple self-service clients on
+ one machine
+
+2003-10-15 05:08 ivan
+
+ * FS/bin/freeside-setup: fix agent username and password
+ nullability
+
+2003-10-15 02:41 ivan
+
+ * FS/FS/cust_main.pm: - Business::OnlinePayment "recurring_billing"
+ flag is set for subsequent credit card transactions; some
+ processors (AuthorozeNet, others?) use this to waive the CVV2
+ requirement.
+
+2003-10-14 09:59 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: fix the default success
+ template
+
+2003-10-09 10:40 ivan
+
+ * FS/FS/cust_pay_batch.pm: parse last line from TD Canada Trust
+
+2003-10-09 04:05 ivan
+
+ * httemplate/docs/install.html: don't install on a public server!
+
+2003-10-07 21:09 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/misc/upload-batch.cgi: can't use
+ File::Basename::basename for windows filenames! use a regex
+ instead
+
+2003-10-07 06:50 ivan
+
+ * Makefile: mandrake
+
+2003-10-07 01:05 ivan
+
+ * FS/: FS/acct_snarf.pm, FS.pm, FS/part_export.pm: adding
+ acct_snarf
+
+2003-10-06 23:06 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: problem was scalar context
+ propogating to the wrong place in the grep
+
+2003-10-06 23:03 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: fix subroutine call from
+ UpdateAccountSettings sub
+
+2003-10-06 22:50 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: add suspend and unsuspend
+ hooks, don't try and set '*SUSPENDED*' passwords
+
+2003-10-06 22:49 ivan
+
+ * FS/FS/svc_acct.pm: doc
+
+2003-10-06 19:27 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: add suspension /
+ unsuspension export to communigate
+
+2003-10-06 05:05 ivan
+
+ * httemplate/search/cust_main-quickpay.html: - put link to main
+ menu on quick payment search page
+
+2003-10-06 04:39 ivan
+
+ * httemplate/search/svc_acct.cgi: fix URL argument processing for
+ account searches by popnum
+
+2003-10-06 04:22 ivan
+
+ * httemplate/search/svc_acct.cgi: typo
+
+2003-10-06 04:20 ivan
+
+ * httemplate/: browse/svc_acct_pop.cgi, search/svc_acct.cgi: fix
+ linking to account list per access number
+
+2003-10-06 04:14 ivan
+
+ * httemplate/: browse/svc_acct_pop.cgi, search/svc_acct.cgi: agent
+ browse shows # of active accounts & links to appropriate account
+ search
+
+2003-10-02 14:51 khoff
+
+ * httemplate/edit/svc_broadband.cgi: $field isn't a global.
+
+2003-10-02 07:26 ivan
+
+ * Makefile: minor Makefile updates
+
+2003-10-02 07:19 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: add emaildecline-exclude config
+ option
+
+2003-10-02 06:08 ivan
+
+ * fs_selfservice/FS-SelfService/freeside-selfservice-clientd: turn
+ off super-verbose logging
+
+2003-10-02 05:42 ivan
+
+ * fs_selfservice/FS-SelfService/Makefile.PL,
+ fs_signup/FS-SignupClient/Makefile.PL: update Makefile.PL
+ dependancies (PREREQ_PM) for self-service module and signup
+ wrapper
+
+2003-10-02 04:23 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/login.html: removing testing
+ info
+
+2003-10-02 03:18 ivan
+
+ * FS/bin/freeside-daily: added -y switch to freeside-daily to
+ specify an offset in days
+
+2003-10-02 01:56 ivan
+
+ * FS/FS/raddb.pm, bin/generate-raddb: update with dictionaries from
+ freeradius 0.9.1, and fix generate-raddb to avoid duplicates
+
+2003-09-30 08:01 ivan
+
+ * FS/FS/agent.pm: no duplicate usernames
+
+2003-09-30 07:58 ivan
+
+ * httemplate/docs/upgrade10.html: agent schema changes
+
+2003-09-30 05:48 ivan
+
+ * httemplate/misc/download-batch.cgi: IE doesn't like downloading
+ MIME type text/comma-separated-values
+
+2003-09-30 01:21 ivan
+
+ * httemplate/edit/REAL_cust_pkg.cgi, CREDITS,
+ httemplate/elements/calendar-en.js,
+ httemplate/elements/calendar-setup.js,
+ httemplate/elements/calendar-win2k-2.css,
+ httemplate/elements/calendar.js,
+ httemplate/elements/calendar_stripped.js,
+ httemplate/images/calendar.png, httemplate/search/cust_pkg.html,
+ httemplate/search/report_cc.html,
+ httemplate/search/report_credit.html,
+ httemplate/search/report_cust_pay.html,
+ httemplate/search/report_tax.html: calendar popups!
+
+2003-09-30 00:04 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/docs/upgrade-1.4.2.html: CGI.pm 2.47 required for
+ ->upload() method
+
+2003-09-29 03:10 ivan
+
+ * httemplate/: browse/agent.cgi, search/cust_main.cgi: agent browse
+ now links to active/cancelled customers
+
+2003-09-28 23:51 ivan
+
+ * FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/cgi/signup-agentselect.html,
+ fs_signup/FS-SignupClient/cgi/signup.cgi: signup with agent
+ selection
+
+2003-09-28 23:35 ivan
+
+ * httemplate/index.html: remove Gratuitous Capitalization
+
+2003-09-28 23:22 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: eliminate warning
+
+2003-09-28 22:51 ivan
+
+ * FS/FS/agent.pm, httemplate/browse/agent.cgi,
+ httemplate/edit/agent.cgi, httemplate/edit/cust_main.cgi: agents
+ can be disabled (auto-sensing based on schema)
+
+2003-09-28 22:51 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/schema.html: added
+ agent.disabled agent.username agent._password
+
+2003-09-28 19:17 ivan
+
+ * FS/: FS/Conf.pm, bin/freeside-selfservice-server: finish removing
+ quiet config options
+
+2003-09-27 19:36 ivan
+
+ * FS/FS/cust_pay_batch.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/browse/cust_pay_batch.cgi,
+ httemplate/misc/upload-batch.cgi: add upload of batch result from
+ TD Canada Trust some global.asa / handler.pl enhancements
+
+2003-09-26 16:33 khoff
+
+ * httemplate/edit/svc_www.cgi: $field is not a global.
+
+2003-09-26 14:02 khoff
+
+ * httemplate/edit/svc_acct.cgi: $field isn't a global.
+
+2003-09-26 06:37 ivan
+
+ * httemplate/docs/upgrade10.html: sql
+
+2003-09-26 06:04 ivan
+
+ * FS/: FS/cust_main.pm, bin/freeside-daily: re-setup option to
+ re-charge setup fee
+
+2003-09-26 02:31 ivan
+
+ * FS/FS/cust_main.pm: scalar/array scope fix... new, multiple (i.e.
+ canadian GST/PST) taxes work now!
+
+2003-09-26 02:15 ivan
+
+ * FS/FS/UID.pm: re-enable ChopBlanks for now
+
+2003-09-26 02:09 ivan
+
+ * FS/FS/cust_pkg.pm: fix manual_flag problem preventing cust_pkg
+ editing
+
+2003-09-26 01:11 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/cust_main_county.cgi: fix tax edit UI
+
+2003-09-25 04:56 ivan
+
+ * httemplate/docs/upgrade10.html: new per-tax setuptax and recurtax
+ fields
+
+2003-09-25 04:49 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/cust_main_county.cgi: UI for multiple named taxes w/setup &
+ recur exemptions 1.4 schema-auto-adjusting backport
+
+2003-09-25 04:17 ivan
+
+ * FS/FS/: cust_main.pm, cust_main_county.pm: multiple, named taxes
+ for a single region 1.4 backport auto-adjusts based on schema
+
+2003-09-25 03:40 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/schema.html: add setuptax
+ and recurtax fields to cust_main_county
+
+2003-09-25 03:28 ivan
+
+ * fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ freebsd portability fix
+
+2003-09-25 03:27 ivan
+
+ * FS/bin/freeside-selfservice-server: freebsd portability fixes
+
+2003-09-25 03:26 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm: quiet self-service server cancels
+
+2003-09-25 02:40 ivan
+
+ * httemplate/docs/upgrade-1.4.2.html: 1.4.2 upgrade
+
+2003-09-25 02:39 ivan
+
+ * httemplate/docs/upgrade9.html: update upgrade docs for bind
+ exports
+
+2003-09-24 10:20 ivan
+
+ * FS/FS/part_export/shellcommands.pm: don't change dir either when
+ username_pwonly is set
+
+2003-09-24 10:06 ivan
+
+ * FS/FS/part_export/shellcommands.pm: don't allow uid changes when
+ usermod_pwonly set
+
+2003-09-23 19:37 ivan
+
+ * install/freebsd/ports: need Cache::Cache in 1.4.2+
+
+2003-09-23 18:30 ivan
+
+ * httemplate/browse/agent.cgi: fix boolean precedence error leading
+ to inaccurate results on the new customer status list
+
+2003-09-21 00:31 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/misc/download-batch.cgi: remove
+ trancode from batching
+
+2003-09-20 23:52 ivan
+
+ * httemplate/misc/download-batch.cgi: eliminate extraneous newlines
+
+2003-09-20 18:22 ivan
+
+ * httemplate/misc/download-batch.cgi: preliminary batch download
+
+2003-09-20 18:22 ivan
+
+ * httemplate/browse/cust_pay_batch.cgi: add link to preliminary
+ batch download
+
+2003-09-19 05:40 ivan
+
+ * FS/FS/cust_main.pm: quiet option to cancel method
+
+2003-09-19 05:19 ivan
+
+ * fs_signup/FS-SignupClient/SignupClient.pm: fix
+ backwards-compatibility for signup server
+
+2003-09-19 05:13 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: remove klunky $error ||= usage
+
+2003-09-19 05:04 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: oops, flipped an or to an and
+
+2003-09-19 05:02 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: cache initial signup_info for
+ performance
+
+2003-09-19 04:56 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: better error message when you don't
+ select a package
+
+2003-09-19 04:50 ivan
+
+ * init.d/freeside-init: correct pid filename for stopping
+ self-service server
+
+2003-09-19 04:35 ivan
+
+ * fs_selfservice/FS-SelfService/SelfService.pm: finish moving
+ signup server functions to self-service interace
+
+2003-09-19 04:00 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: module needs to return true
+
+2003-09-19 03:08 ivan
+
+ * FS/FS/ClientAPI/Signup.pm: make sure signup cancels are quiet
+
+2003-09-19 03:07 ivan
+
+ * Makefile, FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ FS/FS/ClientAPI/Signup.pm,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ httemplate/docs/index.html: move signup server functions to
+ self-service server. fix provisioning & immediate suspension of
+ declined signups.
+
+2003-09-19 02:59 ivan
+
+ * init.d/freeside-init: removing signup and passwd servers
+
+2003-09-18 21:25 ivan
+
+ * FS/FS/cust_main.pm: finish cleaning up the quiet stuff
+
+2003-09-18 21:13 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm, cust_pkg.pm: deprecate
+ signup_server-quiet config option
+
+2003-09-18 03:52 ivan
+
+ * httemplate/browse/agent.cgi: oops
+
+2003-09-18 03:46 ivan
+
+ * httemplate/browse/agent.cgi: include info on number of
+ active/cancelled customers in agent browse
+
+2003-09-15 14:33 ivan
+
+ * httemplate/search/cust_pkg.cgi: package search skips cancelled
+ packages when searching by date range
+
+2003-09-11 17:14 khoff
+
+ * FS/FS/addr_block.pm: @excludeaddr is a list of addresses, not
+ NetAddrs, so it shouldn't be map'd
+
+2003-09-11 14:57 ivan
+
+ * FS/FS/part_export.pm: also update sqlradius_withdomaind
+ description for freeradius 0.9.1
+
+2003-09-11 14:54 ivan
+
+ * FS/FS/part_export.pm: update doc note for freeradius 0.9.1
+
+2003-09-10 15:10 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: communigate pro quota bs
+
+2003-09-10 14:56 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: don't set an empty
+ externalFlag
+
+2003-09-10 14:45 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: communitgate pro
+ CreateAccount examples are on crack
+
+2003-09-10 14:39 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: fix for communigate pro
+ weird data structure on create
+
+2003-09-10 14:01 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: set initial password for
+ new accounts
+
+2003-09-10 03:54 ivan
+
+ * FS/FS/cust_pay.pm: adding cust_main method
+
+2003-09-09 15:36 ivan
+
+ * FS/MANIFEST: adding communigate_pro export
+
+2003-09-08 21:16 ivan
+
+ * FS/FS/part_export.pm: typo hiding remote username labels
+
+2003-09-06 00:20 ivan
+
+ * httemplate/browse/agent_type.cgi: hide display of disabled
+ packages from agent type browse
+
+2003-09-05 23:45 ivan
+
+ * FS/FS/part_export.pm: updated DBI link in sqlradius export notes
+
+2003-09-05 18:45 ivan
+
+ * FS/FS/svc_acct.pm: fix method name
+
+2003-09-05 18:44 ivan
+
+ * FS/FS/: cust_svc.pm, svc_acct.pm: add
+ get_session_history_sqlradacct have $ignore_quantity also ignore
+ 0 quantities
+
+2003-09-05 06:19 ivan
+
+ * FS/FS/part_export/communigate_pro.pm: typo
+
+2003-09-05 06:18 ivan
+
+ * FS/FS/: part_export.pm, part_export/communigate_pro.pm: add
+ communigate pro export
+
+2003-09-05 06:16 ivan
+
+ * FS/FS/Conf.pm: doc
+
+2003-09-05 02:13 ivan
+
+ * FS/FS/svc_acct.pm: allow ! password like !!
+
+2003-09-05 01:17 ivan
+
+ * FS/FS/Conf.pm: fix reference to obsolete shellcommands-useradd
+ conf value (refer to exports instead)
+
+2003-09-05 01:02 ivan
+
+ * FS/FS/Conf.pm: fix typo
+
+2003-09-05 01:01 ivan
+
+ * FS/FS/svc_acct.pm: allow up to 60 char encrypted passwords for
+ blowfish
+
+2003-09-05 00:55 ivan
+
+ * FS/bin/freeside-setup: svc_acct._password from 50 to 72 for
+ blowfish passwords
+
+2003-09-04 21:09 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: users-allow_comp config value to
+ control creation of complimentary accounts and minor pod updates
+
+2003-09-04 19:31 ivan
+
+ * httemplate/edit/part_svc.cgi: -w-safe and run under a 1.4 schema
+ too
+
+2003-09-03 16:06 ivan
+
+ * httemplate/view/cust_main.cgi: list extraneous services, closes:
+ #213
+
+2003-09-03 13:22 ivan
+
+ * FS/FS/Record.pm: turn off query debugging
+
+2003-09-03 11:46 ivan
+
+ * FS/FS/Record.pm: turn vfieldpart_hashref into a method, not a
+ subroutine another fix to support running 1.5.0 virtual field
+ code on 1.4.x databases
+
+2003-09-03 06:18 ivan
+
+ * FS/FS/part_export.pm: openbsd also uses sane useradd/mod/del
+ commands
+
+2003-09-03 05:35 ivan
+
+ * Makefile: makefile trivia for openbsd
+
+2003-08-21 00:42 ivan
+
+ * install/debian/3.0/INSTALL: woody backports
+
+2003-08-20 23:46 ivan
+
+ * install/debian/3.0/INSTALL: iffy
+
+2003-08-20 23:42 ivan
+
+ * install/debian/3.0/INSTALL: woody
+
+2003-08-07 22:54 ivan
+
+ * httemplate/view/svc_acct.cgi: - fix possible glitch with Mason on
+ account view screen
+
+2003-08-07 22:42 ivan
+
+ * FS/FS/CGI.pm, bin/masonize, httemplate/index.html,
+ httemplate/elements/header.html,
+ httemplate/elements/menubar.html, httemplate/elements/pager.html,
+ httemplate/elements/table.html, httemplate/search/sql.cgi,
+ httemplate/search/sql.html,
+ httemplate/search/elements/search.html: - (finish) includes!
+ (closes: Bug#551) - (finish) moving SQL search to including
+ generic elements/search.html - new elements: menubar.html,
+ header.html, pager.html and table.html - have masonize process
+ .html files also
+
+2003-08-07 19:02 ivan
+
+ * bin/masonize, htetc/global.asa, httemplate/autohandler,
+ httemplate/graph/money_time-graph.cgi,
+ httemplate/graph/money_time.cgi, httemplate/search/sql.html,
+ httemplate/search/elements/search.html: - fix Mason profiling to
+ pass-through images (for graph/) - fix graph/money-time.cgi use
+ of $m interfering with Mason - fix graph/money-time-graph.cgi to
+ set content-type in a Mason/ASP-independant fashion -
+ (beginning of) includes! - (beginning of) moving SQL search to
+ including generic elements/search.html - fix global.asa typo -
+ fix masonize to not prepend an extraneous blank line (breaking
+ graph/money-time-graph.cgi)
+
+2003-08-07 06:08 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/view/cust_main.cgi: - turn on profiling with mason
+ like with Apache::ASP (redirects now working) - fix mason error
+ with new view/cust_main.cgi UI
+
+2003-08-07 05:47 ivan
+
+ * Makefile, htetc/global.asa, htetc/handler.pl,
+ htetc/handler.pl-1.0x, httemplate/autohandler,
+ httemplate/index.html, httemplate/docs/install.html,
+ httemplate/docs/upgrade10.html: - switch to mason by default -
+ minimum mason version 1.1 (and doc) - evaluate .html files with
+ mason/asp - turn on profiling with mason like with Apache::ASP
+ (redirects not working) - (start of) includes
+
+2003-08-05 14:00 ivan
+
+ * httemplate/browse/part_pkg.cgi: doh, revert stuff that shouldn't
+ have been checked in
+
+2003-08-05 13:06 ivan
+
+ * htetc/: handler.pl, handler.pl-1.0x: no svc_acct_sm in 1.5
+
+2003-08-05 12:07 ivan
+
+ * FS/FS/part_export.pm: update sqlradius{_withdomain} documentation
+
+2003-08-05 11:52 ivan
+
+ * FS/FS/svc_domain.pm: remove spurious re-use of $error
+
+2003-08-05 11:45 ivan
+
+ * FS/FS/Record.pm: backwards compatibility if the schema hasn't
+ been updated
+
+2003-08-04 17:32 khoff
+
+ * httemplate/index.html: Fixed %%%VERSION%%% tag
+
+2003-08-04 17:20 khoff
+
+ * FS/MANIFEST, FS/FS/Record.pm, FS/FS/addr_block.pm,
+ FS/FS/agent.pm, FS/FS/agent_type.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_event.pm, FS/FS/cust_bill_pay.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_bill_pkg_detail.pm,
+ FS/FS/cust_credit.pm, FS/FS/cust_credit_bill.pm,
+ FS/FS/cust_credit_refund.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_county.pm, FS/FS/cust_main_invoice.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pay_batch.pm, FS/FS/cust_pkg.pm,
+ FS/FS/cust_refund.pm, FS/FS/cust_svc.pm,
+ FS/FS/cust_tax_exempt.pm, FS/FS/domain_record.pm,
+ FS/FS/export_svc.pm, FS/FS/msgcat.pm, FS/FS/nas.pm,
+ FS/FS/part_bill_event.pm, FS/FS/part_export.pm,
+ FS/FS/part_export_option.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_pop_local.pm, FS/FS/part_referral.pm,
+ FS/FS/part_svc.pm, FS/FS/part_svc_column.pm,
+ FS/FS/part_virtual_field.pm, FS/FS/pkg_svc.pm, FS/FS/port.pm,
+ FS/FS/prepay_credit.pm, FS/FS/queue.pm, FS/FS/queue_arg.pm,
+ FS/FS/queue_depend.pm, FS/FS/radius_usergroup.pm,
+ FS/FS/router.pm, FS/FS/session.pm, FS/FS/svc_Common.pm,
+ FS/FS/svc_acct.pm, FS/FS/svc_acct_pop.pm, FS/FS/svc_broadband.pm,
+ FS/FS/svc_domain.pm, FS/FS/svc_forward.pm, FS/FS/svc_www.pm,
+ FS/FS/type_pkgs.pm, FS/bin/freeside-setup, htetc/global.asa,
+ htetc/handler.pl, htetc/handler.pl-1.0x, httemplate/index.html,
+ httemplate/browse/part_svc.cgi,
+ httemplate/browse/part_virtual_field.cgi,
+ httemplate/browse/router.cgi, httemplate/docs/upgrade10.html,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/part_virtual_field.cgi,
+ httemplate/edit/router.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_broadband.cgi, httemplate/edit/svc_www.cgi,
+ httemplate/edit/process/router.cgi,
+ httemplate/edit/process/svc_broadband.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_broadband.cgi,
+ httemplate/view/svc_forward.cgi, httemplate/view/svc_www.cgi:
+ Virtual field merge
+
+2003-08-04 17:00 khoff
+
+ * FS/FS/part_router_field.pm, FS/FS/part_sb_field.pm,
+ FS/FS/router_field.pm, FS/FS/sb_field.pm,
+ httemplate/browse/part_sb_field.cgi,
+ httemplate/edit/part_router_field.cgi,
+ httemplate/edit/part_sb_field.cgi: Virtual field merge
+
+2003-07-25 09:26 ivan
+
+ * FS/FS/svc_acct.pm: typo
+
+2003-07-25 06:13 ivan
+
+ * FS/FS/Conf.pm: doc
+
+2003-07-23 10:05 ivan
+
+ * FS/FS/part_export/domain_shellcommands.pm: bugfix for
+ non-catchall domains
+
+2003-07-23 08:36 ivan
+
+ * httemplate/edit/: cust_main.cgi, process/cust_main.cgi: fix
+ spurious "can't purchase pkgpart" errors
+
+2003-07-17 09:02 ivan
+
+ * FS/FS/cust_main.pm: one last tiny bugfix for the retry_realtime
+ functionality
+
+2003-07-16 09:05 ivan
+
+ * httemplate/search/cust_pay.cgi: UI
+
+2003-07-16 09:01 ivan
+
+ * httemplate/search/cust_pay.cgi: show totals in payment report
+
+2003-07-15 06:30 ivan
+
+ * rt/: ChangeLog, Makefile, README, TODO, bin/initacls.Oracle,
+ bin/initacls.Pg, bin/initacls.mysql, bin/mason_handler.fcgi,
+ bin/mason_handler.scgi, bin/rt, bin/rt-mailgate, bin/rtadmin,
+ bin/webmux.pl, docs/rt.gif, docs/design_docs/acls,
+ docs/design_docs/basic-definitions.txt,
+ docs/design_docs/cli_spec, docs/design_docs/evil_plans,
+ docs/design_docs/local_hacking, etc/acl.Oracle, etc/acl.Pg,
+ etc/acl.mysql, etc/config.pm, etc/schema.Oracle, etc/schema.Pg,
+ etc/schema.mysql, etc/schema.pm, lib/MANIFEST, lib/MANIFEST.SKIP,
+ lib/Makefile.PL, lib/RT.pm, lib/test.pl, lib/RT/ACE.pm,
+ lib/RT/ACL.pm, lib/RT/Attachment.pm, lib/RT/Attachments.pm,
+ lib/RT/CurrentUser.pm, lib/RT/Date.pm, lib/RT/EasySearch.pm,
+ lib/RT/Group.pm, lib/RT/GroupMember.pm, lib/RT/GroupMembers.pm,
+ lib/RT/Groups.pm, lib/RT/Handle.pm, lib/RT/Keyword.pm,
+ lib/RT/KeywordSelect.pm, lib/RT/KeywordSelects.pm,
+ lib/RT/Keywords.pm, lib/RT/Link.pm, lib/RT/Links.pm,
+ lib/RT/ObjectKeyword.pm, lib/RT/ObjectKeywords.pm,
+ lib/RT/Queue.pm, lib/RT/Queues.pm, lib/RT/Record.pm,
+ lib/RT/Scrip.pm, lib/RT/ScripAction.pm, lib/RT/ScripActions.pm,
+ lib/RT/ScripCondition.pm, lib/RT/ScripConditions.pm,
+ lib/RT/Scrips.pm, lib/RT/Template.pm, lib/RT/Templates.pm,
+ lib/RT/TestHarness.pm, lib/RT/Ticket.pm, lib/RT/Tickets.pm,
+ lib/RT/Transaction.pm, lib/RT/Transactions.pm, lib/RT/User.pm,
+ lib/RT/Users.pm, lib/RT/Watcher.pm, lib/RT/Watchers.pm,
+ lib/RT/Action/Autoreply.pm, lib/RT/Action/Generic.pm,
+ lib/RT/Action/Notify.pm, lib/RT/Action/NotifyAsComment.pm,
+ lib/RT/Action/OpenDependent.pm, lib/RT/Action/ResolveMembers.pm,
+ lib/RT/Action/SendEmail.pm, lib/RT/Action/SendPasswordEmail.pm,
+ lib/RT/Action/StallDependent.pm,
+ lib/RT/Condition/AnyTransaction.pm, lib/RT/Condition/Generic.pm,
+ lib/RT/Condition/NewDependency.pm,
+ lib/RT/Condition/StatusChange.pm, lib/RT/Interface/CLI.pm,
+ lib/RT/Interface/Email.pm, lib/RT/Interface/Web.pm,
+ tools/cpan2rpm, tools/initdb, tools/insertdata, tools/testdeps,
+ webrt/autohandler, webrt/index.html, webrt/Admin/index.html,
+ webrt/Admin/Elements/CreateQueueCalled,
+ webrt/Admin/Elements/CreateUserCalled,
+ webrt/Admin/Elements/EditUserComments,
+ webrt/Admin/Elements/GrantQueueRightsTo,
+ webrt/Admin/Elements/GroupTabs, webrt/Admin/Elements/Header,
+ webrt/Admin/Elements/ListGlobalKeywordSelects,
+ webrt/Admin/Elements/ListGlobalScrips,
+ webrt/Admin/Elements/ModifyKeyword,
+ webrt/Admin/Elements/ModifyKeywordSelect,
+ webrt/Admin/Elements/ModifyQueue,
+ webrt/Admin/Elements/ModifyTemplate,
+ webrt/Admin/Elements/ModifyUser,
+ webrt/Admin/Elements/QueueRightsForUser,
+ webrt/Admin/Elements/QueueTabs,
+ webrt/Admin/Elements/SelectKeywordSelect,
+ webrt/Admin/Elements/SelectModifyGroup,
+ webrt/Admin/Elements/SelectModifyKeyword,
+ webrt/Admin/Elements/SelectModifyKeywordSelect,
+ webrt/Admin/Elements/SelectModifyQueue,
+ webrt/Admin/Elements/SelectModifyUser,
+ webrt/Admin/Elements/SelectQueueRights,
+ webrt/Admin/Elements/SelectRights,
+ webrt/Admin/Elements/SelectScrip,
+ webrt/Admin/Elements/SelectScripAction,
+ webrt/Admin/Elements/SelectScripCondition,
+ webrt/Admin/Elements/SelectSingleOrMultiple,
+ webrt/Admin/Elements/SelectTemplate,
+ webrt/Admin/Elements/SelectUsers,
+ webrt/Admin/Elements/SystemTabs, webrt/Admin/Elements/Tabs,
+ webrt/Admin/Elements/UserTabs,
+ webrt/Admin/Global/GroupRights.html,
+ webrt/Admin/Global/Keywords.html, webrt/Admin/Global/Scrips.html,
+ webrt/Admin/Global/Template.html,
+ webrt/Admin/Global/Templates.html,
+ webrt/Admin/Global/UserRights.html,
+ webrt/Admin/Global/index.html, webrt/Admin/Groups/Members.html,
+ webrt/Admin/Groups/Modify.html, webrt/Admin/Groups/Rights.html,
+ webrt/Admin/Groups/index.html,
+ webrt/Admin/KeywordSelects/Modify.html,
+ webrt/Admin/KeywordSelects/index.html,
+ webrt/Admin/Keywords/Modify.html,
+ webrt/Admin/Keywords/index.html, webrt/Admin/Queues/Create.html,
+ webrt/Admin/Queues/GroupRights.html,
+ webrt/Admin/Queues/Keywords.html, webrt/Admin/Queues/Modify.html,
+ webrt/Admin/Queues/People.html, webrt/Admin/Queues/Scrips.html,
+ webrt/Admin/Queues/Template.html,
+ webrt/Admin/Queues/Templates.html,
+ webrt/Admin/Queues/UserRights.html,
+ webrt/Admin/Queues/index.html, webrt/Admin/Users/Modify.html,
+ webrt/Admin/Users/Prefs.html, webrt/Admin/Users/Rights.html,
+ webrt/Admin/Users/index.html, webrt/Elements/Checkbox,
+ webrt/Elements/CreateTicket, webrt/Elements/CustomHomepageHeader,
+ webrt/Elements/Error, webrt/Elements/Footer,
+ webrt/Elements/GotoTicket, webrt/Elements/Header,
+ webrt/Elements/ListActions, webrt/Elements/Login,
+ webrt/Elements/MessageBox, webrt/Elements/MyRequests,
+ webrt/Elements/MyTickets, webrt/Elements/Quicksearch,
+ webrt/Elements/Refresh, webrt/Elements/Section,
+ webrt/Elements/SelectBoolean, webrt/Elements/SelectDate,
+ webrt/Elements/SelectDateRelation, webrt/Elements/SelectDateType,
+ webrt/Elements/SelectEqualityOperator,
+ webrt/Elements/SelectKeyword,
+ webrt/Elements/SelectKeywordOptions,
+ webrt/Elements/SelectLinkType, webrt/Elements/SelectMatch,
+ webrt/Elements/SelectNewTicketQueue, webrt/Elements/SelectOwner,
+ webrt/Elements/SelectQueue, webrt/Elements/SelectResultsPerPage,
+ webrt/Elements/SelectSortOrder, webrt/Elements/SelectStatus,
+ webrt/Elements/SelectTicketSortBy, webrt/Elements/SelectUsers,
+ webrt/Elements/SelectWatcherType, webrt/Elements/ShadedBox,
+ webrt/Elements/Submit, webrt/Elements/Tabs,
+ webrt/Elements/TitleBoxEnd, webrt/Elements/TitleBoxStart,
+ webrt/Elements/ViewUser, webrt/Elements/dayMenu,
+ webrt/Elements/monthMenu, webrt/Elements/yearMenu,
+ webrt/NoAuth/Logout.html, webrt/NoAuth/Reminder.html,
+ webrt/NoAuth/webrt.css, webrt/NoAuth/images/rt.jpg,
+ webrt/NoAuth/images/spacer.gif, webrt/Search/Bulk.html,
+ webrt/Search/Listing.html, webrt/Search/PickRestriction,
+ webrt/Search/RestrictSearch.html, webrt/Search/TicketCell,
+ webrt/SelfService/Closed.html, webrt/SelfService/Create.html,
+ webrt/SelfService/Display.html, webrt/SelfService/Error.html,
+ webrt/SelfService/Prefs.html, webrt/SelfService/Update.html,
+ webrt/SelfService/index.html,
+ webrt/SelfService/Attachment/dhandler,
+ webrt/SelfService/Elements/GotoTicket,
+ webrt/SelfService/Elements/Header,
+ webrt/SelfService/Elements/MyRequests,
+ webrt/SelfService/Elements/Tabs, webrt/Ticket/Create.html,
+ webrt/Ticket/Display.html, webrt/Ticket/History.html,
+ webrt/Ticket/Modify.html, webrt/Ticket/ModifyAll.html,
+ webrt/Ticket/ModifyDates.html, webrt/Ticket/ModifyLinks.html,
+ webrt/Ticket/ModifyPeople.html, webrt/Ticket/Update.html,
+ webrt/Ticket/Attachment/dhandler,
+ webrt/Ticket/Elements/AddWatchers,
+ webrt/Ticket/Elements/EditBasics,
+ webrt/Ticket/Elements/EditDates,
+ webrt/Ticket/Elements/EditKeywordSelects,
+ webrt/Ticket/Elements/EditLinks,
+ webrt/Ticket/Elements/EditPeople,
+ webrt/Ticket/Elements/EditWatchers,
+ webrt/Ticket/Elements/ShowBasics,
+ webrt/Ticket/Elements/ShowDates,
+ webrt/Ticket/Elements/ShowDependencies,
+ webrt/Ticket/Elements/ShowHistory,
+ webrt/Ticket/Elements/ShowKeywordSelects,
+ webrt/Ticket/Elements/ShowLinks,
+ webrt/Ticket/Elements/ShowMemberOf,
+ webrt/Ticket/Elements/ShowMembers,
+ webrt/Ticket/Elements/ShowPeople,
+ webrt/Ticket/Elements/ShowReferences,
+ webrt/Ticket/Elements/ShowRequestor,
+ webrt/Ticket/Elements/ShowSummary,
+ webrt/Ticket/Elements/ShowTransaction,
+ webrt/Ticket/Elements/Tabs, webrt/Ticket/Elements/ToolBar,
+ webrt/User/Prefs.html: reverting to vendor branch rt 3.0.4,
+ hopefully
+
+2003-07-15 06:16 ivan
+
+ * rt/: Makefile.in, aclocal.m4, config, config.layout, Changelog,
+ config.log, config.pld, config.status, configure, configure.ac,
+ install-sh, HOWTO/README, HOWTO/change.txt, HOWTO/release.txt,
+ HOWTO/version-control.txt, bin/mason_handler.fcgi.in,
+ bin/mason_handler.scgi.in, bin/mason_handler.svc,
+ bin/mason_handler.svc.in, bin/rt-commit-handler,
+ bin/rt-commit-handler.in, bin/rt-crontool.in, bin/rt-mailgate.in,
+ bin/webmux.pl.in, bin/rt-crontool,
+ docs/design_docs/approval_notices,
+ docs/design_docs/approval_template, docs/design_docs/cf_search,
+ docs/design_docs/delegation, docs/design_docs/groups_notes,
+ docs/design_docs/recursive_group_membership_algorithm,
+ docs/design_docs/rql_parser_machine.graphviz,
+ docs/design_docs/string-extraction-guide.txt,
+ docs/design_docs/ticket_templates, etc/RT_Config.pm,
+ etc/RT_Config.pm.in, etc/RT_SiteConfig.pm, etc/constraints.mysql,
+ etc/initialdata, etc/schema.SQLite, etc/upgrade/2.1.71,
+ html/autohandler, html/index.html, html/l, html/Admin/index.html,
+ html/Admin/Elements/AddCustomFieldValue,
+ html/Admin/Elements/CreateUserCalled,
+ html/Admin/Elements/EditCustomField,
+ html/Admin/Elements/EditCustomFieldValues,
+ html/Admin/Elements/EditCustomFields,
+ html/Admin/Elements/EditQueueWatchers,
+ html/Admin/Elements/EditScrip, html/Admin/Elements/EditScrips,
+ html/Admin/Elements/EditTemplates,
+ html/Admin/Elements/EditUserComments,
+ html/Admin/Elements/GroupTabs, html/Admin/Elements/Header,
+ html/Admin/Elements/ListGlobalCustomFields,
+ html/Admin/Elements/ListGlobalScrips,
+ html/Admin/Elements/ModifyQueue,
+ html/Admin/Elements/ModifyTemplate,
+ html/Admin/Elements/ModifyUser,
+ html/Admin/Elements/QueueRightsForUser,
+ html/Admin/Elements/QueueTabs,
+ html/Admin/Elements/SelectCustomFieldType,
+ html/Admin/Elements/SelectGroups,
+ html/Admin/Elements/SelectModifyGroup,
+ html/Admin/Elements/SelectModifyQueue,
+ html/Admin/Elements/SelectModifyUser,
+ html/Admin/Elements/SelectNewGroupMembers,
+ html/Admin/Elements/SelectRights,
+ html/Admin/Elements/SelectScrip,
+ html/Admin/Elements/SelectScripAction,
+ html/Admin/Elements/SelectScripCondition,
+ html/Admin/Elements/SelectSingleOrMultiple,
+ html/Admin/Elements/SelectTemplate,
+ html/Admin/Elements/SelectUsers, html/Admin/Elements/SystemTabs,
+ html/Admin/Elements/Tabs, html/Admin/Elements/UserTabs,
+ html/Admin/Global/CustomField.html,
+ html/Admin/Global/CustomFields.html,
+ html/Admin/Global/GroupRights.html, html/Admin/Global/Scrip.html,
+ html/Admin/Global/Scrips.html, html/Admin/Global/Template.html,
+ html/Admin/Global/Templates.html,
+ html/Admin/Global/UserRights.html, html/Admin/Global/index.html,
+ html/Admin/Groups/GroupRights.html,
+ html/Admin/Groups/Members.html, html/Admin/Groups/Modify.html,
+ html/Admin/Groups/UserRights.html, html/Admin/Groups/index.html,
+ html/Admin/Queues/CustomField.html,
+ html/Admin/Queues/CustomFields.html,
+ html/Admin/Queues/GroupRights.html,
+ html/Admin/Queues/Modify.html, html/Admin/Queues/People.html,
+ html/Admin/Queues/Scrip.html, html/Admin/Queues/Scrips.html,
+ html/Admin/Queues/Template.html,
+ html/Admin/Queues/Templates.html,
+ html/Admin/Queues/UserRights.html, html/Admin/Queues/index.html,
+ html/Admin/Users/Modify.html, html/Admin/Users/Prefs.html,
+ html/Admin/Users/index.html, html/Approvals/Display.html,
+ html/Approvals/index.html, html/Approvals/Elements/Approve,
+ html/Approvals/Elements/PendingMyApproval,
+ html/Approvals/Elements/ShowDependency,
+ html/Approvals/Elements/Tabs, html/Elements/BevelBoxRaisedEnd,
+ html/Elements/BevelBoxRaisedStart, html/Elements/Callback,
+ html/Elements/Checkbox, html/Elements/CreateTicket,
+ html/Elements/Error, html/Elements/Footer,
+ html/Elements/GotoTicket, html/Elements/Header,
+ html/Elements/ListActions, html/Elements/Login,
+ html/Elements/Menu, html/Elements/MessageBox,
+ html/Elements/MyRequests, html/Elements/MyTickets,
+ html/Elements/PageLayout, html/Elements/Quicksearch,
+ html/Elements/Refresh, html/Elements/Section,
+ html/Elements/SelectAttachmentField, html/Elements/SelectBoolean,
+ html/Elements/SelectCustomFieldOperator,
+ html/Elements/SelectCustomFieldValue, html/Elements/SelectDate,
+ html/Elements/SelectDateRelation, html/Elements/SelectDateType,
+ html/Elements/SelectEqualityOperator, html/Elements/SelectGroups,
+ html/Elements/SelectLinkType, html/Elements/SelectMatch,
+ html/Elements/SelectNewTicketQueue, html/Elements/SelectOwner,
+ html/Elements/SelectQueue, html/Elements/SelectResultsPerPage,
+ html/Elements/SelectSortOrder, html/Elements/SelectStatus,
+ html/Elements/SelectTicketSortBy,
+ html/Elements/SelectTicketTypes, html/Elements/SelectUsers,
+ html/Elements/SelectWatcherType,
+ html/Elements/SetupSessionCookie, html/Elements/ShadedBox,
+ html/Elements/ShadedInputRow, html/Elements/ShadedRow,
+ html/Elements/SimpleSearch, html/Elements/Submit,
+ html/Elements/Tabs, html/Elements/TitleBoxEnd,
+ html/Elements/TitleBoxStart, html/Elements/ViewUser,
+ html/NoAuth/Logout.html, html/NoAuth/Reminder.html,
+ html/NoAuth/webrt.css, html/NoAuth/images/back_home.gif,
+ html/NoAuth/images/bplogo.gif, html/NoAuth/images/favicon.png,
+ html/NoAuth/images/head_requestracker.gif,
+ html/NoAuth/images/rt.jpg, html/NoAuth/images/space.gif,
+ html/NoAuth/images/spacer.gif,
+ html/NoAuth/images/squares_blue.gif,
+ html/REST/1.0/NoAuth/mail-gateway, html/Search/Bulk.html,
+ html/Search/Listing.html, html/Search/Elements/PickRestriction,
+ html/Search/Elements/TicketHeader,
+ html/Search/Elements/TicketHeaderCell,
+ html/Search/Elements/TicketRow, html/SelfService/Closed.html,
+ html/SelfService/Create.html, html/SelfService/Display.html,
+ html/SelfService/Error.html, html/SelfService/Prefs.html,
+ html/SelfService/Update.html, html/SelfService/index.html,
+ html/SelfService/Attachment/dhandler,
+ html/SelfService/Elements/GotoTicket,
+ html/SelfService/Elements/Header,
+ html/SelfService/Elements/MyRequests,
+ html/SelfService/Elements/Tabs, html/Ticket/Create.html,
+ html/Ticket/Display.html, html/Ticket/History.html,
+ html/Ticket/Modify.html, html/Ticket/ModifyAll.html,
+ html/Ticket/ModifyDates.html, html/Ticket/ModifyLinks.html,
+ html/Ticket/ModifyPeople.html, html/Ticket/Update.html,
+ html/Ticket/Attachment/dhandler,
+ html/Ticket/Elements/AddWatchers, html/Ticket/Elements/BulkLinks,
+ html/Ticket/Elements/EditBasics,
+ html/Ticket/Elements/EditCustomField,
+ html/Ticket/Elements/EditCustomFields,
+ html/Ticket/Elements/EditDates, html/Ticket/Elements/EditLinks,
+ html/Ticket/Elements/EditPeople,
+ html/Ticket/Elements/EditWatchers,
+ html/Ticket/Elements/ShowAttachments,
+ html/Ticket/Elements/ShowBasics,
+ html/Ticket/Elements/ShowCustomFields,
+ html/Ticket/Elements/ShowDates,
+ html/Ticket/Elements/ShowDependencies,
+ html/Ticket/Elements/ShowHistory, html/Ticket/Elements/ShowLink,
+ html/Ticket/Elements/ShowLinks,
+ html/Ticket/Elements/ShowMemberOf,
+ html/Ticket/Elements/ShowMembers,
+ html/Ticket/Elements/ShowMessageHeaders,
+ html/Ticket/Elements/ShowMessageStanza,
+ html/Ticket/Elements/ShowPeople,
+ html/Ticket/Elements/ShowReferences,
+ html/Ticket/Elements/ShowRequestor,
+ html/Ticket/Elements/ShowSummary,
+ html/Ticket/Elements/ShowTransaction, html/Ticket/Elements/Tabs,
+ html/User/Delegation.html, html/User/Prefs.html,
+ html/User/Elements/DelegateRights, html/User/Elements/GroupTabs,
+ html/User/Elements/Tabs, html/User/Groups/Members.html,
+ html/User/Groups/Modify.html, html/User/Groups/index.html,
+ lib/RT.pm.in, lib/RT/ACE_Overlay.pm, lib/RT/ACL_Overlay.pm,
+ lib/RT/Attachment_Overlay.pm, lib/RT/Attachments_Overlay.pm,
+ lib/RT/Base.pm, lib/RT/CachedGroupMember.pm,
+ lib/RT/CachedGroupMember_Overlay.pm,
+ lib/RT/CachedGroupMembers.pm,
+ lib/RT/CachedGroupMembers_Overlay.pm, lib/RT/CustomField.pm,
+ lib/RT/CustomFieldValue.pm, lib/RT/CustomFieldValues.pm,
+ lib/RT/CustomFieldValues_Overlay.pm,
+ lib/RT/CustomField_Overlay.pm, lib/RT/CustomFields.pm,
+ lib/RT/CustomFields_Overlay.pm, lib/RT/EmailParser.pm,
+ lib/RT/GroupMember_Overlay.pm, lib/RT/GroupMembers_Overlay.pm,
+ lib/RT/Group_Overlay.pm, lib/RT/Groups_Overlay.pm,
+ lib/RT/I18N.pm, lib/RT/Link_Overlay.pm, lib/RT/Links_Overlay.pm,
+ lib/RT/Principal.pm, lib/RT/Principal_Overlay.pm,
+ lib/RT/Principals.pm, lib/RT/Principals_Overlay.pm,
+ lib/RT/Queue_Overlay.pm, lib/RT/Queues_Overlay.pm,
+ lib/RT/ScripAction_Overlay.pm, lib/RT/ScripActions_Overlay.pm,
+ lib/RT/ScripCondition_Overlay.pm,
+ lib/RT/ScripConditions_Overlay.pm, lib/RT/Scrip_Overlay.pm,
+ lib/RT/Scrips_Overlay.pm, lib/RT/SearchBuilder.pm,
+ lib/RT/System.pm, lib/RT/Template_Overlay.pm,
+ lib/RT/Templates_Overlay.pm, lib/RT/TicketCustomFieldValue.pm,
+ lib/RT/TicketCustomFieldValue_Overlay.pm,
+ lib/RT/TicketCustomFieldValues.pm,
+ lib/RT/TicketCustomFieldValues_Overlay.pm,
+ lib/RT/Ticket_Overlay.pm, lib/RT/Tickets_Overlay.pm,
+ lib/RT/Tickets_Overlay_SQL.pm, lib/RT/Transaction_Overlay.pm,
+ lib/RT/Transactions_Overlay.pm, lib/RT/URI.pm,
+ lib/RT/User_Overlay.pm, lib/RT/Users_Overlay.pm,
+ lib/RT/Action/AutoOpen.pm, lib/RT/Action/CreateTickets.pm,
+ lib/RT/Action/EscalatePriority.pm, lib/RT/Action/SetPriority.pm,
+ lib/RT/Action/UserDefined.pm, lib/RT/Condition/BeforeDue.pm,
+ lib/RT/Condition/Overdue.pm, lib/RT/Condition/OwnerChange.pm,
+ lib/RT/Condition/PriorityExceeds.pm,
+ lib/RT/Condition/QueueChange.pm, lib/RT/Condition/UserDefined.pm,
+ lib/RT/I18N/cs.pm, lib/RT/I18N/cs.po, lib/RT/I18N/de.po,
+ lib/RT/I18N/en.po, lib/RT/I18N/es.po, lib/RT/I18N/fi.po,
+ lib/RT/I18N/fr.po, lib/RT/I18N/he.po, lib/RT/I18N/i_default.pm,
+ lib/RT/I18N/ja.po, lib/RT/I18N/nl.po, lib/RT/I18N/no.po,
+ lib/RT/I18N/pt_br.po, lib/RT/I18N/ru.po, lib/RT/I18N/zh_cn.po,
+ lib/RT/I18N/zh_tw.po, lib/RT/Interface/Email/Auth/MailFrom.pm,
+ lib/RT/Interface/Email/Filter/SpamAssassin.pm,
+ lib/RT/Search/ActiveTicketsInQueue.pm, lib/RT/Search/Generic.pm,
+ lib/RT/URI/base.pm, lib/RT/URI/fsck_com_rt.pm, lib/t/00smoke.t,
+ lib/t/00smoke.t.in, lib/t/01harness.t, lib/t/01harness.t.in,
+ lib/t/02regression.t, lib/t/02regression.t.in, lib/t/03web.pl,
+ lib/t/03web.pl.in, lib/t/04_send_email.pl,
+ lib/t/04_send_email.pl.in,
+ lib/t/data/multipart-alternative-with-umlaut,
+ lib/t/data/nested-mime-sample, lib/t/data/nested-rfc-822,
+ lib/t/data/new-ticket-from-iso-8859-1,
+ lib/t/data/new-ticket-from-iso-8859-1-full,
+ lib/t/data/russian-subject-no-content-type,
+ lib/t/data/text-html-in-russian,
+ lib/t/data/text-html-with-umlaut,
+ lib/t/data/8859-15-message-series/dir,
+ lib/t/data/8859-15-message-series/msg1,
+ lib/t/data/8859-15-message-series/msg2,
+ lib/t/data/8859-15-message-series/msg3,
+ lib/t/data/8859-15-message-series/msg4,
+ lib/t/data/8859-15-message-series/msg5,
+ lib/t/data/8859-15-message-series/msg6,
+ lib/t/data/8859-15-message-series/msg7,
+ lib/t/regression/00placeholder, lib/t/regression/mime_tests,
+ m4/rt_enable_layout.m4, m4/rt_expand_var.m4, m4/rt_layout.m4,
+ m4/rt_subst_expanded_arg.m4, sbin/extract-message-catalog,
+ sbin/extract_pod_tests, sbin/factory, sbin/license_tag,
+ sbin/regression_harness, sbin/rt-setup-database,
+ sbin/rt-setup-database.in, sbin/rt-test-dependencies.in,
+ autom4te.cache/output.0, autom4te.cache/requests,
+ autom4te.cache/traces.0, sbin/rt-test-dependencies: Initial
+ revision
+
+2003-07-15 04:44 ivan
+
+ * sql-ledger/: VERSION, am.pl, favicon.ico, login.pl, menu.ini,
+ setup.pl, sql-ledger.conf.default, sql-ledger.png, SL/AM.pm,
+ SL/AP.pm, SL/AR.pm, SL/CT.pm, SL/Form.pm, SL/GL.pm, SL/IC.pm,
+ SL/IR.pm, SL/IS.pm, SL/User.pm, SL/CA.pm, SL/CP.pm,
+ SL/Inifile.pm, SL/Mailer.pm, SL/Menu.pm, SL/Num2text.pm,
+ SL/OE.pm, SL/PE.pm, SL/RC.pm, SL/RP.pm, bin/lynx/menu.pl,
+ bin/mozilla/admin.pl, bin/mozilla/am.pl, bin/mozilla/ap.pl,
+ bin/mozilla/ar.pl, bin/mozilla/ca.pl, bin/mozilla/ct.pl,
+ bin/mozilla/gl.pl, bin/mozilla/ic.pl, bin/mozilla/io.pl,
+ bin/mozilla/ir.pl, bin/mozilla/login.pl, bin/mozilla/menu.pl,
+ bin/mozilla/arap.pl, bin/mozilla/cp.pl, bin/mozilla/is.pl,
+ bin/mozilla/oe.pl, bin/mozilla/pe.pl, bin/mozilla/rc.pl,
+ bin/mozilla/rp.pl, css/sql-ledger.css, doc/COPYING, doc/README,
+ doc/UPGRADE-1.6-1.8, doc/UPGRADE-1.8-1.8.3,
+ doc/UPGRADE-1.8.3-1.8.4, doc/UPGRADE-1.8.4-1.8.5,
+ doc/UPGRADE-1.8.5-1.8.7, doc/UPGRADE-1.8.7-2.0.0,
+ doc/UPGRADE-2.0-2.0.8, doc/copyright, doc/faq.html,
+ locale/de/admin, locale/de/COPYING, locale/de/LANGUAGE,
+ locale/de/Num2text, locale/de/all, locale/de/am, locale/de/ap,
+ locale/de/ar, locale/de/arap, locale/de/ca, locale/de/cp,
+ locale/de/ct, locale/de/gl, locale/de/ic, locale/de/io,
+ locale/de/ir, locale/de/is, locale/de/locales.pl,
+ locale/de/login, locale/de/menu, locale/de/oe, locale/de/pe,
+ locale/de/rc, locale/de/rp, locale/fr/admin, locale/fr/all,
+ locale/fr/am, locale/fr/ap, locale/fr/ar, locale/fr/ca,
+ locale/fr/ct, locale/fr/gl, locale/fr/ic, locale/fr/io,
+ locale/es/COPYING, locale/es/LANGUAGE, locale/es/Num2text,
+ locale/es/admin, locale/es/all, locale/es/am, locale/es/ap,
+ locale/es/ar, locale/es/arap, locale/es/ca, locale/es/cp,
+ locale/es/ct, locale/es/gl, locale/es/ic, locale/es/io,
+ locale/es/ir, locale/es/is, locale/es/login, locale/es/menu,
+ locale/es/oe, locale/es/pe, locale/es/rc, locale/es/rp,
+ locale/fr/COPYING, locale/fr/LANGUAGE, locale/fr/arap,
+ locale/fr/cp, locale/fr/ir, locale/fr/is, locale/fr/login,
+ locale/fr/menu, locale/fr/oe, locale/fr/pe, locale/fr/rc,
+ locale/fr/rp, locale/tw/admin, locale/tw/login,
+ locale/dk/LANGUAGE, locale/dk/admin, locale/dk/all, locale/dk/am,
+ locale/dk/ap, locale/dk/ar, locale/dk/arap, locale/dk/ca,
+ locale/dk/ct, locale/dk/gl, locale/dk/ic, locale/dk/io,
+ locale/dk/ir, locale/dk/is, locale/dk/login, locale/dk/menu,
+ locale/dk/oe, locale/dk/rp, locale/tw/COPYING,
+ locale/tw/LANGUAGE, locale/tw/all, locale/tw/am, locale/tw/ap,
+ locale/tw/ar, locale/tw/arap, locale/tw/ca, locale/tw/cp,
+ locale/tw/ct, locale/tw/gl, locale/tw/ic, locale/tw/io,
+ locale/tw/ir, locale/tw/is, locale/tw/menu, locale/tw/oe,
+ locale/tw/pe, locale/tw/rc, locale/tw/rp, locale/br/COPYING,
+ locale/br/LANGUAGE, locale/br/admin, locale/br/all, locale/br/am,
+ locale/br/ap, locale/br/ar, locale/br/arap, locale/br/ca,
+ locale/br/cp, locale/br/ct, locale/br/gl, locale/br/ic,
+ locale/br/io, locale/br/ir, locale/br/is, locale/br/login,
+ locale/br/menu, locale/br/oe, locale/br/pe, locale/br/rc,
+ locale/br/rp, locale/dk/COPYING, locale/dk/cp, locale/dk/pe,
+ locale/dk/rc, locale/it/admin, locale/it/ap, locale/it/ar,
+ locale/it/ca, locale/it/ct, locale/it/gl, locale/it/ic,
+ locale/it/ir, locale/it/menu, locale/ct/COPYING,
+ locale/ct/LANGUAGE, locale/ct/admin, locale/ct/all, locale/ct/am,
+ locale/ct/ap, locale/ct/ar, locale/ct/ca, locale/ct/ct,
+ locale/ct/gl, locale/ct/ic, locale/ct/io, locale/ct/ir,
+ locale/ct/is, locale/ct/login, locale/ct/menu, locale/ct/oe,
+ locale/ct/rp, locale/it/COPYING, locale/it/LANGUAGE,
+ locale/it/Num2text, locale/it/all, locale/it/am, locale/it/arap,
+ locale/it/cp, locale/it/io, locale/it/is, locale/it/login,
+ locale/it/oe, locale/it/pe, locale/it/qe, locale/it/rc,
+ locale/it/rp, locale/ct/arap, locale/ct/cp, locale/ct/pe,
+ locale/ct/rc, locale/ee/COPYING, locale/ee/LANGUAGE,
+ locale/ee/admin, locale/ee/all, locale/ee/am, locale/ee/ap,
+ locale/ee/ar, locale/ee/arap, locale/ee/ca, locale/ee/cp,
+ locale/ee/ct, locale/ee/gl, locale/ee/ic, locale/ee/io,
+ locale/ee/ir, locale/ee/is, locale/ee/login, locale/ee/menu,
+ locale/ee/oe, locale/ee/pe, locale/ee/rc, locale/ee/rp,
+ locale/nl/admin, locale/nl/all, locale/nl/am, locale/nl/ap,
+ locale/nl/ar, locale/nl/ca, locale/nl/ct, locale/nl/gl,
+ locale/nl/COPYING, locale/nl/LANGUAGE, locale/nl/Num2text,
+ locale/nl/arap, locale/nl/cp, locale/nl/ic, locale/nl/io,
+ locale/nl/ir, locale/nl/is, locale/nl/login, locale/nl/menu,
+ locale/nl/oe, locale/nl/pe, locale/nl/rc, locale/nl/rp,
+ locale/no/COPYING, locale/no/LANGUAGE, locale/no/admin,
+ locale/no/all, locale/no/am, locale/no/ap, locale/no/ar,
+ locale/no/arap, locale/no/ca, locale/no/cp, locale/no/ct,
+ locale/no/gl, locale/no/ic, locale/no/io, locale/no/ir,
+ locale/no/is, locale/no/login, locale/no/menu, locale/no/oe,
+ locale/no/pe, locale/no/rc, locale/no/rp, locale/tr/COPYING,
+ locale/tr/LANGUAGE, locale/tr/admin, locale/tr/all, locale/tr/am,
+ locale/tr/ap, locale/tr/ar, locale/tr/arap, locale/tr/ca,
+ locale/tr/cp, locale/tr/ct, locale/tr/gl, locale/tr/ic,
+ locale/tr/io, locale/tr/ir, locale/tr/is, locale/tr/login,
+ locale/tr/menu, locale/tr/oe, locale/tr/pe, locale/tr/rc,
+ locale/tr/rp, locale/ve/COPYING, locale/ve/admin, locale/ve/all,
+ locale/ve/am, locale/ve/ap, locale/ve/ar, locale/ve/ca,
+ locale/ve/ct, locale/ve/gl, locale/ve/ic, locale/ve/ir,
+ locale/ve/is, locale/ve/login, locale/ve/rp, locale/cz/admin,
+ locale/cz/all, locale/cz/am, locale/pa/COPYING,
+ locale/pa/LANGUAGE, locale/pa/admin, locale/pa/all, locale/pa/am,
+ locale/pa/ap, locale/pa/ar, locale/pa/arap, locale/pa/ca,
+ locale/pa/cp, locale/pa/ct, locale/pa/gl, locale/pa/ic,
+ locale/pa/io, locale/pa/ir, locale/pa/is, locale/pa/login,
+ locale/pa/menu, locale/pa/oe, locale/pa/pe, locale/pa/rc,
+ locale/pa/rp, locale/ve/LANGUAGE, locale/ve/arap, locale/ve/cp,
+ locale/ve/io, locale/ve/menu, locale/ve/oe, locale/ve/pe,
+ locale/ve/rc, locale/cz/COPYING, locale/cz/LANGUAGE,
+ locale/cz/ap, locale/cz/ar, locale/cz/arap, locale/cz/ca,
+ locale/cz/cp, locale/cz/ct, locale/cz/gl, locale/cz/ic,
+ locale/cz/io, locale/cz/ir, locale/cz/is, locale/cz/login,
+ locale/cz/menu, locale/cz/oe, locale/cz/pe, locale/cz/rc,
+ locale/cz/rp, locale/pt/COPYING, locale/pt/LANGUAGE,
+ locale/pt/admin, locale/pt/all, locale/pt/am, locale/pt/ap,
+ locale/pt/ar, locale/pt/arap, locale/pt/ca, locale/pt/cp,
+ locale/pt/ct, locale/pt/gl, locale/pt/ic, locale/pt/io,
+ locale/pt/ir, locale/pt/is, locale/pt/login, locale/pt/menu,
+ locale/pt/oe, locale/pt/pe, locale/pt/rc, locale/pt/rp,
+ locale/cn/COPYING, locale/cn/LANGUAGE, locale/cn/admin,
+ locale/cn/all, locale/cn/am, locale/cn/ap, locale/cn/ar,
+ locale/cn/arap, locale/cn/ca, locale/cn/cp, locale/cn/ct,
+ locale/cn/gl, locale/cn/ic, locale/cn/io, locale/cn/ir,
+ locale/cn/is, locale/cn/login, locale/cn/menu, locale/cn/oe,
+ locale/cn/pe, locale/cn/rc, locale/cn/rp, locale/pl/admin,
+ locale/pl/all, locale/pl/am, locale/pl/ap, locale/pl/ar,
+ locale/pl/ca, locale/pl/ct, locale/pl/gl, locale/pl/ic,
+ locale/pl/ir, locale/fi/COPYING, locale/fi/LANGUAGE,
+ locale/fi/admin, locale/fi/all, locale/mx/COPYING,
+ locale/mx/LANGUAGE, locale/mx/admin, locale/mx/all, locale/mx/am,
+ locale/mx/ap, locale/mx/ar, locale/mx/arap, locale/mx/ca,
+ locale/mx/cp, locale/mx/ct, locale/mx/gl, locale/mx/ic,
+ locale/mx/io, locale/mx/ir, locale/mx/is, locale/mx/login,
+ locale/mx/menu, locale/mx/oe, locale/mx/pe, locale/mx/rc,
+ locale/mx/rp, locale/pl/COPYING, locale/pl/LANGUAGE,
+ locale/pl/arap, locale/pl/cp, locale/pl/io, locale/pl/is,
+ locale/pl/login, locale/pl/menu, locale/pl/oe, locale/pl/pe,
+ locale/pl/rc, locale/pl/rp, locale/fi/am, locale/fi/ap,
+ locale/fi/ar, locale/fi/arap, locale/fi/ca, locale/fi/cp,
+ locale/fi/ct, locale/fi/gl, locale/fi/ic, locale/fi/io,
+ locale/fi/ir, locale/fi/is, locale/fi/login, locale/fi/menu,
+ locale/fi/oe, locale/fi/pe, locale/fi/rc, locale/fi/rp,
+ locale/ua/COPYING, locale/ua/LANGUAGE, locale/ua/admin,
+ locale/ua/all, locale/ua/am, locale/ua/ap, locale/hu/COPYING,
+ locale/hu/LANGUAGE, locale/hu/admin, locale/hu/all, locale/hu/am,
+ locale/hu/ap, locale/ua/ar, locale/ua/arap, locale/ua/ca,
+ locale/ua/cp, locale/ua/ct, locale/ua/gl, locale/ua/ic,
+ locale/ua/io, locale/ua/ir, locale/ua/is, locale/ua/login,
+ locale/ua/menu, locale/ua/oe, locale/ua/pe, locale/ua/rc,
+ locale/ua/rp, locale/hu/ar, locale/hu/arap, locale/hu/ca,
+ locale/hu/cp, locale/hu/ct, locale/hu/gl, locale/hu/ic,
+ locale/hu/io, locale/hu/ir, locale/hu/is, locale/hu/login,
+ locale/hu/menu, locale/hu/oe, locale/hu/pe, locale/hu/rc,
+ locale/hu/rp, locale/is/COPYING, locale/is/LANGUAGE,
+ locale/is/all, locale/is/admin, locale/is/am, locale/is/ap,
+ locale/is/ar, locale/is/arap, locale/is/ca, locale/is/cp,
+ locale/is/ct, locale/is/gl, locale/is/ic, locale/is/io,
+ locale/is/ir, locale/is/is, locale/is/login, locale/is/menu,
+ locale/is/oe, locale/is/pe, locale/is/rc, locale/is/rp,
+ locale/ru/COPYING, locale/ru/LANGUAGE, locale/ru/all,
+ locale/ru/admin, locale/ru/am, locale/ru/ap, locale/ru/ar,
+ locale/ru/arap, locale/ru/ca, locale/ru/cp, locale/ru/ct,
+ locale/ru/gl, locale/ru/ic, locale/ru/io, locale/ru/ir,
+ locale/ru/is, locale/ru/login, locale/ru/menu, locale/ru/oe,
+ locale/ru/pe, locale/ru/rc, locale/ru/rp, locale/se/COPYING,
+ locale/se/LANGUAGE, locale/se/admin, locale/se/all,
+ locale/lt/COPYING, locale/lt/LANGUAGE, locale/lt/admin,
+ locale/lt/all, locale/se/am, locale/se/ap, locale/se/ar,
+ locale/se/arap, locale/se/ca, locale/se/cp, locale/se/ct,
+ locale/se/gl, locale/se/ic, locale/se/io, locale/se/ir,
+ locale/se/is, locale/se/login, locale/se/menu, locale/se/oe,
+ locale/se/pe, locale/se/rc, locale/se/rp, locale/en_GB/admin,
+ locale/en_GB/am, locale/en_GB/ap, locale/en_GB/ar,
+ locale/en_GB/ca, locale/en_GB/ct, locale/en_GB/gl, locale/lt/am,
+ locale/lt/ap, locale/lt/ar, locale/lt/arap, locale/lt/ca,
+ locale/lt/cp, locale/lt/ct, locale/lt/gl, locale/lt/ic,
+ locale/lt/io, locale/lt/ir, locale/lt/is, locale/lt/login,
+ locale/lt/menu, locale/lt/oe, locale/lt/pe, locale/lt/rc,
+ locale/lt/rp, locale/en_GB/COPYING, locale/en_GB/LANGUAGE,
+ locale/en_GB/all, locale/en_GB/arap, locale/en_GB/bp,
+ locale/en_GB/cp, locale/en_GB/ic, locale/en_GB/io,
+ locale/en_GB/ir, locale/en_GB/is, locale/en_GB/login,
+ locale/en_GB/menu, locale/en_GB/oe, locale/en_GB/pe,
+ locale/en_GB/rc, locale/en_GB/rp, sql/Default-chart.sql,
+ sql/Oracle-tables.sql, sql/Pg-tables.sql, sql/Canada-gifi.sql,
+ sql/Danish_Default-chart.sql, sql/Dutch_Default-chart.sql,
+ sql/France-chart.sql, sql/Italy-chart.sql,
+ sql/Oracle-indices.sql, sql/Pg-indices.sql,
+ sql/Pg-upgrade-1.6.0-1.8.0.sql,
+ sql/Simplified_Chinese_Default-chart.sql, sql/Spain-chart.sql,
+ sql/Traditional_Chinese_Default-chart.sql, sql/Austria-chart.sql,
+ sql/Austria-gifi.sql, sql/Canada_General-chart.sql,
+ sql/Czech_Republic-chart.sql, sql/Dutch_Standard-chart.sql,
+ sql/German-Sample-chart.sql, sql/German-Sample-gifi.sql,
+ sql/Oracle-upgrade-1.8.0-1.8.4.sql,
+ sql/Oracle-upgrade-1.8.4-1.8.5.sql,
+ sql/Pg-upgrade-1.2.6-1.2.7.sql, sql/Pg-upgrade-1.2.7-1.4.0.sql,
+ sql/Pg-upgrade-1.4.0-1.6.0.sql, sql/Pg-upgrade-1.8.0-1.8.4.sql,
+ sql/Pg-upgrade-1.8.4-1.8.5.sql, sql/Swiss-German-chart.sql,
+ sql/Swiss-German-gifi.sql, sql/US_General-chart.sql,
+ sql/Germany-DATEV-SKR03-gifi.sql, sql/Germany-SKR03-chart.sql,
+ sql/Germany-SKR03-gifi.sql, sql/Pg-upgrade-1.8.5-2.0.0.sql,
+ sql/Brazil_General-chart.sql, sql/Germany-DATEV-SKR03-chart.sql,
+ sql/Oracle-upgrade-1.8.5-2.0.0.sql,
+ sql/Oracle-upgrade-2.0.0-2.0.8.sql,
+ sql/Pg-upgrade-2.0.0-2.0.8.sql, sql/Poland-chart.sql,
+ templates/Danish-balance_sheet.html,
+ templates/Danish-income_statement.html,
+ templates/Danish-invoice.html, templates/Danish-invoice.tex,
+ templates/Danish-packing_list.html,
+ templates/Danish-packing_list.tex,
+ templates/Danish-purchase_order.html,
+ templates/Danish-purchase_order.tex,
+ templates/Danish-sales_order.html,
+ templates/Danish-sales_order.tex,
+ templates/Default-balance_sheet.html,
+ templates/Default-income_statement.html,
+ templates/Default-invoice.html,
+ templates/Estonian-balance_sheet.html,
+ templates/Estonian-income_statement.html,
+ templates/French-balance_sheet.html,
+ templates/French-income_statement.html,
+ templates/French-invoice.html,
+ templates/French-packing_list.html,
+ templates/Service-balance_sheet.html,
+ templates/Service-income_statement.html,
+ templates/Service-invoice.html, templates/Service-invoice.tex,
+ templates/Service-packing_list.html,
+ templates/Service-packing_list.tex,
+ templates/Service-purchase_order.tex,
+ templates/Service-sales_order.tex,
+ templates/Spanish_A4-balance_sheet.html,
+ templates/Spanish_A4-income_statement.html,
+ templates/Spanish_A4-invoice.html,
+ templates/Spanish_A4-invoice.tex,
+ templates/Spanish_A4-packing_list.html,
+ templates/Spanish_A4-packing_list.tex,
+ templates/Spanish_A4-purchase_order.html,
+ templates/Spanish_A4-purchase_order.tex,
+ templates/Spanish_A4-sales_order.html,
+ templates/Spanish_A4-sales_order.tex,
+ templates/Spanish_Letter-balance_sheet.html,
+ templates/Spanish_Letter-income_statement.html,
+ templates/Spanish_Letter-invoice.html,
+ templates/Spanish_Letter-invoice.tex,
+ templates/Spanish_Letter-packing_list.html,
+ templates/Spanish_Letter-packing_list.tex,
+ templates/Spanish_Letter-purchase_order.html,
+ templates/Spanish_Letter-purchase_order.tex,
+ templates/Spanish_Letter-sales_order.html,
+ templates/Spanish_Letter-sales_order.tex, users/members.default,
+ templates/Brazilian_Portuguese-check.tex,
+ templates/Danish-check.tex, templates/Danish-receipt.tex,
+ templates/Danish-statement.html, templates/Danish-statement.tex,
+ templates/Default-check.tex, templates/Default-invoice.tex,
+ templates/Default-packing_list.html,
+ templates/Default-packing_list.tex,
+ templates/Default-purchase_order.html,
+ templates/Default-purchase_order.tex,
+ templates/Default-receipt.tex,
+ templates/Default-sales_order.html,
+ templates/Default-sales_order.tex,
+ templates/Default-statement.html,
+ templates/Default-statement.tex,
+ templates/Dutch-balance_sheet.html, templates/Dutch-check.tex,
+ templates/Dutch-income_statement.html,
+ templates/Dutch-invoice.html, templates/Dutch-invoice.tex,
+ templates/Dutch-packing_list.html,
+ templates/Dutch-packing_list.tex,
+ templates/Dutch-purchase_order.html,
+ templates/Dutch-purchase_order.tex, templates/Dutch-receipt.tex,
+ templates/Dutch-sales_order.html,
+ templates/Dutch-sales_order.tex, templates/Dutch-statement.html,
+ templates/Dutch-statement.tex, templates/Estonian-check.tex,
+ templates/Estonian-invoice.html, templates/Estonian-invoice.tex,
+ templates/Estonian-packing_list.html,
+ templates/Estonian-packing_list.tex,
+ templates/Estonian-purchase_order.html,
+ templates/Estonian-purchase_order.tex,
+ templates/Estonian-receipt.tex,
+ templates/Estonian-sales_order.html,
+ templates/Estonian-sales_order.tex,
+ templates/Estonian-statement.html,
+ templates/Estonian-statement.tex, templates/French-check.tex,
+ templates/French-invoice.tex, templates/French-packing_list.tex,
+ templates/French-purchase_order.html,
+ templates/French-purchase_order.tex,
+ templates/French-receipt.tex, templates/French-sales_order.html,
+ templates/French-sales_order.tex,
+ templates/French-statement.html, templates/French-statement.tex,
+ templates/German-balance_sheet.html, templates/German-check.tex,
+ templates/German-income_statement.html,
+ templates/German-invoice.html, templates/German-invoice.tex,
+ templates/German-packing_list.html,
+ templates/German-packing_list.tex,
+ templates/German-purchase_order.html,
+ templates/German-purchase_order.tex,
+ templates/German-receipt.tex, templates/German-sales_order.html,
+ templates/German-sales_order.tex,
+ templates/German-statement.html, templates/German-statement.tex,
+ templates/Service-check.tex,
+ templates/Service-purchase_order.html,
+ templates/Service-receipt.tex,
+ templates/Service-sales_order.html,
+ templates/Service-statement.html,
+ templates/Service-statement.tex, templates/Spanish_A4-check.tex,
+ templates/Spanish_A4-receipt.tex,
+ templates/Spanish_A4-statement.html,
+ templates/Spanish_A4-statement.tex,
+ templates/Spanish_Letter-check.tex,
+ templates/Spanish_Letter-receipt.tex,
+ templates/Spanish_Letter-statement.html,
+ templates/Spanish_Letter-statement.tex,
+ templates/Brazilian_Portuguese-balance_sheet.html,
+ templates/Brazilian_Portuguese-income_statement.html,
+ templates/Brazilian_Portuguese-invoice.html,
+ templates/Brazilian_Portuguese-invoice.tex,
+ templates/Brazilian_Portuguese-packing_list.html,
+ templates/Brazilian_Portuguese-packing_list.tex,
+ templates/Brazilian_Portuguese-purchase_order.html,
+ templates/Brazilian_Portuguese-purchase_order.tex,
+ templates/Brazilian_Portuguese-receipt.tex,
+ templates/Brazilian_Portuguese-sales_order.html,
+ templates/Brazilian_Portuguese-sales_order.tex,
+ templates/Brazilian_Portuguese-statement.html,
+ templates/Brazilian_Portuguese-statement.tex: Initial revision
+
+2003-07-15 04:23 ivan
+
+ * Makefile: 1.5.0pre3
+
+2003-07-13 23:21 ivan
+
+ * httemplate/search/cust_pay.cgi: fix bug when both a payment type
+ and date range are specified
+
+2003-07-12 04:14 ivan
+
+ * httemplate/index.html: remove Gratuitous capitalization
+
+2003-07-12 04:09 ivan
+
+ * httemplate/: index.html, browse/part_pkg.cgi,
+ browse/part_svc.cgi, search/cust_pkg.cgi: - better description of
+ payment search - some clarification of services/packages vs.
+ service/package definitions in browse/part_{svc,pkg}.cgi -
+ package definition report by # of active customer packages (with
+ links to customer package listing)
+
+2003-07-11 08:37 ivan
+
+ * FS/FS/cust_main.pm: fix timelocal AUTOLOAD problem introduced by
+ Time::Local fix in rc3 (closes: Bug#550)
+
+2003-07-11 08:23 ivan
+
+ * httemplate/: index.html, search/cust_pay.cgi,
+ search/cust_pkg.cgi, search/report_cust_pay.html: payments report
+ for inventivemedia / hpnx
+
+2003-07-11 00:54 ivan
+
+ * FS/FS/Record.pm: typo
+
+2003-07-11 00:30 ivan
+
+ * FS/FS/Record.pm: provide stack backtrace when we wind up in
+ FS::Record::AUTOLOAD by accident
+
+2003-07-09 07:39 ivan
+
+ * httemplate/edit/svc_domain.cgi: increase max domain length to 63
+
+2003-07-06 11:58 ivan
+
+ * httemplate/view/cust_main.cgi: don't bother displaying comments
+ that are only whitespace/newlines
+
+2003-07-03 20:47 ivan
+
+ * fs_signup/FS-SignupClient/cgi/stateselect.html: adding
+
+2003-07-03 20:34 ivan
+
+ * etc/acp_logfile-parse: removing obsolete file
+
+2003-07-03 20:31 ivan
+
+ * etc/abbr_state.txt: adding states
+
+2003-07-03 20:27 ivan
+
+ * etc/example-direct-cardin: removing ancient cybercash example
+
+2003-07-03 20:21 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: properly pass
+ init_popstate to error pages
+
+2003-07-03 20:12 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: add "initial_popstate"
+ option to signup server
+
+2003-07-03 18:54 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: don't add extra blank
+ pop
+
+2003-07-03 18:48 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: typo
+
+2003-07-03 18:37 ivan
+
+ * FS/FS/svc_acct_pop.pm, fs_signup/FS-SignupClient/cgi/signup.cgi:
+ don't populate the whole initial list if there are tons of POPs
+
+2003-07-03 17:51 ivan
+
+ * FS/FS/svc_acct_pop.pm, fs_signup/FS-SignupClient/cgi/signup.cgi:
+ optimize javascript to handle large numbers of POPs
+
+2003-07-03 16:00 ivan
+
+ * htetc/global.asa: working DBIx::Profile again
+
+2003-07-02 05:58 ivan
+
+ * FS/FS/part_pkg.pm: tyop
+
+2003-07-02 05:56 ivan
+
+ * FS/FS/part_pkg.pm, fs_signup/fs_signup_server: relaxed "first
+ package" restrictions; will find any appropriate service with
+ quantity 1
+
+2003-07-02 05:34 ivan
+
+ * Artistic, README: change license to GPL only
+
+2003-07-01 02:00 ivan
+
+ * httemplate/edit/part_export.cgi: larger textareas in export
+ options
+
+2003-06-30 17:27 ivan
+
+ * FS/FS/part_export.pm: typo
+
+2003-06-30 12:15 ivan
+
+ * FS/FS/cust_main.pm: bugfix for manual re-charging changes
+ (Bug#423)
+
+2003-06-30 11:56 ivan
+
+ * FS/FS/cust_main.pm: pass additional fields to ACH processors
+ (Authorize.Net should work now)
+
+2003-06-30 06:18 ivan
+
+ * FS/: MANIFEST, bin/freeside-overdue: removing deprecated
+ freeside-overdue
+
+2003-06-30 05:22 ivan
+
+ * FS/: FS/part_export.pm, FS/part_export/sqlradius.pm,
+ FS/part_export/sqlradius_withdomain.pm,
+ bin/freeside-sqlradius-reset,
+ t/part_export-sqlradius_withdomain.t: adding sqlradius_withdomain
+ export including realms, closes: bug#514
+
+2003-06-30 00:44 ivan
+
+ * FS/FS/svc_domain.pm: increase maximum domain length to 67
+
+2003-06-27 07:19 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add radius-ip configuration
+ parameter for Framed-IP-Address vs. Framed-Address
+
+2003-06-25 03:22 ivan
+
+ * httemplate/search/cust_bill_event.cgi: Pg 7.3 incompatibility
+ with empty dates in Failed Invoice Event search, patch from
+ rlucas@tercent.net
+
+2003-06-25 01:40 ivan
+
+ * FS/FS/: svc_acct.pm, part_export/cp.pm: svc_acct doc update cp
+ export - disable old-style suspending
+
+2003-06-24 17:57 ivan
+
+ * FS/FS/part_export/forward_shellcommands.pm: forward_shellcommands
+ update: might work now
+
+2003-06-24 08:34 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: display full POP
+ numbers in signup server - patch from "Stephen Bechard"
+ <steve@destek.net>
+
+2003-06-24 07:12 ivan
+
+ * FS/FS/part_export/: forward_shellcommands.pm, sqlmail.pm:
+ explicitly use the necessary modules
+
+2003-06-22 07:21 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/bill.cgi: fix the credit card
+ retry on change or manual "retry_card" to ONCE per invoice
+
+2003-06-22 02:11 ivan
+
+ * bin/create-history-tables: skip pg_ tables also (ewww, showing up
+ in reverse-engineered schema)
+
+2003-06-22 02:04 ivan
+
+ * bin/create-history-tables: skip history tables that exist
+ already; easier to re-run now
+
+2003-06-13 19:04 ivan
+
+ * httemplate/docs/upgrade9.html: cust_bill2 index
+
+2003-06-13 19:02 ivan
+
+ * FS/bin/freeside-setup: add index on cust_bill._date
+
+2003-06-13 18:01 ivan
+
+ * bin/apache.export: \n\n between virtualhost entries
+
+2003-06-13 08:18 ivan
+
+ * FS/FS/part_export/shellcommands.pm: $new_quoted_password vs.
+ $quoted_new__password
+
+2003-06-13 02:12 ivan
+
+ * FS/FS/part_export.pm: proper command escape for vpopmail export
+
+2003-06-13 01:46 ivan
+
+ * httemplate/edit/part_export.cgi: missing semi
+
+2003-06-13 01:44 ivan
+
+ * httemplate/edit/part_export.cgi: correct stickiness for checkbox
+ options on export edit
+
+2003-06-13 01:38 ivan
+
+ * FS/FS/part_export.pm: pass vpopmail passwords on command-line
+ (unfortunately)
+
+2003-06-13 01:23 ivan
+
+ * FS/FS/part_export.pm: full path to vpopmail commands
+
+2003-06-13 01:11 ivan
+
+ * FS/FS/: part_export.pm, part_export/shellcommands.pm: add
+ vpopmail presets to shellcommands_withdomain export
+
+2003-06-12 07:08 ivan
+
+ * bin/passwd.import: /bin/halt and /sbin/halt
+
+2003-06-12 07:06 ivan
+
+ * bin/passwd.import: tyop
+
+2003-06-12 06:57 ivan
+
+ * bin/passwd.import: better error handling for re-imports
+
+2003-06-12 06:50 ivan
+
+ * bin/fix-sequences: remove overly-verbose debugging for now
+
+2003-06-12 06:50 ivan
+
+ * bin/fix-sequences: "doc"
+
+2003-06-12 06:49 ivan
+
+ * bin/fix-sequences: arg
+
+2003-06-12 06:47 ivan
+
+ * bin/fix-sequences: debugging
+
+2003-06-12 06:43 ivan
+
+ * bin/fix-sequences: update for long table names; use sequence name
+ directly instead of guessing
+
+2003-06-12 06:35 ivan
+
+ * bin/fix-sequences: moo
+
+2003-06-12 06:32 ivan
+
+ * bin/fix-sequences: adding fix-sequences
+
+2003-06-12 05:57 ivan
+
+ * FS/FS/part_export.pm: _default_ default now sets GECOS like the
+ OS-defaults
+
+2003-06-12 05:43 ivan
+
+ * FS/FS/part_export.pm: sqlradius doc update; don't need to allow
+ null OP columns
+
+2003-06-11 13:27 khoff
+
+ * FS/FS/Misc.pm: In scalar context, smtpsend returns the number of
+ addresses that the message was successfully delivered to. I'm
+ assuming 'Debug' causes Net::SMTP to warn the debug output, not
+ return it.
+
+2003-06-11 12:13 khoff
+
+ * FS/FS/Misc.pm: We're passing a list here, not one argument.
+
+2003-06-09 04:11 ivan
+
+ * FS/FS/cust_svc.pm: add "$ignore_quantity" bypass
+
+2003-06-08 17:59 ivan
+
+ * httemplate/docs/install.html: documentation update from "Jesse D.
+ Guardiani" <jesse@wingnet.net>, thanks
+
+2003-06-06 18:58 ivan
+
+ * FS/FS/cust_main.pm: and fix the error message
+
+2003-06-06 18:57 ivan
+
+ * FS/FS/cust_main.pm: really, really give a better error message
+ when used under 5.005 now. really.
+
+2003-06-06 18:47 ivan
+
+ * FS/FS/cust_main.pm: give a better error message regarding
+ Time::Local on old perls. really.
+
+2003-06-06 18:42 ivan
+
+ * FS/FS/cust_main.pm: require Time::Local 1.04 on perls before 5.6
+
+2003-06-06 03:49 ivan
+
+ * FS/FS/part_export/cp.pm: add suspend/unsuspend capability to CP
+ export
+
+2003-06-05 21:42 ivan
+
+ * htetc/global.asa: database profiling bs i should just switch to
+ mason
+
+2003-06-04 17:22 khoff
+
+ * FS/FS/cust_pkg.pm: order/cancel packages rewritten
+
+2003-06-04 09:14 ivan
+
+ * FS/FS/svc_acct.pm: allow empty slipip's
+
+2003-06-04 05:44 ivan
+
+ * httemplate/search/cust_pkg.cgi: fix last bill label
+
+2003-06-03 06:53 ivan
+
+ * httemplate/view/cust_main.cgi: fix provision links
+
+2003-06-03 05:41 ivan
+
+ * FS/FS/: part_export.pm, part_export/cp.pm: minor update to cp
+ export - eliminate redundant "host" parameter
+
+2003-06-03 05:40 ivan
+
+ * Makefile: 1.5.0pre2 (too late, hehe)
+
+2003-06-03 02:34 ivan
+
+ * bin/svc_acct_sm.import: removing (very) deprecated import
+
+2003-06-03 00:54 ivan
+
+ * httemplate/docs/upgrade10.html: upgrade docs
+
+2003-06-02 23:10 ivan
+
+ * httemplate/docs/upgrade10.html: slightly better upgrade docs
+
+2003-06-02 23:09 ivan
+
+ * FS/bin/freeside-setup: use serial for primary keys in new tables
+ too
+
+2003-06-02 22:49 ivan
+
+ * FS/bin/freeside-setup: router.svcnum nullability fix
+
+2003-06-02 07:51 ivan
+
+ * httemplate/view/cust_main.cgi: UI nit
+
+2003-06-02 05:22 ivan
+
+ * FS/FS/cust_pkg.pm: add last_bill field to manpage
+
+2003-05-30 02:40 ivan
+
+ * httemplate/docs/man/FS/part_export/.cvs_is_on_crack: force
+ inclusion of httemplate/docs/man hierarchy
+
+2003-05-30 02:22 ivan
+
+ * FS/FS/part_export/sqlradius.pm: sqlradius exports include "op"
+ field
+
+2003-05-30 01:45 ivan
+
+ * httemplate/docs/ssh.html: doc
+
+2003-05-19 22:43 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/payment_results.html,
+ fs_selfservice/FS-SelfService/cgi/process_payment.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: working
+ self-service self-payments!
+
+2003-05-19 06:54 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: fix up some
+ bugs in processing payments via self-service... appears to be
+ working so far
+
+2003-05-19 06:38 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/process_payment.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: first crack at
+ payment processing with self-service (step two of the process)
+
+2003-05-19 05:00 ivan
+
+ * FS/: MANIFEST, FS/Misc.pm, FS/cust_bill.pm, FS/cust_main.pm,
+ FS/cust_pay.pm, FS/cust_pkg.pm, FS/svc_acct.pm, FS/svc_domain.pm,
+ FS/ClientAPI/MyAccount.pm, t/Misc.t: maintenance: - add
+ FS::Misc with send_email subroutine, remove all duplicate code
+ from various modules - move the realtime_bop from cust_bill
+ to cust_main & change usage slightly. invnum is no longer
+ required. FS::cust_bill::realtime_bop remains as a wrapper.
+ self-service: - fix some syntax errors, make payment UI (step
+ one) really should be working now
+
+2003-05-18 17:15 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/: make_payment.html,
+ selfservice.cgi: processing payments...
+
+2003-05-18 04:44 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/cgi/make_payment.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html: interface for
+ making payments all done
+
+2003-05-18 01:09 ivan
+
+ * fs_selfservice/FS-SelfService/cgi/make_payment.html: forgot this
+ file
+
+2003-05-18 01:08 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm, fs_selfservice/DEPLOY: more
+ self-service make payment UI work
+
+2003-05-17 23:20 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm,
+ fs_selfservice/FS-SelfService/cgi/login.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi: self-service:
+ make payment UI done
+
+2003-05-14 09:51 ivan
+
+ * FS/FS/cust_bill.pm: display recurring custom line items on
+ invoices as well as one-shot ones
+
+2003-05-12 23:01 ivan
+
+ * FS/FS/cust_bill_event.pm: - document missing fields in
+ cust_bill_event
+
+2003-05-12 22:47 ivan
+
+ * FS/FS/addr_block.pm: missing pod =cut at end
+
+2003-05-12 20:22 ivan
+
+ * FS/FS/svc_acct.pm, fs_selfservice/FS-SelfService/cgi/login.html,
+ fs_selfservice/FS-SelfService/cgi/myaccount.html,
+ fs_selfservice/FS-SelfService/cgi/selfservice.cgi,
+ fs_selfservice/FS-SelfService/cgi/view_invoice.html: -
+ self-service updates: cleanup and beginnings of "make a payment"
+ - fix pod masking FS::svc_acct::cust_svc
+
+2003-05-12 00:34 ivan
+
+ * fs_selfservice/FS-SelfService/freeside-selfservice-clientd:
+ setbuf call doesn't appear to be working...
+
+2003-05-12 00:33 ivan
+
+ * httemplate/view/cust_main.cgi: fix service links
+
+2003-05-11 15:55 ivan
+
+ * httemplate/index.html: mail forward search not yet implemented
+
+2003-05-11 15:53 ivan
+
+ * httemplate/search/cust_pkg.cgi: patch from Richard Siddall for
+ strict vars
+
+2003-05-11 15:34 ivan
+
+ * CREDITS, httemplate/view/cust_main.cgi: red here is too confusing
+
+2003-05-11 15:25 ivan
+
+ * htetc/: handler.pl, handler.pl-1.0x: handler.pl updates from
+ Richard Siddall <richard.siddall@elirion.net>
+
+2003-05-09 23:45 ivan
+
+ * httemplate/view/: cust_main.cgi, cust_pkg.cgi: first pass at new
+ package list UI
+
+2003-05-09 22:41 ivan
+
+ * FS/FS/cust_pkg.pm: fix bug in last_bill method which prevented
+ last_bill dates from being set
+
+2003-05-09 22:40 ivan
+
+ * FS/FS/cust_main.pm: - substitute '0' for existing blank
+ setup/recur fees - use timelocal_nocheck instead of timelocal for
+ proper wraparound
+
+2003-05-09 12:30 khoff
+
+ * httemplate/view/cust_main.cgi: Cleaned-up package view code and
+ added CSS tags.
+
+2003-05-09 00:17 ivan
+
+ * install/freebsd/ports: mod_ssl before mod_perl so mod_perl picks
+ up EAPI
+
+2003-05-09 00:05 ivan
+
+ * install/freebsd/: INSTALL, ports: little bit more fbsd install
+ automation
+
+2003-05-08 23:14 ivan
+
+ * install/freebsd/INSTALL: freebsd install
+
+2003-05-08 23:03 ivan
+
+ * fs_selfservice/DEPLOY, install/freebsd/INSTALL,
+ install/freebsd/ports: updated freebsd install
+
+2003-05-08 18:18 ivan
+
+ * install/freebsd/ports: Net::SSH and Net::SCP are in ports
+
+2003-05-08 17:10 ivan
+
+ * install/redhat/7.3/: INSTALL, sources.list: redhat install foo
+
+2003-05-08 17:10 ivan
+
+ * install/freebsd/: INSTALL, ports: automated install foo
+
+2003-05-08 03:28 ivan
+
+ * CREDITS: credit where credit's due
+
+2003-05-08 02:34 ivan
+
+ * Makefile, FS/FS/Record.pm: general Pg 7.3 fix for setting int
+ columns to '' / NULL
+
+2003-05-06 14:15 ivan
+
+ * httemplate/view/cust_main_alt.cgi: don't create new files in lieu
+ of branches
+
+2003-05-06 13:33 khoff
+
+ * httemplate/view/cust_main_alt.cgi: Can't pull out of thin air.
+
+2003-05-04 13:58 khoff
+
+ * httemplate/view/cust_main_alt.cgi: proposed cust_main.cgi
+
+2003-05-02 19:06 ivan
+
+ * FS/FS/part_export/infostreet.pm, httemplate/edit/svc_acct.cgi:
+ enable quota maintenance in infostreet export
+
+2003-05-02 19:03 ivan
+
+ * bin/apache.export: typo in usage instructions
+
+2003-05-02 18:30 ivan
+
+ * FS/FS/part_export.pm: clean up CVS cruft
+
+2003-05-02 16:51 khoff
+
+ * httemplate/view/cust_main.cgi: CARD && DCRD?
+
+2003-04-29 12:49 khoff
+
+ * httemplate/misc/catchall.cgi: 0 has a hash key looks like svcnum
+ = 0. Suprisingly, '' works.
+
+2003-04-29 11:28 khoff
+
+ * FS/FS/domain_record.pm: Better SOA checking
+
+2003-04-29 09:59 khoff
+
+ * httemplate/edit/svc_broadband.cgi: It helps if you can edit the
+ ip_addr field.
+
+2003-04-25 19:01 khoff
+
+ * FS/FS/cust_svc.pm: I don't like FS::Record warnings
+
+2003-04-25 17:28 khoff
+
+ * FS/FS/cust_bill.pm: Tyop
+
+2003-04-24 16:01 ivan
+
+ * httemplate/edit/cust_main.cgi: fix for bug triggered by
+ nonexistant referring customer numbers
+
+2003-04-24 11:46 khoff
+
+ * FS/FS/part_export/sqlmail.pm: MySQL returns zero on an update
+ when no values change. We would insert on an rv of zero, so now
+ we select count(*)... instead of relying on the rv of the update.
+
+2003-04-24 11:45 khoff
+
+ * FS/FS/domain_record.pm: Support for nWnDnHnMnS time format
+
+2003-04-23 19:46 ivan
+
+ * FS/FS/: part_export.pm, part_export/domain_shellcommands.pm:
+ better shellcommands documentation of all sorts
+
+2003-04-23 18:43 khoff
+
+ * FS/FS/part_export.pm, bin/bind.export: Support for exporting to
+ an ISC BIND9 name server
+
+2003-04-23 18:00 khoff
+
+ * FS/FS/part_export/sqlmail.pm: Apparently deleting elements from
+ svc_Common->hashref is bad.
+
+2003-04-23 16:12 ivan
+
+ * Makefile, htetc/handler.pl, htetc/handler.pl-1.0x,
+ httemplate/docs/install.html: compatible with mason 1.1! closes:
+ bug#492
+
+2003-04-23 15:16 ivan
+
+ * FS/FS/part_export.pm: might not be necessary, but to be safe...
+
+2003-04-22 22:36 khoff
+
+ * httemplate/search/cust_main.cgi: Missing comma.
+
+2003-04-22 21:53 khoff
+
+ * FS/bin/freeside-setup: DBD::Pg doesn't handle char types very
+ well.
+
+2003-04-22 11:46 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi: properly deprecate ancient apache &
+ sendmail config options
+
+2003-04-22 10:54 ivan
+
+ * httemplate/edit/part_export.cgi: mason is more strict about
+ variables - patch from Richard Siddall, thanks
+
+2003-04-21 21:39 ivan
+
+ * FS/MANIFEST, FS/FS/Conf.pm, FS/FS/part_export.pm,
+ FS/FS/svc_domain.pm, FS/FS/svc_forward.pm,
+ FS/FS/part_export/domain_shellcommands.pm,
+ FS/FS/part_export/forward_shellcommands.pm,
+ FS/t/part_export-forward_shellcommands.t,
+ httemplate/docs/install.html: - mysql 4.1 is available; update
+ documentation - remove last vestiges of 1.3-style qmail/vpopmail
+ exports from svc_domain and svc_forward; add appropriate
+ exports (closes: Bug#299)
+
+2003-04-21 15:40 ivan
+
+ * httemplate/view/svc_acct.cgi: typo
+
+2003-04-21 14:42 khoff
+
+ * FS/FS/addr_block.pm: renamed config option excludeaddr
+
+2003-04-21 14:40 khoff
+
+ * FS/FS/Conf.pm: renamed/clarified exclude_ip_addr option.
+
+2003-04-21 14:29 khoff
+
+ * httemplate/edit/: part_router_field.cgi, process/generic.cgi:
+ Navigation fixes.
+
+2003-04-21 14:13 khoff
+
+ * httemplate/edit/process/router.cgi: Fixed bug with $routernum and
+ new routers. Navigation cleanup.
+
+2003-04-21 14:12 khoff
+
+ * httemplate/edit/router.cgi: Lines added for clairity
+
+2003-04-21 13:53 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/part_bill_event.pm,
+ FS/bin/freeside-daily, FS/bin/freeside-expiration-alerter,
+ FS/bin/freeside-setup, fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/docs/schema.html, httemplate/edit/cust_main.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/search/cust_main.cgi, httemplate/view/cust_main.cgi:
+ on-demand vs. automatic cards & checks: added DCRD and DCHK
+ payment types
+
+2003-04-21 13:31 khoff
+
+ * FS/FS/: part_export.pm, part_export/sqlmail.pm: Bug fixes for
+ sqlmail. Added support for courier and dovecot authentication.
+
+2003-04-21 13:27 khoff
+
+ * FS/FS/: Conf.pm, addr_block.pm: excludeaddr option for
+ svc_broadband
+
+2003-04-19 10:51 ivan
+
+ * FS/FS/: Conf.pm, part_pkg.pm: /^\s*$/ setup/recur expressions now
+ failsafe to 0 (closes: Bug#498) deprecate old 1.3-style qmail
+ integration
+
+2003-04-17 20:29 ivan
+
+ * httemplate/view/svc_acct.cgi: YA pg7.3 fix
+
+2003-04-02 06:52 ivan
+
+ * FS/FS/cust_main.pm: added order_pkgs sub
+
+2003-04-02 03:38 ivan
+
+ * FS/FS/: UID.pm, cust_main.pm: better callbacks
+
+2003-04-02 01:46 ivan
+
+ * httemplate/misc/process/meta-import.cgi: updated meta-import web
+ UI to allow duplicate import tables
+
+2003-04-01 19:23 ivan
+
+ * httemplate/edit/: cust_main.cgi, process/cust_main.cgi: fix
+ disappearing email invoice on errors, finally (closes: Bug#35)
+
+2003-04-01 00:03 ivan
+
+ * FS/FS/Record.pm, httemplate/docs/index.html,
+ httemplate/docs/upgrade10.html, httemplate/view/cust_main.cgi: -
+ update qsearch for Pg 7.3 - preliminary 1.5.0 upgrade docs -
+ syntax error in main customer view
+
+2003-03-31 22:55 ivan
+
+ * httemplate/: misc/cust_main-cancel.cgi, view/cust_main.cgi:
+ cancel button for customers (closes: Bug#25)
+
+2003-03-31 17:22 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/cust_pkg.pm, debian/changelog,
+ debian/control, httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_pkg.cgi: correct last_bill problems with $0
+ invoice (non-existant) edge cases
+
+2003-03-31 15:49 ivan
+
+ * httemplate/docs/schema.html: added last_bill column
+
+2003-03-31 15:48 ivan
+
+ * FS/bin/freeside-setup: add 'last_bill' column
+
+2003-03-28 21:34 ivan
+
+ * bin/apache.export: restart apache, not bind!
+
+2003-03-28 20:52 ivan
+
+ * FS/FS/cust_svc.pm, FS/FS/domain_record.pm,
+ FS/FS/part_export/www_shellcommands.pm,
+ httemplate/view/svc_www.cgi: correct web UI for svc_www services
+ & no more @.domain in www_shellcommands export
+
+2003-03-28 18:35 ivan
+
+ * FS/FS/part_export/www_shellcommands.pm: trim leading @. off zones
+
+2003-03-28 18:19 ivan
+
+ * FS/FS/part_export.pm: cust_svc and svc_x methods
+
+2003-03-28 13:59 ivan
+
+ * bin/apache.export: fix missing semicolon in apache export
+
+2003-03-28 13:43 ivan
+
+ * FS/FS/part_export/apache.pm: oops in null apache export
+
+2003-03-24 00:30 ivan
+
+ * httemplate/search/svc_acct.cgi: another Pg7.3 fix
+
+2003-03-19 20:36 ivan
+
+ * httemplate/edit/part_export.cgi: virtual wrap...
+
+2003-03-19 20:09 ivan
+
+ * httemplate/edit/part_export.cgi: wrap this textbox hard
+
+2003-03-19 20:00 ivan
+
+ * httemplate/edit/part_export.cgi: wide textareas
+
+2003-03-19 19:41 ivan
+
+ * FS/MANIFEST, FS/FS/domain_record.pm, FS/FS/part_export.pm,
+ FS/FS/part_export/apache.pm, FS/t/part_export-apache.t,
+ bin/apache.export, bin/bind.export, bin/bsdshell.export,
+ bin/sysvshell.export: apache export!
+
+2003-03-11 16:44 ivan
+
+ * httemplate/docs/upgrade9.html: doc from 1.4 branch
+
+2003-03-11 03:40 ivan
+
+ * FS/FS/svc_domain.pm: another pg7.3 fix
+
+2003-03-11 03:36 ivan
+
+ * httemplate/misc/: meta-import.cgi, process/meta-import.cgi: minor
+ meta import webUI updates
+
+2003-03-11 02:41 ivan
+
+ * httemplate/edit/part_pkg.cgi: another pg7.3 fix
+
+2003-03-03 17:56 khoff
+
+ * FS/MANIFEST: updated for svc_broadband changes
+
+2003-02-28 19:14 ivan
+
+ * FS/FS/cust_main.pm: change next bill date comparison from < to <=
+
+2003-02-24 21:40 ivan
+
+ * httemplate/edit/cust_main.cgi: remove max length on ACH account
+ number
+
+2003-02-11 17:21 khoff
+
+ * FS/bin/freeside-setup: s/;/,/
+
+2003-02-05 21:26 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_pkg.pm, FS/FS/cust_bill_pkg_detail.pm,
+ FS/FS/cust_main.pm, FS/bin/freeside-setup,
+ FS/t/cust_bill_pkg_detail.t, httemplate/docs/schema.html,
+ httemplate/docs/upgrade10.html, httemplate/edit/part_pkg.cgi:
+ time/data detail on invoices
+
+2003-02-05 15:22 khoff
+
+ * FS/FS/ac.pm, FS/FS/ac_block.pm, FS/FS/ac_field.pm,
+ FS/FS/ac_type.pm, FS/FS/part_ac_field.pm,
+ httemplate/browse/ac.cgi, httemplate/browse/ac_type.cgi,
+ httemplate/edit/ac.cgi, httemplate/edit/ac_type.cgi,
+ httemplate/edit/process/ac.cgi,
+ httemplate/edit/process/ac_block.cgi,
+ httemplate/edit/process/ac_field.cgi,
+ httemplate/edit/process/ac_type.cgi,
+ httemplate/edit/process/part_ac_field.cgi: svc_broadband rewrite
+
+2003-02-05 15:17 khoff
+
+ * FS/FS/addr_block.pm, FS/FS/part_router_field.pm,
+ FS/FS/part_sb_field.pm, FS/FS/part_svc_router.pm,
+ FS/FS/router.pm, FS/FS/router_field.pm, FS/FS/sb_field.pm,
+ FS/FS/svc_broadband.pm, httemplate/browse/addr_block.cgi,
+ httemplate/browse/generic.cgi,
+ httemplate/browse/part_sb_field.cgi,
+ httemplate/browse/router.cgi,
+ httemplate/edit/part_router_field.cgi,
+ httemplate/edit/part_sb_field.cgi, httemplate/edit/router.cgi,
+ httemplate/edit/svc_broadband.cgi,
+ httemplate/edit/process/addr_block/add.cgi,
+ httemplate/edit/process/addr_block/allocate.cgi,
+ httemplate/edit/process/addr_block/deallocate.cgi,
+ FS/bin/freeside-setup, httemplate/edit/process/generic.cgi,
+ httemplate/edit/process/router.cgi,
+ httemplate/edit/process/svc_broadband.cgi,
+ httemplate/edit/process/addr_block/split.cgi, htetc/global.asa,
+ htetc/handler.pl, httemplate/index.html,
+ httemplate/view/svc_broadband.cgi: svc_broadband rewrite
+
+2003-02-05 14:06 khoff
+
+ * FS/FS/cust_svc.pm: ip_netmask is gone now
+
+2003-02-04 14:04 ivan
+
+ * htetc/global.asa, httemplate/docs/install.html: 1.5-specific
+ fixes
+
+2003-01-27 23:47 ivan
+
+ * FS/bin/freeside-setup: eek, and this is what caused connectup to
+ fail too
+
+2003-01-27 22:08 ivan
+
+ * FS/FS/part_export/ldap.pm: crypt password export to ldap fix from
+ dave denney <daud@kaosol.net>
+
+2003-01-16 22:21 ivan
+
+ * FS/FS/ClientAPI/MyAccount.pm,
+ fs_selfservice/FS-SelfService/SelfService.pm: selfservice cancel
+ functionality
+
+2003-01-15 18:58 ivan
+
+ * FS/FS/part_export/shellcommands.pm: don't run empty shellcommands
+
+2003-01-14 02:15 ivan
+
+ * Makefile: selfservice
+
+2003-01-14 01:26 ivan
+
+ * FS/MANIFEST, FS/bin/freeside-selfservice-server,
+ fs_selfservice/freeside-selfservice-server, init.d/freeside-init:
+ move freeside-selfservice-server to proper MakeMaker install
+ location
+
+2003-01-14 00:49 ivan
+
+ * Makefile, FS/FS/svc_acct.pm, init.d/freeside-init: add
+ freeside-selfservice-server to init script add domsvc checking as
+ a foreign key
+
+2003-01-12 23:26 ivan
+
+ * httemplate/edit/part_export.cgi: another Pg 7.3 fix
+
+2003-01-12 22:19 ivan
+
+ * httemplate/edit/part_svc.cgi: whitespace inconsistancy causing
+ extraneous diffs
+
+2003-01-09 23:41 ivan
+
+ * FS/FS/cust_bill.pm: pop off an extra blank line in
+ business-onlinepayment options
+
+2002-12-28 01:16 ivan
+
+ * FS/FS/: cust_bill.pm, svc_acct.pm: prevent edge-case
+ business-onlinepayment mod_perl leakage in multi-database
+ installs. ugh.
+
+2002-12-27 04:56 ivan
+
+ * FS/FS/cust_main.pm: better times on failed billing events
+
+2002-12-24 22:59 ivan
+
+ * FS/bin/freeside-daily: declare $opt_p usage
+
+2002-12-24 15:03 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: electronic checks work
+ in signup.cgi
+
+2002-12-24 14:41 ivan
+
+ * README.1.5.0pre1, FS/bin/freeside-setup,
+ httemplate/view/cust_main.cgi: optimization for ginourmous
+ numbers of packages for intergate, whew
+
+2002-12-23 15:56 ivan
+
+ * FS/FS/svc_acct.pm: remove gratuitous warning and better error
+ messages
+
+2002-12-23 07:21 ivan
+
+ * FS/FS/cust_bill.pm: make agent available to invoice templates
+
+2002-12-23 07:05 steve
+
+ * FS/FS/part_export/shellcommands.pm: add email address to
+ shellcommands
+
+ don't error out when importing unaudited accounts (even though
+ should probably be using $FS::svc_Common::noexport_hack anyway)
+
+2002-12-23 06:54 steve
+
+ * FS/FS/cust_pkg.pm: added stuff for selfservice_server-quiet,
+ signup_server-quiet, and emailcancel messages.
+
+2002-12-23 06:38 steve
+
+ * fs_selfservice/freeside-selfservice-server: added stuff for
+ selfservice_server-quiet, signup_server-quiet, and emailcancel
+ messages.
+
+2002-12-23 06:36 steve
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/SignupClient.pm:
+ added stuff for selfservice_server-quiet, signup_server-quiet,
+ and emailcancel messages.
+
+ signup server can set user's comment field.
+
+2002-12-23 06:22 steve
+
+ * FS/FS/: cust_bill.pm, Conf.pm: added stuff for
+ selfservice_server-quiet, signup_server-quiet, and emailcancel
+ messages.
+
+2002-12-22 00:53 ivan
+
+ * FS/: FS/cust_pkg.pm, bin/freeside-daily: -p option for
+ freeside-daily to only run for a particular payby
+ $disable_agentcheck option for cust_pkg for import optimization
+
+2002-12-21 15:48 ivan
+
+ * httemplate/search/svc_domain.cgi: UI
+
+2002-12-21 15:44 ivan
+
+ * httemplate/search/svc_domain.cgi: don't display all accounts in
+ each domain
+
+2002-12-21 02:14 ivan
+
+ * FS/FS/cust_main.pm: could be multiple returns from these
+ searches, with taxclasses
+
+2002-12-21 02:02 ivan
+
+ * FS/FS/Record.pm: better qsearchs warning
+
+2002-12-20 23:36 ivan
+
+ * FS/FS/svc_acct.pm: $noexport hack moved to svc_Common
+
+2002-12-20 20:31 ivan
+
+ * FS/FS/svc_acct.pm: kludge around uninitialized value errors
+
+2002-12-19 19:29 ivan
+
+ * httemplate/view/cust_main.cgi: no changing cancelled packages
+
+2002-12-17 13:31 ivan
+
+ * FS/FS/cust_bill.pm: invoice_lines() fix
+
+2002-12-17 05:02 ivan
+
+ * httemplate/view/svc_acct.cgi: change wording
+
+2002-12-17 02:42 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: doh! but finally fixed
+
+2002-12-17 02:36 ivan
+
+ * FS/FS/cust_svc.pm: sqlradius time calculation fix wrt open
+ sessions
+
+2002-12-17 01:52 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: sheesh
+
+2002-12-17 01:48 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: sigh
+
+2002-12-17 01:47 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: is this broken or is the
+ calculation?
+
+2002-12-17 01:37 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: grr double doh
+
+2002-12-17 01:35 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: doh
+
+2002-12-17 01:30 ivan
+
+ * FS/bin/freeside-sqlradius-seconds: carriage return helps alot
+
+2002-12-17 01:24 ivan
+
+ * FS/: MANIFEST, bin/freeside-sqlradius-seconds: adding
+ freeside-sqlradius-seconds
+
+2002-12-16 22:36 ivan
+
+ * httemplate/docs/install.html: add PerlModule commands to install
+ instructions
+
+2002-12-16 13:52 ivan
+
+ * FS/FS/part_svc.pm, httemplate/edit/part_svc.cgi: fix for Pg 7.3,
+ are there others?
+
+2002-12-16 10:53 ivan
+
+ * httemplate/view/svc_domain.cgi: add PTR record to domain edit
+
+2002-12-16 02:47 ivan
+
+ * httemplate/graph/: money_time-graph.cgi, money_time.cgi: working
+ date range selector that defaults to the past year!
+
+2002-12-14 13:18 ivan
+
+ * FS/FS/cust_svc.pm: fix for auditing packages
+
+2002-12-12 16:31 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/process/meta-import.cgi:
+ taxclass fix (?)
+
+2002-12-12 13:44 ivan
+
+ * FS/FS/svc_acct.pm: custnum in welcome email
+
+2002-12-10 16:12 ivan
+
+ * httemplate/misc/: meta-import.cgi, process/meta-import.cgi:
+ beginning of web-based data importer
+
+2002-12-09 02:54 ivan
+
+ * httemplate/docs/install.html: doc
+
+2002-12-04 04:43 ivan
+
+ * bin/bind.export: really fixed now
+
+2002-12-04 04:37 ivan
+
+ * bin/bind.export: oops, typo
+
+2002-12-04 04:31 ivan
+
+ * FS/FS/cust_bill.pm: empty invoice_lines() fix
+
+2002-11-28 21:14 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: accept unmunged
+ state/county/country
+
+2002-11-28 02:54 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/cgi/signup.cgi,
+ FS-SignupClient/cgi/signup.html: separate state and country
+ <SELECT> in signup server also, closes: Bug#353
+
+2002-11-27 21:44 ivan
+
+ * FS/FS/part_export.pm: add -g FreeBSD shellcommands export as per
+ "Stephen Bechard" <steve@destek.net>
+
+2002-11-27 21:10 ivan
+
+ * FS/FS/Conf.pm, httemplate/docs/upgrade8.html: deprecate
+ username_policy
+
+2002-11-26 03:58 ivan
+
+ * httemplate/misc/process/link.cgi: link by username now only links
+ to same svcpart
+
+2002-11-26 02:25 ivan
+
+ * FS/FS/part_export/ldap.pm: ldap export: fix $crypt_password
+
+2002-11-25 21:42 ivan
+
+ * FS/FS/svc_acct.pm: remove harmless re-my to silence warning
+
+2002-11-25 02:46 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/edit/svc_acct.cgi: fix disappearing
+ radius group bug, whew
+
+2002-11-22 19:39 ivan
+
+ * httemplate/index.html: eww get rid of black border on konq3
+
+2002-11-22 04:19 ivan
+
+ * FS/FS/cust_bill.pm: fix nasty typo which would affect credit card
+ payments
+
+2002-11-22 03:14 ivan
+
+ * FS/FS/part_bill_event.pm, httemplate/edit/part_bill_event.cgi:
+ add lec billing event
+
+2002-11-22 02:48 ivan
+
+ * FS/FS/cust_main.pm: oops, one last LECB change
+
+2002-11-22 00:06 ivan
+
+ * fs_signup/fs_signup_server: silly LECB error in signup server
+
+2002-11-21 23:50 ivan
+
+ * FS/FS/: part_export.pm, part_export/ldap.pm: separate root and
+ user dn in ldap export
+
+2002-11-21 16:14 ivan
+
+ * fs_signup/fs_signup_server: signup server: use 'daytime' for LECB
+ payinfo
+
+2002-11-21 12:44 ivan
+
+ * FS/FS/part_export.pm: change DN labeling for those obtuse
+ blockheads at netmagic
+
+2002-11-20 13:13 ivan
+
+ * FS/FS/: part_export.pm, part_export/ldap.pm: add objectclass and
+ ability to have multiple comma-separated values to LDAP export
+
+2002-11-20 02:09 ivan
+
+ * FS/FS/part_export/ldap.pm: hmm, so you add the username to the DN
+ for the add call...? i don't get LDAP
+
+2002-11-20 01:10 ivan
+
+ * FS/FS/part_export/ldap.pm: fix silly bug in ldap export
+
+2002-11-20 01:07 ivan
+
+ * FS/bin/freeside-setup, httemplate/docs/upgrade9.html: ugh... need
+ to increase length of payinfo field in cust_pay and cust_refund
+ for ACH
+
+2002-11-19 14:55 ivan
+
+ * FS/FS/cust_bill_event.pm: give better error message on bad
+ invnum, also 'use FS::cust_bill' here
+
+2002-11-19 14:48 ivan
+
+ * FS/FS/cust_bill.pm: Business::OnlinePayment type is ECHECK not
+ CHECK
+
+2002-11-19 13:20 ivan
+
+ * FS/FS/part_export/ldap.pm: ldap export: don't use password if not
+ given
+
+2002-11-19 12:56 ivan
+
+ * FS/FS/part_export/ldap.pm: ldap export update
+
+2002-11-19 12:36 ivan
+
+ * FS/bin/freeside-setup: increase length of reczone and recdata
+ fields in domain_record
+
+2002-11-19 02:09 ivan
+
+ * FS/FS/cust_bill.pm: typo adding lec transactions
+
+2002-11-19 02:02 ivan
+
+ * FS/FS/cust_main.pm: silly regex bug parsing echeck info
+
+2002-11-19 01:51 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_refund.pm, FS/FS/part_bill_event.pm,
+ FS/FS/part_pkg.pm, FS/FS/part_export/ldap.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/docs/schema.html, httemplate/edit/cust_main.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/view/cust_main.cgi: add LEC billing
+
+2002-11-18 21:17 ivan
+
+ * httemplate/edit/cust_main.cgi: oops, remove 10 digit account
+ number limit
+
+2002-11-18 02:15 ivan
+
+ * FS/MANIFEST, FS/FS/part_export.pm, FS/FS/part_export/ldap.pm,
+ FS/t/part_export-ldap.t, httemplate/edit/part_export.cgi:
+ preliminary ldap export
+
+2002-11-16 02:33 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm: separate ACH processor support
+
+2002-11-09 02:59 ivan
+
+ * httemplate/edit/part_pkg.cgi: javascript quoting problem in
+ per-hour charging
+
+2002-11-07 14:53 ivan
+
+ * FS/FS/cust_main.pm: doc
+
+2002-11-05 21:41 ivan
+
+ * httemplate/graph/money_time-graph.cgi: lala
+
+2002-11-05 20:23 ivan
+
+ * FS/FS/part_pkg.pm: safe regex for sqlradius hour/data billing,
+ closes: Bug#474
+
+2002-11-05 20:11 ivan
+
+ * httemplate/edit/part_pkg.cgi: data billing
+
+2002-11-05 19:58 ivan
+
+ * httemplate/edit/part_pkg.cgi: data charging
+
+2002-11-05 15:43 ivan
+
+ * httemplate/view/svc_acct.cgi: ui
+
+2002-11-05 15:41 ivan
+
+ * httemplate/: edit/part_pkg.cgi, view/svc_acct.cgi: fix for
+ correct radacct column names
+
+2002-11-05 15:34 ivan
+
+ * FS/FS/cust_svc.pm: can't use placeholders in SELECT SUM(?)
+
+2002-11-05 15:29 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/part_pkg.cgi, httemplate/view/svc_acct.cgi:
+ bandwidth charges from sqlradius
+
+2002-11-05 12:29 ivan
+
+ * FS/bin/freeside-sqlradius-radacctd: lost?
+
+2002-11-04 18:15 ivan
+
+ * httemplate/graph/money_time-graph.cgi: local kludge
+
+2002-11-04 15:40 ivan
+
+ * FS/FS/CGI.pm: balance on small_custview
+
+2002-11-04 13:20 ivan
+
+ * httemplate/docs/upgrade9.html: doc
+
+2002-11-04 12:51 ivan
+
+ * httemplate/view/svc_acct.cgi: fix cosmetic bug on online time
+ view
+
+2002-11-01 16:13 ivan
+
+ * httemplate/graph/: money_time-graph.cgi, money_time.cgi: whew,
+ glad i had a copy of this
+
+2002-10-28 05:22 ivan
+
+ * FS/bin/freeside-queued: signal-less queued child handling
+ (closes: Bug#477)
+
+2002-10-25 14:24 ivan
+
+ * FS/FS/part_export/shellcommands.pm: make $old_domain available
+ too
+
+2002-10-25 06:39 ivan
+
+ * httemplate/: browse/part_svc.cgi, edit/part_svc.cgi: show export
+ numbers
+
+2002-10-23 10:07 ivan
+
+ * FS/: FS/Conf.pm, bin/freeside-daily: database dump & scp support
+
+2002-10-23 08:49 ivan
+
+ * FS/FS/Conf.pm, httemplate/misc/unapply-cust_pay.cgi,
+ httemplate/view/cust_main.cgi: add option to unapply payments
+
+2002-10-22 02:15 ivan
+
+ * FS/FS/part_export/vpopmail.pm: bugfix in vpopmail restart
+
+2002-10-22 01:13 ivan
+
+ * FS/FS/part_bill_event.pm, httemplate/edit/part_bill_event.cgi:
+ ACH fixes from s5
+
+2002-10-21 23:28 ivan
+
+ * httemplate/edit/part_bill_event.cgi: oops - allow adding CHECK
+ invoice events too
+
+2002-10-21 08:20 ivan
+
+ * httemplate/edit/part_svc.cgi: don't disable for all items
+
+2002-10-21 08:14 ivan
+
+ * httemplate/edit/part_svc.cgi: Prevent a fixed or default username
+ or password from being defined
+
+2002-10-20 01:27 ivan
+
+ * FS/FS/: part_export.pm, part_export/shellcommands.pm: enable
+ shellcommands suspension/unsuspension hooks
+
+2002-10-20 00:26 ivan
+
+ * FS/FS/part_export/vpopmail.pm: don't run restart command unless
+ there is one
+
+2002-10-19 20:28 ivan
+
+ * FS/FS/part_export.pm, FS/FS/part_export/vpopmail.pm,
+ eg/vpopmailrestart: vpopmail restart export option
+
+2002-10-18 09:54 ivan
+
+ * Makefile: force executable permissions on bin/pod2x
+
+2002-10-18 06:28 ivan
+
+ * FS/bin/freeside-radgroup: argh
+
+2002-10-18 06:23 ivan
+
+ * FS/FS/svc_acct.pm: don't re-insert non-changed usernames to fuzzy
+ cache
+
+2002-10-18 03:28 ivan
+
+ * FS/: MANIFEST, bin/freeside-radgroup: adding
+
+2002-10-17 08:06 ivan
+
+ * httemplate/view/svc_acct.cgi: use consistant terminology
+
+2002-10-17 08:05 ivan
+
+ * httemplate/view/svc_acct.cgi: UI change for hour info
+
+2002-10-17 07:59 ivan
+
+ * FS/FS/cust_svc.pm: yay missing paren
+
+2002-10-17 07:50 ivan
+
+ * FS/FS/cust_svc.pm: *sigh* better debugging
+
+2002-10-17 07:46 ivan
+
+ * FS/FS/cust_svc.pm: really fix sqlradacct for old Pg
+
+2002-10-17 07:37 ivan
+
+ * FS/FS/cust_svc.pm: fix sqlradacct calculations for old Pg
+
+2002-10-17 07:33 ivan
+
+ * httemplate/view/svc_acct.cgi: sqlradacct hour update
+
+2002-10-17 07:16 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm, FS/FS/part_svc.pm,
+ FS/FS/svc_acct.pm, httemplate/edit/part_pkg.cgi,
+ httemplate/view/svc_acct.cgi: radacct update: use sqlradius for
+ datasrc, not plandata options (whew)
+
+2002-10-17 04:17 ivan
+
+ * httemplate/search/cust_bill.cgi: another mason fix, this one from
+ 5
+
+2002-10-15 02:54 ivan
+
+ * FS/FS/cust_bill.pm: ach fix s/ECHECK/CHECK/
+
+2002-10-14 02:28 ivan
+
+ * fs_signup/fs_signup_server: close invoices which are declined.
+ closes: Bug#408
+
+2002-10-14 00:44 ivan
+
+ * FS/FS/Conf.pm: s/bool/checkbox/
+
+2002-10-14 00:30 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/svc_acct.cgi: svc-acct-alldomains
+ config file allows selection of accounts from any domain
+
+2002-10-13 23:17 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/edit/part_pkg.cgi: fix sql radacct
+ billing
+
+2002-10-13 23:16 ivan
+
+ * httemplate/view/svc_acct.cgi: show time online this billing cycle
+ on view account screen
+
+2002-10-13 00:14 ivan
+
+ * httemplate/docs/: session.html, upgrade9.html: doh
+
+2002-10-13 00:13 ivan
+
+ * httemplate/docs/upgrade9.html: msgcat docs for upgrade
+
+2002-10-12 23:49 ivan
+
+ * httemplate/docs/install.html: don't use ILIKE (7.1-ism) anymore
+
+2002-10-12 18:14 ivan
+
+ * FS/FS/Record.pm: change ILIKE into LOWER() for compatibility with
+ non-Pg and Pg before 7.1
+
+2002-10-12 18:05 ivan
+
+ * FS/FS/cust_bill.pm: bug fix in new ACH code
+
+2002-10-12 07:21 ivan
+
+ * httemplate/: edit/cust_main.cgi, view/cust_main.cgi: fix
+ dayphone/nightphone msgcat
+
+2002-10-12 06:46 ivan
+
+ * bin/populate-msgcat, httemplate/edit/cust_main.cgi,
+ httemplate/view/cust_main.cgi: dayphone/nightphone as
+ customizable labels, closes: Bug#464
+
+2002-10-12 06:26 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/part_pkg.cgi: sqlradacct_hour price plan to
+ charge per-hour against an external radacct table
+
+2002-10-12 03:15 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_refund.pm,
+ FS/FS/part_bill_event.pm,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/view/cust_main.cgi: ACH support
+
+2002-10-10 09:48 ivan
+
+ * httemplate/edit/cust_main.cgi: bugfix in payby-default HIDE
+ expiration dates
+
+2002-10-10 09:28 ivan
+
+ * httemplate/edit/cust_main.cgi: expiration date bugfix for HIDE
+
+2002-10-09 07:30 ivan
+
+ * FS/FS/Conf.pm: nasty typo
+
+2002-10-09 06:59 ivan
+
+ * FS/FS/Conf.pm: don't explicitly specify unclassified config
+ section
+
+2002-10-09 06:43 ivan
+
+ * FS/FS/part_export/vpopmail.pm: don't error out trying to create
+ existing directories in vpopmail export
+
+2002-10-09 06:07 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: radius-password config value to set
+ the attribute used for plaintext pw's
+
+2002-10-08 04:10 ivan
+
+ * httemplate/: index.html, search/cust_pkg.cgi: add suspended
+ package browse (closes: Bug#467)
+
+2002-10-08 03:50 ivan
+
+ * eg/export_template.pm: slightly less sucky
+
+2002-10-08 01:33 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/svc_acct.cgi: svc_acct-notes
+ displays static HTML on account view (closes: Bug#465)
+
+2002-10-07 21:46 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi,
+ httemplate/view/cust_main.cgi: payby-default config option, with
+ special "HIDE" option to disable billing information in the web
+ interface (closes: Bug#468)
+
+2002-10-07 01:47 ivan
+
+ * FS/bin/freeside-daily: cancel when it is *after* expiration date,
+ not when it is *before*
+
+2002-10-05 04:14 ivan
+
+ * FS/FS/part_export/sqlradius.pm: fix sqlradius export to not set
+ blank id fields
+
+2002-10-04 05:56 ivan
+
+ * FS/FS/type_pkgs.pm, FS/FS/part_export/sqlradius.pm,
+ FS/bin/freeside-setup, httemplate/docs/install.html,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/misc/change_pkg.cgi, httemplate/search/cust_main.cgi,
+ httemplate/view/cust_main.cgi: working on the road: - easier
+ "change package" link for changing one package to another -
+ sqlradius export now compatible with Pg - indices on phone
+ numbers - install instructions specify Pg 7.1 (at least until
+ ILIKE thing is changed) - searching on phone number fragments
+
+2002-10-04 05:39 ivan
+
+ * FS/bin/freeside-daily: turn on AutoCommit when vacuuming
+
+2002-10-04 05:29 ivan
+
+ * FS/bin/freeside-count-active-customers: adding
+
+2002-10-04 05:09 ivan
+
+ * FS/FS/cust_bill.pm: default for customers with no invoices was:
+ print is now: send email to invoice from address
+
+2002-10-03 08:29 ivan
+
+ * FS/FS/svc_acct.pm: fix implicit RADIUS password attribute to be
+ Crypt-Password for encrypted pw's
+
+2002-09-27 05:14 ivan
+
+ * FS/FS/svc_acct.pm: allow + in md5 encrypted passwords
+
+2002-09-27 05:14 ivan
+
+ * FS/FS/UID.pm: don't chop blanks
+
+2002-09-26 23:00 ivan
+
+ * htetc/global.asa: only load Devel::AutoProfiler if it is
+ installed
+
+2002-09-26 22:36 ivan
+
+ * FS/bin/freeside-adduser: lock mapsecrets file
+
+2002-09-25 22:28 ivan
+
+ * Makefile: fix $INIT_FILE usage
+
+2002-09-25 22:26 ivan
+
+ * FS/FS/svc_acct.pm: fix for inserting un-audited accounts
+
+2002-09-25 22:25 ivan
+
+ * Makefile: oops
+
+2002-09-25 21:45 ivan
+
+ * httemplate/search/svc_acct.cgi: tyop
+
+2002-09-25 02:11 ivan
+
+ * Makefile, httemplate/docs/install.html: doc
+
+2002-09-25 02:09 ivan
+
+ * FS/FS/raddb.pm: regenerate raddb.pm from freeradius-0.4 dicts add
+ "Authentication-Type" for netc.net.au (radiator?)
+
+2002-09-24 01:31 ivan
+
+ * FS/FS/Conf.pm: deprecate vpopmailrestart config value
+
+2002-09-23 07:27 ivan
+
+ * FS/FS/CGI.pm, htetc/global.asa, htetc/handler.pl: global.asa
+ changes for profiling redirects header-handling changes necessary
+ for chart .cgis
+
+2002-09-23 01:50 ivan
+
+ * Makefile: better default Pg datasource
+
+2002-09-21 04:17 ivan
+
+ * README.1.5.0pre1, FS/bin/freeside-setup,
+ httemplate/docs/schema.dia, httemplate/docs/schema.html,
+ FS/FS/cust_bill.pm, FS/FS/cust_bill_pkg.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_main_county.pm, bin/create-history-tables,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/process/cust_main_county.cgi: all taxes now have
+ names. closes: Bug#15
+
+2002-09-20 08:49 ivan
+
+ * README: d
+
+2002-09-20 08:49 ivan
+
+ * FS/Makefile.PL: installing into /usr/bin, bah
+
+2002-09-20 08:48 ivan
+
+ * FS/FS.pm: doc
+
+2002-09-20 08:48 ivan
+
+ * Makefile: 1.5.0
+
+2002-09-20 08:47 ivan
+
+ * FS/MANIFEST, FS/bin/freeside-addoutsourceuser,
+ FS/bin/freeside-deloutsource, FS/bin/freeside-deloutsourceuser,
+ FS/bin/freeside-deluser, FS/bin/freeside-setup,
+ bin/populate-msgcat: add freeside-deluser, freeside-deloutsource
+ and freeside-deloutsourceuser
+
+2002-09-20 08:46 ivan
+
+ * FS/FS/Record.pm: fix database sequence code, closes: Bug#69
+
+2002-09-20 07:48 ivan
+
+ * FS/FS/part_export.pm: extraneous warn
+
+2002-09-20 05:50 ivan
+
+ * FS/bin/freeside-setup, bin/fs-setup,
+ httemplate/docs/install.html: move from bin/fs-setup to
+ FS/bin/freeside-setup
+
+2002-09-20 05:04 ivan
+
+ * README.1.5.0pre1, httemplate/docs/install.html: doc NetAddr::IP
+ dependancy
+
+2002-09-20 03:16 ivan
+
+ * README.1.5.0pre1, FS/FS/UID.pm, bin/fs-setup: change otaker
+ fields to 32 chars
+
+2002-09-19 06:34 ivan
+
+ * bin/fs-setup, FS/FS/Record.pm, bin/dbdef-create: use database
+ SERIAL or AUTO_INCREMENT for primary keys, finally, yay! closes:
+ bug#69
+
+2002-09-19 06:25 ivan
+
+ * README.1.5.0pre1: preliminary upgrade instructions
+
+2002-09-19 01:43 ivan
+
+ * FS/bin/freeside-daily: package expiration
+
+2002-09-19 01:34 ivan
+
+ * FS/FS/svc_acct.pm: remove extra definition of $cust_pkg
+
+2002-09-19 00:15 ivan
+
+ * httemplate/view/cust_pkg.cgi: cancel later in view UI... hmm
+
+2002-09-18 15:50 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main_invoice.pm, FS/FS/svc_acct.pm,
+ FS/bin/freeside-email, httemplate/edit/svc_forward.cgi,
+ httemplate/search/svc_acct.cgi, httemplate/search/svc_domain.cgi,
+ httemplate/view/svc_acct.cgi: remove domain config file, closes:
+ Bug#269
+
+2002-09-18 15:38 ivan
+
+ * FS/FS/: svc_domain.pm, cust_svc.pm: removing svc_acct_sm
+
+2002-09-18 05:10 ivan
+
+ * httemplate/docs/: index.html, legacy.html, upgrade4.html,
+ upgrade5.html, upgrade6.html: doc
+
+2002-09-17 03:21 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ httemplate/edit/part_bill_event.cgi: remove obsolete cybercash
+ support
+
+2002-09-17 02:19 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/InitHandler.pm, FS/FS/cust_pkg.pm,
+ FS/FS/part_export.pm, FS/FS/part_svc.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_acct_sm.pm, FS/t/svc_acct_sm.t, httemplate/index.html,
+ httemplate/docs/schema.dia, httemplate/docs/schema.html,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct_sm.cgi,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/edit/process/svc_acct_sm.cgi,
+ httemplate/misc/link.cgi, httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_acct_sm.html,
+ httemplate/search/svc_domain.cgi,
+ httemplate/view/svc_acct_sm.cgi: remove svc_acct_sm
+
+2002-09-16 17:40 ivan
+
+ * FS/FS/cust_bill.pm: send_ftp doc fix
+
+2002-09-16 17:33 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm, cust_main.pm, svc_acct.pm: -
+ "emailinvoiceauto" implementation rewritten to work properly,
+ stop
+ overwriting existing invoice destinations
+
+2002-09-16 02:27 ivan
+
+ * FS/bin/freeside-expiration-alerter: skip empty expiration dates
+
+2002-09-11 02:28 ivan
+
+ * httemplate/browse/svc_acct_pop.cgi: mason error
+
+2002-09-11 02:09 ivan
+
+ * httemplate/search/cust_main.cgi: mason warnings
+
+2002-09-09 20:31 ivan
+
+ * FS/FS/cust_bill.pm: Business::OnlinePaymet fix for processors w/o
+ order numbers, like VirtualNet
+
+2002-09-09 17:37 ivan
+
+ * httemplate/docs/upgrade9.html: doc: need Net::SSH 0.07 for 1.4.1
+
+2002-09-09 16:05 khoff
+
+ * httemplate/: browse/ac.cgi, browse/ac_type.cgi, edit/ac.cgi,
+ edit/ac_type.cgi, edit/svc_broadband.cgi, edit/process/ac.cgi,
+ edit/process/ac_block.cgi, edit/process/ac_field.cgi,
+ edit/process/ac_type.cgi, edit/process/part_ac_field.cgi,
+ edit/process/svc_broadband.cgi, view/svc_broadband.cgi:
+ svc_broadband merge
+
+2002-09-09 16:01 khoff
+
+ * FS/FS/cust_svc.pm, FS/FS/part_export.pm, bin/fs-setup,
+ htetc/global.asa, httemplate/index.html,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi, FS/FS/ac.pm,
+ FS/FS/ac_block.pm, FS/FS/ac_field.pm, FS/FS/ac_type.pm,
+ FS/FS/part_ac_field.pm, FS/FS/svc_broadband.pm: svc_broadband
+ merge
+
+2002-09-09 15:57 ivan
+
+ * FS/bin/: freeside-cc-receipts-report, freeside-credit-report,
+ freeside-receivables-report, freeside-tax-report: allow . in
+ untaint_argv, for usernames
+
+2002-09-09 15:56 khoff
+
+ * FS/MANIFEST: svc_broadband merge
+
+2002-09-09 12:56 ivan
+
+ * FS/FS/part_export.pm: vpopmail export doc clarification: ssh as
+ vpopmail user
+
+2002-09-09 12:54 ivan
+
+ * httemplate/docs/ssh.html: doc clarification about users
+
+2002-09-09 05:34 ivan
+
+ * FS/FS/: ClientAPI.pm, InitHandler.pm, svc_acct.pm,
+ ClientAPI/passwd.pm: : is not legal in GECOS
+
+2002-09-08 05:57 ivan
+
+ * FS/FS/svc_domain.pm: ordering fix on delete: domain_record
+ records first, then svc_domain
+
+2002-09-08 05:40 ivan
+
+ * bin/bind.export: error out if can't open .HEADER files
+
+2002-09-08 04:36 ivan
+
+ * README: 1.4.1
+
+2002-09-08 02:49 ivan
+
+ * conf/: soadefaultttl, soaexpire, soarefresh, soaretry: some
+ useful default domain files
+
+2002-09-07 07:20 ivan
+
+ * FS/FS/part_export.pm: mention docs/ssh.html in vpopmail
+ description, give up hoping for a better description of the
+ export from jeff
+
+2002-09-06 19:27 ivan
+
+ * httemplate/docs/: index.html, upgrade9.html: 1.4.1
+
+2002-09-06 19:19 ivan
+
+ * FS/FS/part_export/vpopmail.pm: import flocking constants
+
+2002-09-05 11:51 ivan
+
+ * FS/FS/part_export/vpopmail.pm: clear up directory silliness ick
+
+2002-09-05 10:01 ivan
+
+ * httemplate/edit/cust_main.cgi: "same as billing address" box
+ would uncheck itself on errors (only looked at previous
+ ship_last, not CGI checkbox value too) Closes: Bug#448
+
+2002-09-05 09:51 ivan
+
+ * FS/FS/cust_bill.pm: Business::OnlinePayment::VitualNet
+ compatibility
+
+2002-09-05 06:59 ivan
+
+ * ANNOUCE.1.4.0: naw
+
+2002-09-05 06:50 ivan
+
+ * httemplate/browse/part_svc.cgi: don't show "clone an existing
+ service definition" if there aren't any yet
+
+2002-09-05 06:27 ivan
+
+ * FS/FS/cust_main.pm, httemplate/index.html,
+ httemplate/misc/cust_main-import_charges.cgi,
+ httemplate/misc/process/cust_main-import_charges.cgi: batch
+ charge/credit import
+
+2002-09-05 06:01 ivan
+
+ * FS/FS/svc_acct.pm: show illegal dir in error msg
+
+2002-09-05 02:10 ivan
+
+ * FS/FS/: part_export.pm, part_export/vpopmail.pm: get rid of
+ extraneous `vpopmail machine' field
+
+2002-09-04 05:43 ivan
+
+ * Makefile, httemplate/index.html: 1.4.1beta1
+
+2002-09-04 01:42 ivan
+
+ * httemplate/edit/part_pkg.cgi: spelling
+
+2002-08-30 16:48 ivan
+
+ * FS/FS/cust_bill.pm: oops, missing charged column in csv exports
+
+2002-08-30 16:42 ivan
+
+ * httemplate/edit/part_bill_event.cgi, FS/FS/cust_bill.pm,
+ httemplate/edit/process/part_bill_event.cgi: new invoice event:
+ upload a CSV file
+
+2002-08-30 16:17 ivan
+
+ * FS/FS/cust_main.pm: bill batch imported customers immediately (as
+ of their cust_pkg.bill date) - setting cust_pkg.bill date
+ directly bypasses setup fee
+
+2002-08-30 10:34 ivan
+
+ * FS/FS/cust_main.pm, httemplate/index.html,
+ httemplate/misc/cust_main-import.cgi,
+ httemplate/misc/process/cust_main-import.cgi: working CSV import
+ for crcmn
+
+2002-08-30 04:33 ivan
+
+ * httemplate/edit/cust_main.cgi: use eidiot rather than die for
+ (hopefully) better error message
+
+2002-08-30 03:25 ivan
+
+ * Makefile: silly conf/registries dir still hanging around in CVS
+ checkouts
+
+2002-08-29 07:11 ivan
+
+ * httemplate/search/cust_pkg.cgi: UI ROWSPAN fix
+
+2002-08-29 02:11 ivan
+
+ * FS/FS/svc_acct.pm: dont require uid for finger and quota, fix md5
+ import, make username/password for unexported services conflict
+ at least with self
+
+2002-08-29 01:13 khoff
+
+ * httemplate/view/svc_domain.cgi: Missing Mason/Apache::ASP tags
+
+2002-08-29 00:50 ivan
+
+ * FS/FS/: part_export.pm, part_export/vpopmail.pm: vpopmail updates
+
+2002-08-28 23:02 ivan
+
+ * FS/FS/UID.pm: stupid kludge until schema otakers are not 8 chars
+
+2002-08-28 22:57 ivan
+
+ * httemplate/view/svc_acct.cgi: password viewing UI change
+
+2002-08-27 00:26 khoff
+
+ * FS/FS/Record.pm: Yip yip, I sprained my brain
+
+2002-08-26 13:40 ivan
+
+ * FS/FS/cust_pkg.pm: allow . and - in otaker usernames
+
+2002-08-26 12:07 khoff
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: Fancy three-stage
+ popselector a la javascript
+
+2002-08-24 20:54 ivan
+
+ * FS/bin/freeside-addoutsourceuser: ?
+
+2002-08-24 20:42 ivan
+
+ * FS/bin/freeside-addoutsourceuser: correct secrets file path
+
+2002-08-24 19:35 ivan
+
+ * FS/FS/part_export/shellcommands.pm: separate vars for quoted
+ passwords
+
+2002-08-24 19:26 ivan
+
+ * FS/FS/part_export/shellcommands.pm: properly quote password as
+ well as finger
+
+2002-08-24 18:48 ivan
+
+ * FS/bin/freeside-addoutsourceuser: password
+
+2002-08-24 18:48 ivan
+
+ * FS/: MANIFEST, bin/freeside-addoutsourceuser: Added Files:
+ bin/freeside-addoutsourceuser
+
+2002-08-24 18:16 ivan
+
+ * FS/bin/: freeside-adduser, freeside-setup: doc
+
+2002-08-24 18:14 ivan
+
+ * FS/bin/freeside-setup: noninteractive freeside-setup
+
+2002-08-24 18:09 ivan
+
+ * FS/bin/: freeside-adduser, freeside-setup: doc
+
+2002-08-24 01:13 ivan
+
+ * FS/bin/freeside-adduser: also do -b flag
+
+2002-08-24 00:43 ivan
+
+ * FS/FS/part_export/shellcommands.pm: allow $domain as a variable
+ in commands
+
+2002-08-24 00:20 ivan
+
+ * httemplate/edit/part_export.cgi: don't substitute defaults for
+ empty options when editing exports
+
+2002-08-23 23:41 ivan
+
+ * FS/FS/part_export/: domain_shellcommands.pm, shellcommands.pm,
+ www_shellcommands.pm: - depend on Net::SSH 0.07, for OpenSSH -T
+ fix - no strict 'vars'; when necessary
+
+2002-08-23 20:29 ivan
+
+ * httemplate/: view/cust_main.cgi, misc/unprovision.cgi:
+ unprovision a single service
+
+2002-08-23 19:10 ivan
+
+ * FS/bin/freeside-addoutsource: fix path
+
+2002-08-23 18:53 ivan
+
+ * FS/bin/freeside-queued: depend on Net::SSH 0.07, for -T fix
+
+2002-08-23 17:51 ivan
+
+ * httemplate/view/cust_main.cgi: UI
+
+2002-08-23 17:16 ivan
+
+ * FS/: MANIFEST, bin/freeside-addoutsource: Added Files:
+ bin/freeside-addoutsource
+
+2002-08-23 16:43 ivan
+
+ * FS/: MANIFEST, FS/part_export.pm,
+ FS/part_export/domain_shellcommands.pm,
+ t/part_export-domain_shellcommands.t: add domain_shellcommands
+ export
+
+2002-08-19 16:08 ivan
+
+ * httemplate/view/cust_main.cgi: encode_entities for comments
+ entries
+
+2002-08-11 23:17 ivan
+
+ * rt/: COPYING, ChangeLog, Makefile, README, TODO,
+ bin/initacls.Oracle, bin/initacls.Pg, bin/initacls.mysql,
+ bin/mason_handler.fcgi, bin/mason_handler.scgi, bin/rt,
+ bin/rt-mailgate, bin/rtadmin, bin/webmux.pl, docs/README.docs,
+ docs/Security, docs/rt.gif, docs/design_docs/CARS,
+ docs/design_docs/TransactionTypes.txt, docs/design_docs/acls,
+ docs/design_docs/basic-definitions.txt,
+ docs/design_docs/cli_spec, docs/design_docs/cvs_integration,
+ docs/design_docs/evil_plans,
+ docs/design_docs/link-definitions.txt,
+ docs/design_docs/local_hacking,
+ docs/design_docs/subscription-definitions.txt,
+ docs/design_docs/users, etc/acl.Oracle, etc/acl.Pg,
+ etc/acl.mysql, etc/config.pm, etc/rt.spec, etc/schema.Oracle,
+ etc/schema.Pg, etc/schema.mysql, etc/schema.pm, lib/MANIFEST,
+ lib/MANIFEST.SKIP, lib/Makefile.PL, lib/RT.pm, lib/test.pl,
+ lib/RT/ACE.pm, lib/RT/ACL.pm, lib/RT/Attachment.pm,
+ lib/RT/Attachments.pm, lib/RT/CurrentUser.pm, lib/RT/Date.pm,
+ lib/RT/EasySearch.pm, lib/RT/Group.pm, lib/RT/GroupMember.pm,
+ lib/RT/GroupMembers.pm, lib/RT/Groups.pm, lib/RT/Handle.pm,
+ lib/RT/Keyword.pm, lib/RT/KeywordSelect.pm,
+ lib/RT/KeywordSelects.pm, lib/RT/Keywords.pm, lib/RT/Link.pm,
+ lib/RT/Links.pm, lib/RT/ObjectKeyword.pm,
+ lib/RT/ObjectKeywords.pm, lib/RT/Queue.pm, lib/RT/Queues.pm,
+ lib/RT/Record.pm, lib/RT/Scrip.pm, lib/RT/ScripAction.pm,
+ lib/RT/ScripActions.pm, lib/RT/ScripCondition.pm,
+ lib/RT/ScripConditions.pm, lib/RT/Scrips.pm, lib/RT/Template.pm,
+ lib/RT/Templates.pm, lib/RT/TestHarness.pm, lib/RT/Ticket.pm,
+ lib/RT/Tickets.pm, lib/RT/Transaction.pm, lib/RT/Transactions.pm,
+ lib/RT/User.pm, lib/RT/Users.pm, lib/RT/Watcher.pm,
+ lib/RT/Watchers.pm, lib/RT/Action/Autoreply.pm,
+ lib/RT/Action/Generic.pm, lib/RT/Action/Notify.pm,
+ lib/RT/Action/NotifyAsComment.pm, lib/RT/Action/OpenDependent.pm,
+ lib/RT/Action/ResolveMembers.pm, lib/RT/Action/SendEmail.pm,
+ lib/RT/Action/SendPasswordEmail.pm,
+ lib/RT/Action/StallDependent.pm,
+ lib/RT/Condition/AnyTransaction.pm, lib/RT/Condition/Generic.pm,
+ lib/RT/Condition/NewDependency.pm,
+ lib/RT/Condition/StatusChange.pm, lib/RT/Interface/CLI.pm,
+ lib/RT/Interface/Email.pm, lib/RT/Interface/Web.pm,
+ tools/cpan2rpm, tools/initdb, tools/insertdata, tools/testdeps,
+ webrt/autohandler, webrt/index.html, webrt/Admin/index.html,
+ webrt/Admin/Elements/CreateQueueCalled,
+ webrt/Admin/Elements/CreateUserCalled,
+ webrt/Admin/Elements/EditUserComments,
+ webrt/Admin/Elements/GrantQueueRightsTo,
+ webrt/Admin/Elements/GroupTabs, webrt/Admin/Elements/Header,
+ webrt/Admin/Elements/ListGlobalKeywordSelects,
+ webrt/Admin/Elements/ListGlobalScrips,
+ webrt/Admin/Elements/ModifyKeyword,
+ webrt/Admin/Elements/ModifyKeywordSelect,
+ webrt/Admin/Elements/ModifyQueue,
+ webrt/Admin/Elements/ModifyTemplate,
+ webrt/Admin/Elements/ModifyUser,
+ webrt/Admin/Elements/QueueRightsForUser,
+ webrt/Admin/Elements/QueueTabs,
+ webrt/Admin/Elements/SelectKeywordSelect,
+ webrt/Admin/Elements/SelectModifyGroup,
+ webrt/Admin/Elements/SelectModifyKeyword,
+ webrt/Admin/Elements/SelectModifyKeywordSelect,
+ webrt/Admin/Elements/SelectModifyQueue,
+ webrt/Admin/Elements/SelectModifyUser,
+ webrt/Admin/Elements/SelectQueueRights,
+ webrt/Admin/Elements/SelectRights,
+ webrt/Admin/Elements/SelectScrip,
+ webrt/Admin/Elements/SelectScripAction,
+ webrt/Admin/Elements/SelectScripCondition,
+ webrt/Admin/Elements/SelectSingleOrMultiple,
+ webrt/Admin/Elements/SelectTemplate,
+ webrt/Admin/Elements/SelectUsers,
+ webrt/Admin/Elements/SystemTabs, webrt/Admin/Elements/Tabs,
+ webrt/Admin/Elements/UserTabs,
+ webrt/Admin/Global/GroupRights.html,
+ webrt/Admin/Global/Keywords.html, webrt/Admin/Global/Scrips.html,
+ webrt/Admin/Global/Template.html,
+ webrt/Admin/Global/Templates.html,
+ webrt/Admin/Global/UserRights.html,
+ webrt/Admin/Global/index.html, webrt/Admin/Groups/Members.html,
+ webrt/Admin/Groups/Modify.html, webrt/Admin/Groups/Rights.html,
+ webrt/Admin/Groups/index.html,
+ webrt/Admin/KeywordSelects/Modify.html,
+ webrt/Admin/KeywordSelects/index.html,
+ webrt/Admin/Keywords/Modify.html,
+ webrt/Admin/Keywords/index.html, webrt/Admin/Queues/Create.html,
+ webrt/Admin/Queues/GroupRights.html,
+ webrt/Admin/Queues/Keywords.html, webrt/Admin/Queues/Modify.html,
+ webrt/Admin/Queues/People.html, webrt/Admin/Queues/Scrips.html,
+ webrt/Admin/Queues/Template.html,
+ webrt/Admin/Queues/Templates.html,
+ webrt/Admin/Queues/UserRights.html,
+ webrt/Admin/Queues/index.html, webrt/Admin/Users/Modify.html,
+ webrt/Admin/Users/Prefs.html, webrt/Admin/Users/Rights.html,
+ webrt/Admin/Users/index.html, webrt/Elements/Checkbox,
+ webrt/Elements/CreateTicket, webrt/Elements/CustomHomepageHeader,
+ webrt/Elements/Error, webrt/Elements/Footer,
+ webrt/Elements/GotoTicket, webrt/Elements/Header,
+ webrt/Elements/ListActions, webrt/Elements/Login,
+ webrt/Elements/MessageBox, webrt/Elements/MyRequests,
+ webrt/Elements/MyTickets, webrt/Elements/Quicksearch,
+ webrt/Elements/Refresh, webrt/Elements/Section,
+ webrt/Elements/SelectBoolean, webrt/Elements/SelectDate,
+ webrt/Elements/SelectDateRelation, webrt/Elements/SelectDateType,
+ webrt/Elements/SelectEqualityOperator,
+ webrt/Elements/SelectKeyword,
+ webrt/Elements/SelectKeywordOptions,
+ webrt/Elements/SelectLinkType, webrt/Elements/SelectMatch,
+ webrt/Elements/SelectNewTicketQueue, webrt/Elements/SelectOwner,
+ webrt/Elements/SelectQueue, webrt/Elements/SelectResultsPerPage,
+ webrt/Elements/SelectSortOrder, webrt/Elements/SelectStatus,
+ webrt/Elements/SelectTicketSortBy, webrt/Elements/SelectUsers,
+ webrt/Elements/SelectWatcherType, webrt/Elements/ShadedBox,
+ webrt/Elements/Submit, webrt/Elements/Tabs,
+ webrt/Elements/TitleBoxEnd, webrt/Elements/TitleBoxStart,
+ webrt/Elements/ViewUser, webrt/Elements/dayMenu,
+ webrt/Elements/monthMenu, webrt/Elements/yearMenu,
+ webrt/NoAuth/Logout.html, webrt/NoAuth/Reminder.html,
+ webrt/NoAuth/webrt.css, webrt/NoAuth/images/rt.jpg,
+ webrt/NoAuth/images/spacer.gif, webrt/Search/Bulk.html,
+ webrt/Search/Listing.html, webrt/Search/PickRestriction,
+ webrt/Search/RestrictSearch.html, webrt/Search/TicketCell,
+ webrt/SelfService/Closed.html, webrt/SelfService/Create.html,
+ webrt/SelfService/Display.html, webrt/SelfService/Error.html,
+ webrt/SelfService/Prefs.html, webrt/SelfService/Update.html,
+ webrt/SelfService/index.html,
+ webrt/SelfService/Attachment/dhandler,
+ webrt/SelfService/Elements/GotoTicket,
+ webrt/SelfService/Elements/Header,
+ webrt/SelfService/Elements/MyRequests,
+ webrt/SelfService/Elements/Tabs, webrt/Ticket/Create.html,
+ webrt/Ticket/Display.html, webrt/Ticket/History.html,
+ webrt/Ticket/Modify.html, webrt/Ticket/ModifyAll.html,
+ webrt/Ticket/ModifyDates.html, webrt/Ticket/ModifyLinks.html,
+ webrt/Ticket/ModifyPeople.html, webrt/Ticket/Update.html,
+ webrt/Ticket/Attachment/dhandler,
+ webrt/Ticket/Elements/AddWatchers,
+ webrt/Ticket/Elements/EditBasics,
+ webrt/Ticket/Elements/EditDates,
+ webrt/Ticket/Elements/EditKeywordSelects,
+ webrt/Ticket/Elements/EditLinks,
+ webrt/Ticket/Elements/EditPeople,
+ webrt/Ticket/Elements/EditWatchers,
+ webrt/Ticket/Elements/ShowBasics,
+ webrt/Ticket/Elements/ShowDates,
+ webrt/Ticket/Elements/ShowDependencies,
+ webrt/Ticket/Elements/ShowHistory,
+ webrt/Ticket/Elements/ShowKeywordSelects,
+ webrt/Ticket/Elements/ShowLinks,
+ webrt/Ticket/Elements/ShowMemberOf,
+ webrt/Ticket/Elements/ShowMembers,
+ webrt/Ticket/Elements/ShowPeople,
+ webrt/Ticket/Elements/ShowReferences,
+ webrt/Ticket/Elements/ShowRequestor,
+ webrt/Ticket/Elements/ShowSummary,
+ webrt/Ticket/Elements/ShowTransaction,
+ webrt/Ticket/Elements/Tabs, webrt/Ticket/Elements/ToolBar,
+ webrt/User/Prefs.html: import rt 2.0.14
+
+2002-08-02 17:39 ivan
+
+ * httemplate/docs/: install.html, legacy.html: remove some extra
+ modules from install doc
+
+2002-07-31 11:55 ivan
+
+ * FS/FS/part_export.pm: delete directories when deleting users on
+ freebsd
+
+2002-07-31 06:18 ivan
+
+ * FS/FS/svc_acct.pm: fix bug with static IP addresses
+
+2002-07-26 20:56 ivan
+
+ * httemplate/misc/cancel-unaudited.cgi: move transaction from web
+ interface to lib code
+
+2002-07-26 19:47 ivan
+
+ * FS/bin/freeside-daily: vacuum pg databases daily
+
+2002-07-25 19:33 ivan
+
+ * FS/FS/: part_export.pm, part_export/shellcommands.pm:
+ shellcommands edit gecos field too
+
+2002-07-25 18:38 ivan
+
+ * httemplate/docs/install.html: tyop
+
+2002-07-25 18:31 ivan
+
+ * httemplate/docs/install.html: tyop
+
+2002-07-23 05:37 ivan
+
+ * FS/FS/svc_acct.pm: fix small bugs in duplicate username checking
+
+2002-07-22 03:50 ivan
+
+ * FS/t/ClientAPI.t, fs_selfservice/FS-SelfService/cgi/passwd.html:
+ adding
+
+2002-07-22 03:41 ivan
+
+ * httemplate/docs/install.html: no mysql in 1.4.0 release.
+ hopefully 1.4.1
+
+2002-07-22 03:20 ivan
+
+ * ANNOUCE.1.4.0, Makefile, README.1.4.0pre11, README.1.4.0pre12,
+ README.1.4.0pre13, README.1.4.0pre14, README.1.4.0pre8,
+ README.1.4.0pre9: 1.4.0
+
+2002-07-22 03:18 ivan
+
+ * FS/FS/CGI.pm: UI
+
+2002-07-22 03:18 ivan
+
+ * FS/FS/cust_main.pm: sort bills by date
+
+2002-07-16 05:29 ivan
+
+ * FS/: MANIFEST, FS/ClientAPI.pm, FS/ClientAPI/MyAccount.pm,
+ FS/ClientAPI/passwd.pm: ClientAPI
+
+2002-07-16 05:28 ivan
+
+ * fs_selfservice/: DEPLOY, freeside-selfservice-server,
+ fs_passwd_test, FS-SelfService/SelfService.pm,
+ FS-SelfService/freeside-selfservice-clientd,
+ FS-SelfService/cgi/login.html, FS-SelfService/cgi/myaccount.html,
+ FS-SelfService/cgi/selfservice.cgi,
+ FS-SelfService/cgi/view_invoice.html: invoice viewing...
+
+2002-07-15 20:57 ivan
+
+ * FS/FS/part_export/infostreet.pm: missing ; in eval'ed sub
+
+2002-07-15 20:56 ivan
+
+ * FS/FS/part_export/infostreet.pm: better error handling
+
+2002-07-15 20:47 ivan
+
+ * FS/FS/part_export/infostreet.pm: fix XML-RPC weirdness
+
+2002-07-15 01:28 ivan
+
+ * fs_selfservice/: freeside-selfservice-server, fs_passwd_test,
+ FS-SelfService/freeside-selfservice-clientd: working framework,
+ no hung clients, whew
+
+2002-07-14 18:44 ivan
+
+ * bin/bind.import: finally a working DNS::ZoneParse
+
+2002-07-13 17:28 ivan
+
+ * httemplate/docs/: install.html, upgrade8.html: no mason 1.1x yet
+ :(
+
+2002-07-11 06:52 ivan
+
+ * fs_selfservice/: DEPLOY, freeside-selfservice-server,
+ fs_passwd_test, FS-SelfService/MANIFEST,
+ FS-SelfService/SelfService.pm,
+ FS-SelfService/freeside-selfservice-clientd: finally working
+ async framework
+
+2002-07-08 19:23 ivan
+
+ * httemplate/docs/: schema.dia, schema.png: new schema diagram
+
+2002-07-08 10:14 ivan
+
+ * FS/bin/freeside-queued: oops, fix for bug only surfacing with
+ different freeside uid/gid
+
+2002-07-08 08:56 ivan
+
+ * httemplate/edit/svc_acct.cgi: better error message
+
+2002-07-08 06:07 ivan
+
+ * httemplate/edit/: REAL_cust_pkg.cgi, process/REAL_cust_pkg.cgi:
+ edit expiration dates
+
+2002-07-08 03:52 ivan
+
+ * httemplate/search/cust_bill.cgi: remove perl-side sort routines,
+ no longer needed
+
+2002-07-08 03:01 ivan
+
+ * FS/FS/part_export.pm: default linux/netbsd shellcommand userdel
+ should remove home directories
+
+2002-07-08 01:39 ivan
+
+ * httemplate/docs/install.html: new and improved instructions! now
+ even more idiot proof!
+
+2002-07-07 10:49 ivan
+
+ * FS/FS/svc_acct.pm: rewrite uid-dup checking to be
+ new-export-aware, closes: #431
+
+2002-07-07 07:33 ivan
+
+ * httemplate/search/cust_bill.cgi: clean up after rewrite... turned
+ out rather nice
+
+2002-07-07 07:28 ivan
+
+ * httemplate/search/cust_bill.cgi: fixing 30/60/90/120...
+
+2002-07-07 07:26 ivan
+
+ * httemplate/search/cust_bill.cgi: just might work
+
+2002-07-07 07:24 ivan
+
+ * httemplate/search/cust_bill.cgi: that would be nice...
+
+2002-07-07 07:18 ivan
+
+ * httemplate/search/cust_bill.cgi: fix 30/60/90/120 browses
+
+2002-07-07 07:14 ivan
+
+ * httemplate/search/cust_bill.cgi: UI
+
+2002-07-07 07:12 ivan
+
+ * httemplate/search/cust_bill.cgi: totals and order by
+
+2002-07-07 07:00 ivan
+
+ * httemplate/search/cust_bill.cgi: try for correct totals
+
+2002-07-07 06:52 ivan
+
+ * httemplate/search/cust_bill.cgi: don't recalculate owed
+
+2002-07-07 06:31 ivan
+
+ * httemplate/search/cust_bill.cgi: comma
+
+2002-07-07 06:30 ivan
+
+ * httemplate/search/cust_bill.cgi: calculate owed as subquery here
+ too
+
+2002-07-07 06:25 ivan
+
+ * httemplate/search/cust_bill.cgi: don't forget to where the where
+ clause
+
+2002-07-07 06:23 ivan
+
+ * httemplate/search/cust_bill.cgi: try for working paged invoices,
+ this time with subqueries
+
+2002-07-07 04:45 ivan
+
+ * httemplate/search/cust_bill.cgi: wtf?
+
+2002-07-07 04:30 ivan
+
+ * httemplate/search/cust_bill.cgi: invoice search with possibly
+ working pager
+
+2002-07-07 04:03 ivan
+
+ * httemplate/search/cust_bill.cgi: move query logic from perl to
+ sql for scalability
+
+2002-07-06 05:53 ivan
+
+ * httemplate/docs/install.html: new! improved! now even more
+ idiot-proof!
+
+2002-07-06 05:15 ivan
+
+ * Makefile: beta2
+
+2002-07-06 05:13 ivan
+
+ * bin/fs-setup: fix Can't use an undefined value as an ARRAY
+ reference at ./fs-setup line 209, <STDIN> line 3.
+
+2002-07-06 04:08 ivan
+
+ * httemplate/: edit/svc_forward.cgi, view/svc_forward.cgi: fix UI
+ for forwards - use HTML::Widgets::SelectLayers, closes: Bug#303
+
+2002-07-06 01:50 ivan
+
+ * httemplate/view/svc_acct.cgi: add "are you sure?" javascript on
+ view/svc_acct.cgi "cancel unaudited account" (closes: Bug#432)
+
+2002-07-06 01:29 ivan
+
+ * httemplate/view/: cust_pkg.cgi, cust_main.cgi: speling
+
+2002-07-06 00:32 ivan
+
+ * httemplate/edit/part_pkg.cgi: fix speling
+
+2002-07-06 00:31 ivan
+
+ * ANNOUCE.1.4.0: this file should probably go away soon...
+
+2002-07-06 00:30 ivan
+
+ * FS/FS/: Conf.pm, part_export.pm, svc_www.pm,
+ part_export/www_shellcommands.pm: move svc_www ssh jobs to the
+ job queue & exports, and make them configurable
+
+2002-07-05 21:20 ivan
+
+ * FS/FS/svc_acct.pm: typo
+
+2002-07-05 16:32 ivan
+
+ * httemplate/config/config.cgi: fix bug with config having a value
+ not in the select
+
+2002-07-04 03:35 ivan
+
+ * httemplate/browse/: agent.cgi, agent_type.cgi,
+ part_bill_event.cgi, part_export.cgi, part_pkg.cgi,
+ part_referral.cgi, part_svc.cgi, svc_acct_pop.cgi: move "add"
+ links to the top
+
+2002-07-03 07:45 ivan
+
+ * FS/t/part_export-http.t: s/_post//
+
+2002-07-03 07:21 ivan
+
+ * FS/: MANIFEST, FS/part_export.pm, FS/part_export/http.pm,
+ t/part_export-http.t: http export
+
+2002-07-03 04:37 ivan
+
+ * FS/FS/InitHandler.pm: 54
+
+2002-07-03 04:35 ivan
+
+ * FS/FS/InitHandler.pm: sacrifice memory for speed
+
+2002-07-03 04:31 ivan
+
+ * FS/FS/InitHandler.pm: preload modules
+
+2002-07-03 04:23 ivan
+
+ * FS/FS/: InitHandler.pm, UID.pm: fix to allow running during
+ apache init
+
+2002-07-03 04:10 ivan
+
+ * FS/FS/UID.pm: allow InitHandler to work during apache startup
+
+2002-07-03 03:50 ivan
+
+ * FS/FS/InitHandler.pm: skip comment & blank lines
+
+2002-07-03 03:48 ivan
+
+ * FS/FS/InitHandler.pm: debug
+
+2002-07-03 03:33 ivan
+
+ * FS/: MANIFEST, FS/InitHandler.pm, t/InitHandler.t: preload all
+ dbdefs
+
+2002-07-02 20:57 ivan
+
+ * FS/FS/cust_main.pm: working one-time charges again
+
+2002-07-02 20:52 ivan
+
+ * httemplate/view/cust_main.cgi: ui
+
+2002-07-02 20:47 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/quick-charge.cgi,
+ httemplate/view/cust_main.cgi: one-time charges with tax classes
+
+2002-07-02 19:25 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi: deprecate text radius config
+ options update config docs
+
+2002-07-02 18:47 ivan
+
+ * FS/: MANIFEST, bin/freeside-reexport: freeside-reexport
+
+2002-07-02 18:05 ivan
+
+ * FS/bin/freeside-sqlradius-reset: pod
+
+2002-07-02 18:01 ivan
+
+ * FS/bin/freeside-sqlradius-reset: fix usage message
+
+2002-07-02 16:03 ivan
+
+ * FS/FS/part_export.pm: fix usermod commands for freebsd
+
+2002-07-02 07:38 ivan
+
+ * ANNOUCE.1.4.0: beta1!
+
+2002-07-02 07:37 ivan
+
+ * Makefile: beta1!!
+
+2002-07-02 07:22 ivan
+
+ * FS/FS/part_export/textradius.pm: working textradius export
+
+2002-07-02 07:00 ivan
+
+ * FS/FS/part_export/textradius.pm: better diagnostics
+
+2002-07-02 06:22 ivan
+
+ * httemplate/view/cust_main.cgi: ui s/ /&nbsp;
+
+2002-07-02 06:04 ivan
+
+ * FS/FS/part_export/shellcommands.pm: no warnings
+
+2002-07-02 06:00 ivan
+
+ * FS/FS/: part_export.pm, part_export/shellcommands.pm: working
+ linux and freebsd shellcommands
+
+2002-07-02 04:29 ivan
+
+ * FS/FS/part_export.pm: fix for freebsd presets
+
+2002-07-02 04:27 ivan
+
+ * FS/FS/part_export.pm: useful shellcommands presets
+
+2002-07-02 03:14 ivan
+
+ * FS/bin/freeside-queued: grr old openssh grr freebsd
+
+2002-07-02 03:01 ivan
+
+ * httemplate/docs/install.html: freeside group
+
+2002-07-02 02:42 ivan
+
+ * FS/bin/freeside-queued: fleabsd grr
+
+2002-07-02 02:39 ivan
+
+ * FS/bin/freeside-queued: freebsd is sofa king broken
+
+2002-07-02 00:31 ivan
+
+ * FS/FS/part_export/textradius.pm: working textradius
+
+2002-07-02 00:13 ivan
+
+ * FS/FS/part_export/textradius.pm: better error reporting from
+ rsync
+
+2002-07-01 23:58 ivan
+
+ * FS/FS/part_export/: shellcommands.pm, www_shellcommands.pm:
+ s/options/option/, oops, and machine isn't an option
+
+2002-07-01 23:48 ivan
+
+ * FS/FS/queue.pm: error messages can have other chars
+
+2002-07-01 15:38 ivan
+
+ * FS/FS/part_export/textradius.pm: prevent any possible infinite
+ looping
+
+2002-07-01 02:15 ivan
+
+ * FS/FS/part_export/textradius.pm: real-time! text radius export
+
+2002-06-30 04:01 ivan
+
+ * ANNOUCE.1.4.0, CREDITS: administrivia
+
+2002-06-30 00:17 ivan
+
+ * FS/FS/Record.pm: oops, very bad
+
+2002-06-30 00:16 ivan
+
+ * FS/FS/Record.pm: get rid of unneeded Pg-cruft (don't use native
+ Pg money type)
+
+2002-06-30 00:04 ivan
+
+ * FS/FS/Record.pm: fix dbdef caching
+
+2002-06-29 19:13 ivan
+
+ * FS/: MANIFEST, FS/part_export.pm,
+ FS/part_export/shellcommands_withdomain.pm,
+ t/part_export-shellcommands_withdomain.t: export!
+
+2002-06-29 18:18 ivan
+
+ * httemplate/docs/ssh.html: adding
+
+2002-06-28 13:31 ivan
+
+ * FS/FS/svc_acct.pm, bin/populate-msgcat: better error message for
+ illegal password
+
+2002-06-28 13:23 ivan
+
+ * bin/fs-setup: not anymore...
+
+2002-06-28 13:21 ivan
+
+ * FS/FS/cust_main.pm: better error message for missing tax classes
+
+2002-06-28 03:49 ivan
+
+ * FS/FS/Record.pm: remove extraneous check
+
+2002-06-28 01:23 ivan
+
+ * FS/FS/: Record.pm, UID.pm: fix multi-database installs, while
+ hopefully keeping performance improvement
+
+2002-06-27 20:09 ivan
+
+ * httemplate/view/cust_main.cgi: more card display changes
+
+2002-06-27 19:21 ivan
+
+ * httemplate/view/cust_main.cgi: last 4 digits of card instead of
+ first
+
+2002-06-27 02:23 ivan
+
+ * FS/: FS/part_export/bind.pm, FS/part_export/bind_slave.pm,
+ t/part_export-bind.t, t/part_export-bind_slave.t: null bind
+ exports
+
+2002-06-27 02:19 ivan
+
+ * FS/: FS/part_export/bsdshell.pm, FS/part_export/null.pm,
+ FS/part_export/sysvshell.pm, FS/part_export/www_shellcommands.pm,
+ t/part_export-null.t, t/part_export-sysvshell.t,
+ t/part_export-www_shellcommands.t: export updates
+
+2002-06-26 01:36 ivan
+
+ * FS/FS/part_export.pm: tyop
+
+2002-06-26 01:32 ivan
+
+ * FS/FS/part_export.pm: better export docs/defaults
+
+2002-06-26 01:12 ivan
+
+ * FS/FS/cust_main.pm: add type_pkgs record if necessary for
+ one-time charges
+
+2002-06-26 01:05 ivan
+
+ * httemplate/view/cust_main.cgi: close form tags
+
+2002-06-26 00:42 ivan
+
+ * bin/: bsdshell.export, shell.export, sysvshell.export:
+ shell.export -> bsdshell.export & sysvshell.export
+
+2002-06-25 20:53 ivan
+
+ * FS/FS/part_export_option.pm: export options can be anything
+
+2002-06-25 19:37 ivan
+
+ * FS/FS/cust_bill.pm: fix not sending postal invoices to customers
+ with email invoices too
+
+2002-06-25 18:35 ivan
+
+ * FS/FS/cust_main.pm, httemplate/edit/process/quick-charge.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/view/cust_main.cgi: working one-time charges
+
+2002-06-25 17:41 ivan
+
+ * httemplate/edit/part_pkg.cgi: ui
+
+2002-06-25 16:27 ivan
+
+ * httemplate/view/svc_www.cgi: add link to controlling account
+
+2002-06-25 00:18 ivan
+
+ * FS/bin/freeside-queued: might work again under mysql
+
+2002-06-23 12:16 ivan
+
+ * FS/FS/domain_record.pm: domain_record records attached to svc_www
+ records are no longer delete-able, patch from "Stephen Bechard"
+ <steve@destek.net>, thanks! closes: Bug#434
+
+2002-06-22 22:44 ivan
+
+ * httemplate/edit/process/svc_www.cgi: patch to get this working
+ from Stephen Bechard <steve@destek.net>
+
+2002-06-22 22:43 ivan
+
+ * httemplate/view/svc_www.cgi: add link to edit and format nicely
+
+2002-06-22 18:36 ivan
+
+ * FS/FS/svc_www.pm: forgot . between zone and domain, patch from
+ "Stephen Bechard" <steve@destek.net>, thanks
+
+2002-06-22 18:33 ivan
+
+ * httemplate/edit/svc_www.cgi: forgot %> when converting from CGI,
+ works now, patch from "Stephen Bechard" <steve@destek.net>
+
+2002-06-21 14:49 ivan
+
+ * FS/FS/part_export/infostreet.pm: s/title/organization/ at
+ noment's request
+
+2002-06-21 13:26 ivan
+
+ * FS/FS/part_export/infostreet.pm: fix infostreet contact field
+ setting
+
+2002-06-21 13:17 ivan
+
+ * FS/FS/part_export/infostreet.pm: debugging option
+
+2002-06-21 02:57 ivan
+
+ * bin/passwd.import: no, don't check for duplicates like this by
+ default... not new-export style
+
+2002-06-21 02:56 ivan
+
+ * FS/FS/svc_acct.pm: better error messages on uid duplicates... uid
+ stuff still needs to be rewritten for new exports
+
+2002-06-21 02:28 ivan
+
+ * httemplate/docs/upgrade8.html: don't forget part_svc in upgrades
+
+2002-06-21 02:15 ivan
+
+ * bin/passwd.import: oops
+
+2002-06-21 02:13 ivan
+
+ * bin/: bind.import, fs-migrate-svc_acct_sm, passwd.import: import
+ fixes...
+
+2002-06-21 02:11 ivan
+
+ * bin/passwd.import: tiny bit better passwd.import
+
+2002-06-21 02:03 ivan
+
+ * httemplate/docs/upgrade8.html: doc
+
+2002-06-21 01:29 ivan
+
+ * httemplate/: index.html, docs/upgrade8.html: uid search on main
+ menu, updated upgrade docs
+
+2002-06-20 15:35 ivan
+
+ * FS/FS/part_export/infostreet.pm: fix infostreet contact field foo
+
+2002-06-20 15:31 ivan
+
+ * httemplate/docs/install.html: doc
+
+2002-06-19 18:29 ivan
+
+ * FS/FS/part_export.pm, FS/FS/part_export/shellcommands.pm,
+ FS/bin/freeside-queued, httemplate/edit/part_export.cgi,
+ httemplate/edit/process/part_export.cgi: shellcommands
+ w/passwords
+
+2002-06-18 21:54 ivan
+
+ * Makefile, bin/pod2x: pod build fix thanks to Stephen Bechard
+ <steve@destek.net>
+
+2002-06-18 21:03 ivan
+
+ * FS/FS/part_export/infostreet.pm: fix setContactField email
+
+2002-06-18 18:03 ivan
+
+ * FS/FS/svc_acct.pm: and the same for changes...
+
+2002-06-18 17:58 ivan
+
+ * FS/FS/svc_acct.pm: fix problem provisioning RADIUS groups
+ caused by kristian/mark/pc-intouch's changes moving exports into
+ svc_Common - changed sequence of events such that groups were
+ not provisioned when the sqlradius export was run
+
+2002-06-18 16:52 ivan
+
+ * httemplate/misc/queue.cgi: better error message
+
+2002-06-14 18:12 ivan
+
+ * FS/FS/part_export.pm, httemplate/edit/part_svc.cgi:
+ mark@pc-intouch.com: exporttype2svcdb removal
+
+2002-06-14 14:35 ivan
+
+ * FS/FS/part_export/infostreet.pm: freeside night to infostreet
+ faxNumber (? dunno, what noment wants)
+
+2002-06-14 04:44 ivan
+
+ * Makefile: better releaes target?
+
+2002-06-14 04:26 ivan
+
+ * ANNOUCE.1.4.0, Makefile, README.1.4.0pre14: 1.4.0pre14
+
+2002-06-14 04:22 ivan
+
+ * FS/: FS/Conf.pm, bin/freeside-queued, FS/cust_main.pm,
+ FS/queue.pm, FS/svc_Common.pm, FS/svc_acct.pm: working job
+ dependancies FS::queue::joblisting html excapes & truncates long
+ arguments welcome email (sheesh!) closes: Bug#420 (haha at 4:20
+ am, too. really!)
+
+2002-06-14 02:19 ivan
+
+ * FS/FS/UID.pm: only run callbacks once... should speed things up
+ (no dbdef reloading)
+
+2002-06-13 20:26 ivan
+
+ * httemplate/docs/legacy.html: s/svc_domain.import/bind.import/ to
+ match reality
+
+2002-06-13 20:12 ivan
+
+ * httemplate/: classic.html, index.html: remove classic interface
+
+2002-06-13 19:52 ivan
+
+ * httemplate/docs/: install.html, mysql.html: mysql support!
+
+2002-06-13 19:25 ivan
+
+ * FS/bin/freeside-queued: mysql compatibility?
+
+2002-06-13 17:12 ivan
+
+ * httemplate/: index.html, search/cust_main.cgi: search by for
+ address2 (unit) - commented out in default index.html
+
+2002-06-13 16:28 ivan
+
+ * httemplate/: index.html, search/cust_main.cgi: phone number
+ search (Bug#422)
+
+2002-06-13 16:00 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/index.html,
+ httemplate/search/svc_acct.cgi: fuzzy username searching
+ (Bug#422)
+
+2002-06-12 18:29 ivan
+
+ * fs_signup/fs_signup_server: more information in signup email
+
+2002-06-12 17:53 ivan
+
+ * httemplate/: index.html, search/cust_main.cgi: search on customer
+ number (Bug#422)
+
+2002-06-12 13:31 ivan
+
+ * FS/FS/svc_acct.pm: fix new duplicate username checking
+
+2002-06-12 10:29 ivan
+
+ * httemplate/index.html: fix company search
+
+2002-06-12 09:26 ivan
+
+ * FS/FS/cust_main.pm: fix problems with code that resets invoice
+ events
+
+2002-06-11 11:32 ivan
+
+ * bin/shell.export: don't export empty files
+
+2002-06-11 11:25 ivan
+
+ * bin/shell.export: use FS::cust_svc and FS::svc_acct
+
+2002-06-11 11:23 ivan
+
+ * bin/shell.export: bsd only for now
+
+2002-06-11 11:20 ivan
+
+ * bin/: bind.export, shell.export: perl 5.005 needs an explicit
+ mask for mkdir
+
+2002-06-11 02:51 ivan
+
+ * FS/FS/part_export.pm: notes
+
+2002-06-11 02:46 ivan
+
+ * bin/: bind.export, shell.export: add preliminary bsd shell export
+
+2002-06-11 02:14 ivan
+
+ * FS/FS/svc_acct.pm: export-based duplicate username checking!
+
+2002-06-11 01:29 ivan
+
+ * FS/FS/part_export.pm, httemplate/edit/part_export.cgi: add crypt
+ option to (bsd|sysv)shell export
+
+2002-06-10 20:25 ivan
+
+ * FS/FS/: part_export.pm, svc_Common.pm, svc_acct.pm,
+ part_export/infostreet.pm: - add new suspend and unsuspend export
+ hooks (with null defaults) - infostreet export: actually
+ suspend/unsuspend at infostreet (closes: Bug#418) - infostreet
+ export: set some contact fields @ infostreet (Bug#419)
+
+2002-06-10 17:58 ivan
+
+ * Makefile, init.d/freeside-init: dist fixes. locate more stuff in
+ Makefile. whew.
+
+2002-06-10 16:02 ivan
+
+ * FS/FS/domain_record.pm: fix *** ERROR: unterminated L<...> at
+ line 299 in file FS/domain_record.pm
+
+2002-06-10 15:48 ivan
+
+ * FS/FS/cust_main.pm, httemplate/misc/bill.cgi: also retry cards
+ when user clicks "Bill now" (closes: Bug#417)
+
+2002-06-10 15:07 ivan
+
+ * FS/FS/: cust_bill_event.pm, cust_main.pm: retry realtime_card
+ invoice events when a card changes (closes: Bug#417)
+
+2002-06-10 12:44 ivan
+
+ * httemplate/view/cust_main.cgi: final visual update on package
+ date view
+
+2002-06-10 12:41 ivan
+
+ * httemplate/view/cust_main.cgi: fixup time display in packages
+
+2002-06-10 12:30 ivan
+
+ * httemplate/view/cust_main.cgi: add small time display to dates
+
+2002-06-09 19:52 ivan
+
+ * FS/FS/: svc_Common.pm, svc_domain.pm: re-my'ed var
+
+2002-06-09 19:52 ivan
+
+ * FS/FS/cust_main_county.pm: silence undefined warnings
+
+2002-06-09 19:51 ivan
+
+ * FS/FS/CGI.pm: unused global
+
+2002-06-09 19:42 ivan
+
+ * Makefile: back to ASP for profiling...
+
+2002-06-09 18:39 khoff
+
+ * FS/FS/part_pkg.pm, FS/FS/pkg_svc.pm, bin/fs-setup,
+ httemplate/browse/part_pkg.cgi, httemplate/docs/schema.html,
+ httemplate/edit/part_pkg.cgi: Rollback part_pkg.def_svcpart
+ changes.
+
+2002-06-08 00:48 khoff
+
+ * FS/FS/part_pkg.pm, FS/FS/pkg_svc.pm, bin/fs-setup,
+ httemplate/browse/part_pkg.cgi, httemplate/docs/schema.html,
+ httemplate/edit/part_pkg.cgi: Default svcpart support for
+ part_pkg. Fixes 'bug' with new customer and online signup.
+
+2002-06-07 13:33 khoff
+
+ * FS/FS/cust_bill.pm: Setup hash for CC failed Text::Template
+
+2002-06-05 15:46 ivan
+
+ * httemplate/search/: cust_main.cgi, cust_pkg.cgi, svc_acct.cgi:
+ more mysql goodness, thanks dale
+
+2002-06-04 10:37 ivan
+
+ * httemplate/docs/install.html: small doc patch from
+ baloo@gimpgirl.org
+
+2002-06-04 07:35 ivan
+
+ * FS/FS/: cust_credit.pm, cust_pay.pm: fix unsuspendauto
+
+2002-06-04 07:02 ivan
+
+ * CREDITS, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/svc_acct.cgi:
+ mysql support! thanks to Donald Greer <dgreer@austintx.com> for
+ the SQL and Dale Hege <fhege@lumenexus.net> for the patches
+
+2002-06-04 06:46 ivan
+
+ * conf/declinetemplate: misspelling
+
+2002-05-31 15:37 ivan
+
+ * bin/fs-setup: no state necessary in batch cards (i18n)
+
+2002-05-31 13:34 ivan
+
+ * FS/FS/part_export.pm: dammit i want to catch export subclass
+ compilation problems
+
+2002-05-31 13:31 ivan
+
+ * FS/FS/cust_bill.pm: better error reporting
+
+2002-05-31 11:48 khoff
+
+ * FS/t/part_export-sqlmail.t: Don't ask me. I just hacked Ivan's
+ test.
+
+2002-05-31 11:45 khoff
+
+ * FS/MANIFEST: added sqlmail.pm and test
+
+2002-05-31 10:50 ivan
+
+ * FS/FS/svc_forward.pm: typo noticed by <Kaa>
+
+2002-05-30 19:13 ivan
+
+ * FS/FS/part_export.pm: no, actually throw an exception if an
+ export class won't compile.
+
+2002-05-30 17:33 khoff
+
+ * httemplate/edit/part_svc.cgi: Added support for part_exports that
+ are used with more than one svcdb.
+
+2002-05-30 17:22 khoff
+
+ * FS/FS/part_export.pm: updated hashes 'n stuff for
+ FS::part_export::sqlmail
+
+2002-05-30 17:20 khoff
+
+ * FS/FS/part_export/sqlmail.pm: part_export module to export
+ svc_acct, svc_domain, and svc_forward to an external database
+
+2002-05-30 17:18 khoff
+
+ * FS/FS/: svc_Common.pm, svc_acct.pm, svc_domain.pm: Moved
+ new-style export calls to svc_Common.
+
+2002-05-30 15:45 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: don't double \r on old
+ templates
+
+2002-05-30 15:41 khoff
+
+ * fs_signup/ieak.template: the \r's are annoying and for some
+ reason weren't getting evaluated. Text::Template is inconsistent
+ about handling escaped characters between different versions.
+
+2002-05-30 15:36 khoff
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: replace newlines with
+ crlf here instead of escaping them in the template
+
+2002-05-30 14:51 ivan
+
+ * httemplate/misc/delete-customer.cgi: point to correct place for
+ hidecancelledcustomers config option
+
+2002-05-30 10:49 ivan
+
+ * FS/FS/part_export.pm: GRRRRRRRRRRRRR
+
+2002-05-29 13:45 ivan
+
+ * FS/bin/freeside-sqlradius-reset: eliminate harmless "Database
+ handle destroyed without explicit disconnect" errors
+
+2002-05-29 08:56 ivan
+
+ * FS/FS/part_export.pm: freeradius 0.5 doc
+
+2002-05-28 21:40 ivan
+
+ * fs_selfservice/: freeside-selfservice-server,
+ FS-SelfService/Changes, FS-SelfService/MANIFEST,
+ FS-SelfService/Makefile.PL, FS-SelfService/SelfService.pm,
+ FS-SelfService/test.pl: add fs_selfservice
+
+2002-05-28 14:22 ivan
+
+ * FS/FS/svc_acct.pm, bin/populate-msgcat: better error message for
+ "Illegal password"
+
+2002-05-28 00:55 ivan
+
+ * FS/FS/: part_export.pm, part_export/shellcommands.pm: point
+ people at DBI/DBD documentation for information on data sources.
+ *sigh*
+
+2002-05-26 23:53 ivan
+
+ * httemplate/edit/cust_bill_pay.cgi: fix javascript bug reported by
+ baloo@gimpgirl.com, thanks
+
+2002-05-23 06:00 ivan
+
+ * ANNOUCE.1.4.0, FS/FS/domain_record.pm, bin/bind.import,
+ bin/svc_domain.import, httemplate/edit/process/domain_record.cgi,
+ httemplate/view/svc_domain.cgi: bind: allow adding slave domains
+ too
+
+2002-05-22 11:44 ivan
+
+ * FS/FS/domain_record.pm, FS/FS/part_export.pm,
+ FS/FS/svc_domain.pm, bin/bind.export,
+ httemplate/edit/process/domain_record.cgi,
+ httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/delete-domain_record.cgi,
+ httemplate/misc/delete-part_export.cgi,
+ httemplate/view/svc_domain.cgi: bind export, editing zones,
+ deleting unaudited domains, mmm
+
+2002-05-22 05:17 ivan
+
+ * FS/FS/: cust_pkg.pm, cust_svc.pm: move some code from
+ FS::cust_pkg to FS::cust_svc, becomes the cancel method
+
+2002-05-22 04:39 ivan
+
+ * FS/FS/part_export.pm: - remove some out of date documentation -
+ die if an export class won't compile
+
+2002-05-22 03:53 ivan
+
+ * bin/bind.export: bind export
+
+2002-05-21 19:09 ivan
+
+ * FS/FS/part_export/sqlradius.pm: 5.6-isms
+
+2002-05-20 04:02 ivan
+
+ * bin/svc_domain.import: [no log message]
+
+2002-05-18 02:51 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_pay.pm, FS/FS/svc_domain.pm,
+ fs_signup/fs_signup_server: Mail::Internet 1.44
+
+2002-05-17 06:51 ivan
+
+ * httemplate/docs/install.html: tyop
+
+2002-05-16 20:47 ivan
+
+ * FS/FS/svc_acct.pm: freebsd `toor' user
+
+2002-05-16 07:28 ivan
+
+ * FS/: FS/part_export/bsdshell.pm, FS/part_export/textradius.pm,
+ t/part_export-bsdshell.t, t/part_export-textradius.t: adding
+ (stub) bsdshell and textradius exports
+
+2002-05-16 07:28 ivan
+
+ * bin/svc_acct.export: ip address is added by radius_reply method
+ already
+
+2002-05-16 07:27 ivan
+
+ * FS/MANIFEST, eg/export_template.pm: add (stub) bsdshell and
+ textradius exports
+
+2002-05-16 07:21 ivan
+
+ * FS/FS/part_export/infostreet.pm: force all infostreet arguments
+ to be string type, fixes: "0 as first character in password"
+ problem. also see the Frontier::Client manpage
+
+2002-05-16 06:42 ivan
+
+ * httemplate/: browse/part_svc.cgi, edit/part_svc.cgi: service
+ definition cloning
+
+2002-05-16 06:42 ivan
+
+ * FS/FS/svc_acct.pm: allow freebsd `toor' root user
+
+2002-05-16 00:53 ivan
+
+ * httemplate/docs/upgrade8.html: upgrade docs: run populate-msgcat
+
+2002-05-15 07:00 ivan
+
+ * FS/FS/: queue.pm, part_export/sqlradius.pm: use job dependancies
+ in FS::part_export::sqlradius.pm display job dependancies in
+ FS::queue::joblisting
+
+2002-05-15 06:24 ivan
+
+ * ANNOUCE.1.4.0, Makefile, README.1.4.0pre13, FS/FS.pm,
+ FS/MANIFEST, FS/FS/queue.pm, FS/FS/queue_depend.pm,
+ FS/FS/part_export/sqlradius.pm, FS/bin/freeside-queued,
+ FS/t/queue_depend.t, bin/fs-setup, eg/export_template.pm,
+ httemplate/docs/install.html, httemplate/docs/schema.dia,
+ httemplate/docs/schema.html, httemplate/docs/schema.png,
+ httemplate/docs/upgrade8.html: queue dependancies
+
+2002-05-14 00:36 ivan
+
+ * FS/FS/part_export/sqlradius.pm: don't use return value of UPDATE
+ to decide whether or not to INSERT.
+
+2002-05-13 17:27 ivan
+
+ * FS/FS/part_export/shellcommands.pm: shellcomands oops
+
+2002-05-10 00:54 ivan
+
+ * Makefile: always re-install init
+
+2002-05-10 00:50 ivan
+
+ * init.d/freeside-init: correct message
+
+2002-05-10 00:45 ivan
+
+ * FS/FS/svc_domain.pm: bad reuse of variable
+
+2002-05-10 00:42 ivan
+
+ * Makefile: INSTALLGROUP
+
+2002-05-09 09:41 ivan
+
+ * bin/populate-msgcat: permissions
+
+2002-05-09 08:26 ivan
+
+ * Makefile: final make release?
+
+2002-05-09 08:25 ivan
+
+ * Makefile: fix make release target
+
+2002-05-09 08:22 ivan
+
+ * Makefile: make release target
+
+2002-05-09 08:21 ivan
+
+ * httemplate/: edit/cust_main.cgi, view/cust_main.cgi:
+ s/Referral/Advertising source/
+
+2002-05-09 08:14 ivan
+
+ * httemplate/docs/: install.html, mysql.html: attempt to avoid
+ people installing and asking for help with MySQL despite the VERY
+ FUCKING CLEAR instructions that it isn't supported.
+
+2002-05-09 08:12 ivan
+
+ * FS/FS/cust_main_county.pm: don't duplicate state/county/country
+ pulldowns even with taxrates...
+
+2002-05-09 05:38 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_main.pm, FS/FS/cust_main_county.pm,
+ FS/FS/part_pkg.pm, FS/t/cust_tax_exempt.t, htetc/global.asa,
+ htetc/handler.pl, httemplate/browse/agent.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/edit/agent.cgi, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi: texas tax!
+
+2002-05-06 06:36 ivan
+
+ * FS/FS/cust_bill.pm: fixes gratuitous "Illegal payname" errors
+ reported by noment
+
+2002-05-04 08:00 ivan
+
+ * README.1.4.0pre12, FS/FS.pm, FS/MANIFEST,
+ FS/FS/cust_main_county.pm, FS/FS/cust_tax_exempt.pm,
+ FS/FS/part_pkg.pm, FS/t/cust_tax_exempt.pm, bin/fs-setup,
+ httemplate/docs/admin.html, httemplate/docs/schema.dia,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html:
+ schema changes for proper texas tax
+
+2002-05-03 18:11 ivan
+
+ * httemplate/: index.html, search/cust_pkg.cgi: add package search
+ by next bill date to main menu
+
+2002-05-03 17:59 ivan
+
+ * httemplate/search/cust_pkg.cgi: fix ranges on cust_pkg search
+
+2002-05-03 17:49 ivan
+
+ * httemplate/search/cust_pkg.html: point at correct .cgi
+
+2002-05-03 17:47 ivan
+
+ * FS/FS/cust_pkg.pm, fs_signup/fs_signup_server: prevent stuff
+ passed from template/user from being used in searches by signup
+ server
+
+2002-05-03 17:32 ivan
+
+ * httemplate/search/: cust_pkg.cgi, cust_pkg.html: lilunixbtch:
+ trying to pull accounts based on next billdate tofu_beast420: hmm
+ a report ordered by next bill date? tofu_beast420: i don't know
+ how you'd do that per _customer_ since a customer could have lots
+ of packages, but you could do a per-package report maybe?
+
+2002-04-29 22:43 ivan
+
+ * FS/FS/part_export.pm, bin/svc_domain.import: better BIND
+ integration
+
+2002-04-26 04:14 ivan
+
+ * FS/FS/: Conf.pm, svc_acct.pm: add username-nounderscore and
+ username-nodash config files
+
+2002-04-25 06:16 ivan
+
+ * fs_signup/fs_signup_server: fix signup server realtime-card foo
+
+2002-04-25 05:03 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/cgi/decline.html,
+ FS-SignupClient/cgi/signup.cgi: alternate decline handline (Bug
+ #408)
+
+2002-04-25 03:37 ivan
+
+ * FS/FS/part_pkg.pm, httemplate/edit/part_pkg.cgi: free_delayed try
+ #2
+
+2002-04-25 02:47 ivan
+
+ * FS/FS/part_pkg.pm, httemplate/edit/part_pkg.cgi: add flat_delayed
+ plan
+
+2002-04-24 18:15 ivan
+
+ * FS/FS/cust_main.pm: don't require_cardname for non-CARD payby's
+
+2002-04-24 15:14 ivan
+
+ * fs_signup/fs_signup_server: fix suspending all accounts in signup
+ server
+
+2002-04-24 02:09 ivan
+
+ * FS/FS/: Conf.pm, cust_main.pm: require_cardname option
+
+2002-04-24 02:03 ivan
+
+ * FS/FS/cust_main.pm, bin/populate-msgcat: msgcat error for credit
+ card expiration (closes: Bug#407)
+
+2002-04-23 00:32 ivan
+
+ * httemplate/edit/REAL_cust_pkg.cgi: harmless ui glitch
+
+2002-04-23 00:10 ivan
+
+ * FS/FS/Record.pm: fixes inserting strings that end in numbers to
+ TEXT columns... gah i hate SQL
+
+2002-04-22 15:45 ivan
+
+ * FS/FS/part_export.pm: use Tie::IxHash to present export options
+ in a reasonable order
+
+2002-04-22 14:36 ivan
+
+ * FS/FS/cust_main.pm: don't show extended debugging in error
+ messages that could end up on the signup server
+
+2002-04-22 14:23 ivan
+
+ * FS/FS/cust_pkg.pm: fix bug checking agents allowed to purchase
+ packages (moved from signups server)
+
+2002-04-22 14:18 ivan
+
+ * httemplate/edit/agent_type.cgi: add pkgpart to agent type listing
+
+2002-04-22 13:47 ivan
+
+ * FS/FS/cust_pkg.pm, fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/cgi/signup-alternate.html: - check
+ agentnum ability to order packages in FS::cust_pkg, not signup
+ server - order by recur price in signup-alternate template
+
+2002-04-20 05:37 ivan
+
+ * ANNOUCE.1.4.0, FS/FS/part_export.pm,
+ httemplate/edit/part_export.cgi: bind export
+
+2002-04-20 04:57 ivan
+
+ * FS/FS/domain_record.pm, FS/FS/part_export.pm, bin/passwd.import,
+ bin/svc_domain.erase, bin/svc_domain.import,
+ httemplate/docs/legacy.html:
+ working BIND import
+
+2002-04-20 03:49 ivan
+
+ * FS/FS/domain_record.pm: allow * MX records
+
+2002-04-20 03:12 ivan
+
+ * FS/FS/domain_record.pm: allow uppercase in zone data.
+
+2002-04-20 03:09 ivan
+
+ * FS/FS/domain_record.pm: allow uppercase zones...
+
+2002-04-19 23:34 ivan
+
+ * bin/populate-msgcat: perms
+
+2002-04-19 23:33 ivan
+
+ * bin/fs-setup: fixup fs-setup
+
+2002-04-19 19:06 ivan
+
+ * FS/FS/: cust_pkg.pm, cust_svc.pm: fix problem with edge case
+ where there *is* a pkg_svc record with quantity 0, when changing
+ packages and using the special case new service code
+
+2002-04-19 17:48 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: fix signup.cgi to be
+ sticky on *all* errors
+
+2002-04-19 16:50 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: make necessary stuff
+ for success.html global
+
+2002-04-19 16:44 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: deal with
+ morphing popnum field in widget, eek
+
+2002-04-19 16:35 ivan
+
+ * fs_signup/fs_signup_server: compare balance numerically to avoid
+ spurious suspensions
+
+2002-04-19 16:25 ivan
+
+ * FS/FS/svc_acct.pm: maybe just for debugging
+
+2002-04-19 15:56 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: okay
+ _really_ this time username and password should be working
+ outside the widget
+
+2002-04-19 15:34 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: okay finish
+ moving usernames out of the widget, should finally work now
+
+2002-04-19 15:32 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: fix noment's
+ signup template
+
+2002-04-19 15:18 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: syntax error
+
+2002-04-19 15:17 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: move
+ username/password out of widget
+
+2002-04-19 15:09 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup-alternate.html: fix silly
+ problem in H:W:SelectLayers with moving SELECTs to the real form
+
+2002-04-19 07:27 ivan
+
+ * FS/FS/cust_bill.pm: add phone to Business::OnlinePayment usage
+
+2002-04-19 06:17 ivan
+
+ * fs_signup/: fs_signup_server,
+ FS-SignupClient/cgi/signup-alternate.html,
+ FS-SignupClient/cgi/signup.cgi: signup server:
+ FS::part_pkg->payby kludge & example template which uses
+ H:W:SelectLayers
+
+2002-04-18 18:16 ivan
+
+ * Makefile, FS/FS/Record.pm, FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ fs_signup/fs_signup_server, init.d/freeside-init: - add init file
+ installation to Makefile, add unified init file - fix qsearch for
+ op => '!=', value => '' searches - fix invalid_catd typo - add
+ payby method to part_pkg and have fs_signup_server pass the data
+
+2002-04-17 13:43 ivan
+
+ * FS/FS/part_export/sqlradius.pm: fix usergroup_delete DELETE
+ syntax
+
+2002-04-17 12:47 ivan
+
+ * FS/FS/Record.pm: allow = in ut_text
+
+2002-04-17 05:14 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: use signup.html and
+ success.html from current dir...
+
+2002-04-17 05:06 ivan
+
+ * httemplate/index.html: fix default searches
+
+2002-04-17 04:59 ivan
+
+ * fs_signup/fs_signup_server: better debugging messages from signup
+ server
+
+2002-04-17 04:53 ivan
+
+ * fs_signup/fs_signup_server: fix signup_server-realtime
+
+2002-04-17 04:46 ivan
+
+ * fs_signup/FS-SignupClient/cgi/success.html: fix example success
+ template
+
+2002-04-17 04:43 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: allow for the no-pop
+ case
+
+2002-04-17 04:41 ivan
+
+ * FS/FS/Record.pm: get rid of debugging cruft
+
+2002-04-17 04:37 ivan
+
+ * fs_signup/fs_signup_server: forgot to use Date::Format for
+ sending email...
+
+2002-04-17 04:29 ivan
+
+ * fs_signup/fs_signup_server: small tyop
+
+2002-04-17 04:17 ivan
+
+ * fs_signup/FS-SignupClient/: Makefile.PL, SignupClient.pm: typo
+ adding agentnum setting possibility...
+
+2002-04-17 00:32 ivan
+
+ * fs_signup/FS-SignupClient/fs_signupd: also don't leak processes,
+ like fs_passwdd
+
+2002-04-16 22:48 ivan
+
+ * fs_passwd/fs_passwdd: forgotten semicolon
+
+2002-04-16 22:46 ivan
+
+ * fs_passwd/fs_passwdd: also untaint pid
+
+2002-04-16 22:44 ivan
+
+ * fs_passwd/fs_passwdd: *sigh*
+
+2002-04-16 22:42 ivan
+
+ * fs_passwd/fs_passwdd:
+ okay pid file has a change of working now
+
+2002-04-16 22:39 ivan
+
+ * fs_passwd/fs_passwdd: tyop
+
+2002-04-16 22:22 ivan
+
+ * fs_passwd/fs_passwdd: pid file foo
+
+2002-04-16 18:17 ivan
+
+ * fs_signup/fs_signup_server: kill ssh children on exit also, like
+ password server
+
+2002-04-16 18:14 ivan
+
+ * fs_passwd/fs_passwd_server: kill off ssh kid on exit...
+
+2002-04-16 17:25 ivan
+
+ * httemplate/search/cust_main.cgi: better ordering in search
+ results
+
+2002-04-16 16:14 ivan
+
+ * FS/FS/cust_main.pm: there it is! fix bug with
+ FS::cust_main::agent
+
+2002-04-16 15:56 ivan
+
+ * FS/FS/cust_bill.pm: further debugging...
+
+2002-04-16 15:52 ivan
+
+ * README.1.4.0pre12, FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ bin/fs-setup: further authorize.net description debugging
+ (agent??) and get rid of bad unique index on cust_bill_event
+
+2002-04-16 15:38 ivan
+
+ * FS/FS/cust_bill.pm: eek, problem with authorize.net description
+ field
+
+2002-04-16 14:24 ivan
+
+ * FS/bin/freeside-queued: auto-use export classes
+
+2002-04-16 13:13 ivan
+
+ * httemplate/browse/part_svc.cgi: ui
+
+2002-04-16 12:50 ivan
+
+ * httemplate/index.html: exports, then services...
+
+2002-04-16 03:47 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_bill_event.pm,
+ httemplate/index.html, httemplate/search/cust_bill_event.cgi,
+ httemplate/search/cust_bill_event.html,
+ httemplate/search/report_cc.html,
+ httemplate/search/report_credit.html,
+ httemplate/search/report_tax.html, httemplate/view/cust_bill.cgi:
+ report on failed billing events...
+
+2002-04-16 02:38 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ FS/bin/freeside-expiration-alerter, conf/declinetemplate,
+ httemplate/docs/billing.html: - send a notice to the customer
+ when their card is declined - closes: Bug#351 -
+ freeside-expiration-alerter works fine, closes: Bug#7
+
+2002-04-16 01:52 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_export.pm, FS/FS/svc_acct.pm,
+ FS/FS/part_export/vpopmail.pm, httemplate/docs/passwd.html,
+ httemplate/edit/part_export.cgi: move the last of the real-time
+ exports out of svc_acct.pm and into part_export
+
+2002-04-15 23:47 ivan
+
+ * httemplate/index.html: allow multiple search types on main
+ menu... more confusing but default is *too* fuzzy
+
+2002-04-15 17:02 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/SignupClient.pm,
+ FS-SignupClient/cgi/signup.cgi: allow signup to specify agentnum
+
+2002-04-14 02:11 ivan
+
+ * FS/MANIFEST, FS/FS/Conf.pm, FS/FS/part_export.pm,
+ FS/FS/svc_acct.pm, FS/FS/part_export/cp.pm,
+ FS/FS/part_export/cyrus.pm, FS/FS/part_export/infostreet.pm,
+ FS/FS/part_export/shellcommands.pm,
+ FS/FS/part_export/vpopmail.pm, FS/t/part_export-cp.t,
+ FS/t/part_export-cyrus.t, FS/t/part_export-shellcommands.t,
+ FS/t/part_export-vpopmail.t, eg/export_template.pm,
+ httemplate/docs/billing.html, httemplate/docs/legacy.html,
+ httemplate/docs/schema.dia, httemplate/docs/schema.html,
+ httemplate/docs/schema.png: - move cyrus, shellcommands, CP
+ exports exports to new-style - skeleton files for vpopmail
+ exports - documentation updates - add big schema diagram to docs
+
+2002-04-13 18:36 ivan
+
+ * httemplate/docs/billing.html: docu for invoice_lines(0) with no
+ arguments
+
+2002-04-13 06:36 ivan
+
+ * FS/FS.pm, FS/FS/Conf.pm, FS/FS/part_export.pm, FS/FS/svc_acct.pm,
+ FS/FS/part_export/cp.pm, FS/bin/freeside-overdue,
+ FS/bin/freeside-sqlradius-reset, bin/sqlradius_reset,
+ httemplate/edit/part_export.cgi: - documentation updates - move
+ Critical Path export to new-style export - bin/sqlradius_reset
+ gets a manpage and becomes FS/bin/freeside-sqlradius-reset
+
+2002-04-13 03:46 ivan
+
+ * httemplate/index.html: s/otaker/order-taker/
+
+2002-04-13 02:14 ivan
+
+ * FS/FS/cust_bill.pm: allow invoice_lines(0) meaning no limit, no
+ padding (see Bug#388)
+
+2002-04-13 01:51 ivan
+
+ * FS/FS/queue.pm, httemplate/misc/queue.cgi: bulk queue operations
+ (closes: Bug#389)
+
+2002-04-12 08:14 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm,
+ httemplate/edit/cust_pkg.cgi: fudge up FS::cust_pkg::order
+ ("Order and cancel packages") to try to move services between
+ svcparts as a last resort...
+
+2002-04-12 06:22 ivan
+
+ * FS/MANIFEST, FS/FS/Msgcat.pm, FS/FS/Record.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_invoice.pm, FS/FS/msgcat.pm,
+ FS/FS/part_export.pm, FS/FS/svc_acct.pm, FS/t/Msgcat.t,
+ fs_signup/fs_signup_server, htetc/global.asa, htetc/handler.pl,
+ httemplate/browse/part_svc.cgi, httemplate/edit/part_export.cgi,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/part_export.cgi,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/misc/delete-customer.cgi: - should finish off the
+ part_svc -> part_export s/one-to-many/many-to-many/ transition
+ (closes: Bug#375) - fixes a nasty export scoping bug with message
+ catalogs, whew
+
+2002-04-11 15:05 ivan
+
+ * README.1.4.0pre12, FS/FS.pm, FS/MANIFEST, FS/FS/export_svc.pm,
+ FS/FS/part_export.pm, FS/FS/part_svc.pm, FS/t/export_svc.t,
+ bin/fs-setup, bin/sqlradius_reset, httemplate/index.html,
+ httemplate/browse/part_export.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/part_export.cgi,
+ httemplate/edit/process/part_export.cgi,
+ httemplate/misc/delete-part_export.cgi: (almost) everything for
+ bug#375 - create export_svc table - part_svc to part_export is
+ now properly many-to-many, not one-to-many
+
+ still need to finish service editing (choosing exports) in
+ httemplate/edit/part_svc.cgi and
+ httemplate/edti/process/part_svc.cgi
+
+ and do somethinga about that manual $svcdb = 'svc_acct' in
+ httemplate/edit/part_export.cgi (do part_export records need a
+ svcdb? probably not... should be able to just pass an svcdb on
+ creation of new exports, move the big %exports hash into
+ part_export.pm and allow httemplate/edit/part_svc.cgi to query it
+ for exports that can apply to a given svcdb....
+
+2002-04-11 15:04 ivan
+
+ * FS/FS/Record.pm: use the AUTOLOAD that reports errors better &
+ fix problems with ut_domain losing data
+
+2002-04-10 06:42 ivan
+
+ * ANNOUCE.1.4.0, README.1.4.0pre12, FS/FS/Conf.pm, FS/FS/Record.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_main_invoice.pm,
+ FS/FS/svc_acct.pm, FS/FS/svc_acct_pop.pm, bin/populate-msgcat,
+ fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ fs_signup/FS-SignupClient/cgi/success.html,
+ httemplate/browse/msgcat.cgi, httemplate/docs/signup.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/msgcat.cgi,
+ httemplate/edit/process/msgcat.cgi: bulk checkin from working on
+ the road:
+
+ - use msgcat for more error messages - should be all things that
+ would come3 back from the signup server normally now - signup
+ server: don't display access number <SELECT> if there's none or
+ one - signup_server-realtime config option to run billing for
+ signup server signups immediately - signup server: pkg
+ available to success templates, better documentation on success
+ templates - httemplate/edit/msgcat.cgi fields are properly sticky
+ on errors - httemplate/edit/process/msgcat.cgi - don't update
+ identical fields
+
+2002-04-10 01:39 ivan
+
+ * bin/fs-setup: fix mistake in part_pop_local schema (not used by
+ anyone really so no big deal)
+
+2002-04-06 22:23 ivan
+
+ * FS/FS/Conf.pm, FS/FS/cust_bill.pm, FS/FS/cust_pay.pm,
+ fs_signup/fs_signup_server: send email on signup server signups
+ (closes: Bug#386)
+
+2002-04-06 21:56 ivan
+
+ * FS/FS/Conf.pm, FS/FS/msgcat.pm, bin/populate-msgcat,
+ conf/show-msgcat-codes, fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ httemplate/browse/msgcat.cgi, httemplate/docs/install.html,
+ httemplate/edit/msgcat.cgi, httemplate/edit/process/msgcat.cgi:
+ working message catalogs (not used for enough yet) - almost (but
+ not quite) closes Bug#385 - still have to catalog the backend
+ things triggered by signup server.
+
+2002-04-06 16:00 ivan
+
+ * FS/FS/Conf.pm, fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/docs/signup.html: - config option for signup server
+ payment types - credit card type pulldown on signup server
+ (closes: Bug#383)
+
+2002-04-06 14:32 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm, cust_bill_pkg.pm, cust_main.pm:
+ add a config option to set the Business::OnlinePayment
+ description field, and make some useful data available for the
+ config option. closes: Bug#378
+
+2002-04-06 13:39 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/SignupClient.pm,
+ FS-SignupClient/cgi/signup.cgi, FS-SignupClient/cgi/signup.html:
+ closes: bug#384 - adds security phrase to signup server also
+ (already in regular interface)
+
+2002-04-06 13:32 ivan
+
+ * httemplate/search/cust_main.cgi: fix visual glitch
+
+2002-04-06 12:37 ivan
+
+ * fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/Makefile.PL,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/fs_signupd,
+ fs_signup/FS-SignupClient/test.pl,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ httemplate/docs/install.html, httemplate/docs/signup.html: big
+ signup server cleanups. uses Storable for network protocol now.
+ - makes Bugs 384 & 385 easier - closes: Bug#382
+
+2002-04-05 16:08 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/edit/svc_acct.cgi,
+ httemplate/view/svc_acct.cgi: security phrase bug fixes
+
+2002-04-05 15:51 ivan
+
+ * ANNOUCE.1.4.0, CREDITS, Makefile, README.1.4.0pre12, FS/MANIFEST,
+ FS/FS/Conf.pm, FS/FS/msgcat.pm, FS/FS/svc_acct.pm, FS/t/msgcat.t,
+ bin/freeside-session-kill, bin/fs-setup, bin/populate-msgcat,
+ bin/sqlradius_reset, conf/locale, eg/table_template-svc.pm,
+ eg/table_template.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/index.html, httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/msgcat.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/svc_acct.cgi,
+ httemplate/view/svc_acct.cgi: - add message catalog table &
+ beginning of web interface - add security_phrase and conf option
+ to svc_acct.pm - random other stuff
+
+2002-04-05 15:37 jeff
+
+ * httemplate/view/cust_main.cgi: credit/refund display correction
+
+2002-04-05 12:52 ivan
+
+ * httemplate/edit/process/cust_credit_bill.cgi: don't specify date
+ (not on submitting form)
+
+2002-04-05 08:37 ivan
+
+ * eg/export_template.pm, httemplate/search/sql.cgi,
+ FS/t/part_export-infostreet.t, FS/t/part_export-sqlradius.t: oops
+ forgot these from working on the road
+
+2002-04-04 16:42 ivan
+
+ * FS/MANIFEST, FS/FS/part_export.pm,
+ FS/FS/part_export/infostreet.pm, FS/FS/part_export/sqlradius.pm,
+ fs_selfadmin/fs_mailadmin_server, httemplate/index.html,
+ httemplate/docs/install.html, httemplate/edit/part_export.cgi:
+ Checkin of disparate changes from working on the road: - generic
+ SQL query - move exports out to their own files - small cleanup
+ of selfadmin server
+
+2002-03-29 18:35 ivan
+
+ * httemplate/edit/part_referral.cgi: finish up
+ s/referral/advertising source/
+
+2002-03-29 09:27 ivan
+
+ * htetc/global.asa, htetc/handler.pl,
+ httemplate/search/svc_acct.cgi: fix unlinked svc browse!
+
+2002-03-27 16:18 ivan
+
+ * ANNOUCE.1.4.0: still pretty much just notes...
+
+2002-03-26 23:08 ivan
+
+ * FS/FS/queue.pm: don't show queue arguments (passwords!) on svc_*
+ screens (unless queue_dangerous_options!)
+
+2002-03-26 21:36 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/part_referral.pm,
+ httemplate/index.html, httemplate/browse/part_referral.cgi,
+ httemplate/docs/admin.html, httemplate/edit/part_referral.cgi:
+ s/referral/advertising source/
+
+ yes, the name sucks. got a better one?
+
+2002-03-26 15:18 ivan
+
+ * fs_passwd/fs_passwd.cgi: yay works now... just forgot to send
+ http header
+
+2002-03-26 08:24 ivan
+
+ * httemplate/search/cust_main.cgi: simple visual fix: &nbsp; for
+ blank company column
+
+2002-03-26 05:58 ivan
+
+ * FS/FS/part_svc.pm: forgot to use FS::part_export to search on it
+
+2002-03-26 05:20 ivan
+
+ * httemplate/docs/passwd.html: doc
+
+2002-03-26 05:04 ivan
+
+ * bin/create-history-tables: error message typo
+
+2002-03-26 04:35 ivan
+
+ * httemplate/docs/admin.html: s/Add/Provision/
+
+2002-03-25 16:32 ivan
+
+ * FS/FS/part_export.pm, FS/bin/freeside-queued,
+ bin/sqlradius_reset, httemplate/edit/part_export.cgi: further
+ export bugfixing add 10 kid limit to freeside-queued
+ sqlradius_reset now works (closes: Bug#372)
+
+2002-03-25 16:26 ivan
+
+ * Makefile: hhahah oops i _really_ ought to do something about that
+
+2002-03-25 06:59 ivan
+
+ * httemplate/: index.html, search/cust_main-otaker.cgi,
+ search/cust_main.cgi: customers by otaker report (ugly
+ search/cust_main.cgi mods; revert if they cause problems)
+
+2002-03-24 15:16 ivan
+
+ * bin/: icradius_reset, sqlradius_reset: s/icradius/sqlradius/
+
+2002-03-24 12:00 ivan
+
+ * httemplate/: edit/cust_main.cgi, search/svc_acct.cgi,
+ browse/agent.cgi: UI improvements for agents
+
+2002-03-24 10:23 ivan
+
+ * FS/FS/agent.pm: tyop
+
+2002-03-24 09:42 ivan
+
+ * CREDITS, FS/FS/part_pkg.pm, httemplate/edit/part_pkg.cgi:
+ "subscription" price plan from "Luke Pfeifer"
+ <freeside@globalli.com>
+
+2002-03-24 06:29 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_export.pm, FS/FS/queue.pm,
+ FS/FS/radius_usergroup.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/svc_acct.cgi:
+ ICRADIUS groups all done! UI and provisioning. closes: Bug#362
+
+ fix some bugs in the export and add queue_dangerous_controls
+ option too
+
+2002-03-23 09:49 ivan
+
+ * FS/FS/part_svc.pm, FS/FS/svc_acct.pm,
+ httemplate/browse/part_svc.cgi, httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi: okay group editing UI as
+ well as part_svc group editing UI seem to be working
+
+2002-03-23 08:16 ivan
+
+ * FS/FS/part_export.pm, FS/FS/queue.pm, FS/FS/svc_acct.pm,
+ httemplate/edit/svc_acct.cgi,
+ httemplate/edit/process/svc_acct.cgi: group editing seems to be
+ working... everything except defaults... oh and export...
+
+2002-03-22 23:54 ivan
+
+ * FS/bin/freeside-queued: redirect STDOUT/STDERR a bit later for
+ better error reporting
+
+2002-03-22 10:56 ivan
+
+ * Makefile, README.1.4.0pre12, FS/MANIFEST,
+ FS/FS/cust_main_county.pm, FS/FS/svc_acct.pm,
+ FS/t/radius_usergroup.t, bin/create-history-tables, bin/fs-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/view/svc_acct.cgi: RADIUS groups on the way!
+
+2002-03-22 04:49 ivan
+
+ * FS/MANIFEST, FS/FS/Record.pm, FS/FS/part_export.pm,
+ FS/t/part_export.t, FS/t/part_export_option.t,
+ httemplate/browse/part_svc.cgi, httemplate/edit/part_export.cgi,
+ httemplate/edit/process/part_export.cgi,
+ httemplate/misc/delete-part_export.cgi: more new export...
+
+2002-03-20 22:57 ivan
+
+ * FS/FS/part_export.pm, httemplate/edit/part_export.cgi,
+ httemplate/edit/process/part_export.cgi: more for the new world
+ of export...
+
+2002-03-20 13:31 ivan
+
+ * README.1.4.0pre12, FS/FS/Conf.pm, FS/FS/part_export.pm,
+ FS/FS/part_export_option.pm, FS/FS/part_svc.pm,
+ FS/FS/svc_acct.pm, FS/bin/freeside-queued, bin/icradius_reset,
+ bin/svc_acct.export, htetc/global.asa, htetc/handler.pl,
+ httemplate/docs/export.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_export.cgi,
+ httemplate/edit/process/part_export.cgi: new export! infostreet
+ and sqlradius provisioning switched over (Bug #299 - doesn't
+ close it, but all the groundwork is done)
+
+ also removes non-transactional ICRADIUS export from
+ svc_acct.export (closes: Bug#347)
+
+2002-03-19 23:37 ivan
+
+ * FS/FS/cust_main_county.pm: disable region caching for now
+
+2002-03-19 09:48 ivan
+
+ * FS/FS/cust_main_county.pm, httemplate/edit/cust_main.cgi,
+ httemplate/edit/process/cust_main.cgi: changes dum big
+ "state/county/country" select to three, linked with javascript
+ closes: Bug#353
+
+2002-03-18 13:40 ivan
+
+ * FS/FS/: Conf.pm, cust_bill.pm, part_bill_event.pm: bugfixes,
+ closes Bug#314
+
+2002-03-18 12:50 ivan
+
+ * httemplate/edit/part_bill_event.cgi, FS/FS/part_bill_event.pm,
+ FS/FS/Conf.pm: okay, now you can specify an alternate invoice
+ template, and it'll be auto-createad and added to the list of
+ configuration options. closes: Bug#314
+
+2002-03-18 11:49 ivan
+
+ * FS/FS/: Conf.pm, Record.pm, cust_bill.pm, cust_pay.pm: fixes: bug
+ #348 - adds the ability to email on deleted payments.
+
+2002-03-18 11:40 ivan
+
+ * httemplate/search/cust_main-quickpay.html: update quickpay for
+ current search capabilities
+
+2002-03-18 09:50 ivan
+
+ * httemplate/config/config.cgi:
+ fixes bug#367 (yay, that one was annoying):
+
+ in config editor, initial newlines in <textarea>s are lost. even
+ if you didn't mean to edit them you remove that..
+
+2002-03-18 08:07 ivan
+
+ * bin/backup-freeside: removing backup-freeside script from here
+
+2002-03-18 08:05 ivan
+
+ * FS/FS/: svc_Common.pm, svc_acct.pm: handle inserting cust_svc and
+ svc_acct records separately also, to handle imports preserving
+ svcnum
+
+2002-03-18 07:52 ivan
+
+ * httemplate/edit/: part_export.cgi, process/part_export.cgi: added
+ (incomplete) export foo
+
+2002-03-18 07:51 ivan
+
+ * httemplate/browse/part_svc.cgi: UI glitch; forgot ROWSPAN for
+ export column
+
+2002-03-18 06:17 ivan
+
+ * FS/FS/raddb.pm: add noment-specific RADIUS attributes
+
+2002-03-18 01:10 ivan
+
+ * README.1.4.0pre12, FS/FS/Conf.pm, FS/FS/svc_domain.pm,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/docs/upgrade8.html: new config value `defaultrecords',
+ documentation, javascript config file editor
+
+2002-03-17 00:33 ivan
+
+ * httemplate/config/: config-view.cgi, config.cgi: new domain
+ record editing foo
+
+2002-03-12 10:45 ivan
+
+ * httemplate/misc/cancel-unaudited.cgi: print error message for
+ failed cancels!
+
+2002-03-12 07:33 ivan
+
+ * README.1.4.0pre12, htetc/global.asa, htetc/handler.pl,
+ httemplate/docs/install.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/part_svc.cgi:
+ abstract stupid HTML layer trick out to
+ HTML::Widgets::SelectLayers
+
+2002-03-09 02:19 khoff
+
+ * FS/FS/: Conf.pm, svc_domain.pm: Support for default CNAME/A
+ records
+
+2002-03-07 11:50 jeff
+
+ * FS/bin/: freeside-cc-receipts-report, freeside-credit-report,
+ freeside-expiration-alerter, freeside-receivables-report,
+ freeside-tax-report: less shelling, more perly - abolish some
+ pipes to sendmail
+
+2002-03-07 06:13 ivan
+
+ * FS/FS/cust_bill.pm: better error msgs for mail errors
+
+2002-03-07 06:10 ivan
+
+ * FS/FS/: cust_bill.pm, part_export.pm, part_export_option.pm,
+ queue.pm: [no log message]
+
+2002-03-06 15:32 ivan
+
+ * conf/invoice_from: oops, missing invoice_from
+
+2002-03-06 15:31 ivan
+
+ * httemplate/docs/upgrade8.html: add freeside-expiration-alerter to
+ upgrade8.html
+
+2002-03-06 14:44 jeff
+
+ * README.1.4.0pre12, FS/MANIFEST, FS/FS/Conf.pm,
+ FS/bin/freeside-expiration-alerter, conf/alerter_template,
+ httemplate/docs/admin.html: billing expiration alerts
+
+2002-03-05 16:17 ivan
+
+ * FS/bin/: freeside-cc-receipts-report, freeside-credit-report,
+ freeside-receivables-report, freeside-tax-report: remove CVS Log
+ tag
+
+2002-03-05 15:13 jeff
+
+ * FS/bin/freeside-cc-receipts-report,
+ FS/bin/freeside-credit-report,
+ FS/bin/freeside-receivables-report, FS/bin/freeside-tax-report,
+ httemplate/search/report_cc.cgi,
+ httemplate/search/report_credit.cgi,
+ httemplate/search/report_tax.cgi: consistency is nice
+
+2002-03-05 01:44 ivan
+
+ * FS/bin/freeside-receivables-report: yes i have crazy customers
+ with 8-digit customer numbers
+
+2002-03-04 14:10 ivan
+
+ * FS/FS/Record.pm: make history tables conditional
+
+2002-03-04 04:48 ivan
+
+ * Makefile, README.1.4.0pre12, FS/FS/Record.pm, FS/FS/nas.pm,
+ bin/create-history-tables, bin/fs-radius-add-check,
+ bin/fs-radius-add-reply, bin/fs-setup,
+ httemplate/docs/upgrade8.html: [no log message]
+
+2002-03-03 15:46 ivan
+
+ * httemplate/docs/install.html: docu
+
+2002-02-28 15:30 ivan
+
+ * httemplate/search/svc_acct.cgi: tyop
+
+2002-02-28 15:18 ivan
+
+ * FS/FS/svc_acct.pm: clean up mess. *sigh*
+
+2002-02-28 15:17 ivan
+
+ * FS/FS/svc_acct.pm: clean up mess
+
+2002-02-28 15:13 ivan
+
+ * FS/FS/svc_acct.pm: eek
+
+2002-02-28 15:08 ivan
+
+ * httemplate/search/svc_acct.cgi: add main menu link
+
+2002-02-28 15:07 ivan
+
+ * httemplate/misc/cancel-unaudited.cgi: handle errors better
+
+2002-02-28 14:05 ivan
+
+ * FS/FS/Conf.pm, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi: s/depreciated/deprecated/
+
+2002-02-27 16:28 jeff
+
+ * FS/FS/svc_acct.pm: improved vpopmail support for svc_acct records
+
+2002-02-27 15:20 ivan
+
+ * FS/FS/cust_main.pm: oops, spurious error messages
+
+2002-02-27 15:03 ivan
+
+ * FS/FS/cust_main.pm: bubble up billing event errors
+
+2002-02-27 14:40 ivan
+
+ * FS/FS/cust_bill_event.pm: and missing ) *sigh*
+
+2002-02-27 14:40 ivan
+
+ * FS/FS/cust_bill_event.pm: errant ;
+
+2002-02-27 14:39 ivan
+
+ * README.1.4.0pre12, FS/FS/cust_bill_event.pm, bin/fs-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html,
+ httemplate/view/cust_bill.cgi: add status and statustext fields
+ to cust_bill_event
+
+2002-02-27 14:00 ivan
+
+ * FS/FS/cust_main.pm: well, don't make things worse when
+ debugging...
+
+2002-02-27 13:57 ivan
+
+ * FS/: FS/cust_main.pm, bin/freeside-daily: better debugging
+
+2002-02-27 09:07 khoff
+
+ * httemplate/docs/upgrade8.html: Should be "CREATE TABLE" not
+ "CREATE INDEX" for part_export_option
+
+2002-02-26 14:09 ivan
+
+ * httemplate/search/: report_cc.cgi, report_credit.cgi,
+ report_receivables.cgi, report_tax.cgi: fixup reports for
+ templated webUI
+
+2002-02-26 03:53 ivan
+
+ * FS/FS/cust_main.pm: okay, finally fix all the weirdness with
+ shipping adresses. whew.
+
+2002-02-26 03:42 ivan
+
+ * FS/FS/: Record.pm, cust_main.pm: in Record.pm - call ->check
+ **BEFORE** generating @diff for SQL. causing weird effects with
+ cust_main::check that modifies record (ship_ field weirdness)
+
+ fix nasty logic error triggered by changing a ship_ field from
+ something TO identical to the corresponding non-ship_ field.
+ ouch
+
+2002-02-26 03:30 ivan
+
+ * FS/FS/cust_main.pm: fix nasty logic error triggered by changing a
+ ship_ field from something TO identical to the corresponding
+ non-ship_ field. ouch.
+
+2002-02-26 03:11 ivan
+
+ * httemplate/edit/cust_main.cgi: fix a weird oops with service
+ address editing UI that would leave some fields blank... ?
+
+2002-02-26 01:06 ivan
+
+ * FS/FS/cust_bill.pm: ugh, payname needs first/last i guess
+
+2002-02-26 00:34 ivan
+
+ * FS/FS/cust_main.pm: die with a better error message on bad
+ locales
+
+2002-02-25 11:09 ivan
+
+ * httemplate/search/svc_acct.cgi: keith@landel: We have users
+ that have the character "." in their username we can't search
+ these customers by Username, can you please fix.
+
+2002-02-23 14:36 ivan
+
+ * httemplate/search/: report_cc.cgi, report_credit.cgi,
+ report_receivables.cgi, report_tax.cgi: take hardcoded paths out
+ of report cgis
+
+2002-02-23 03:56 ivan
+
+ * CREDITS, FS/FS/Record.pm, httemplate/docs/index.html,
+ httemplate/search/cust_main.cgi,
+ httemplate/search/cust_main.html: case-insensitive and substring
+ searching
+
+2002-02-23 03:46 ivan
+
+ * httemplate/index.html: silly html tweaking
+
+2002-02-22 23:48 ivan
+
+ * httemplate/browse/part_pkg.cgi: it's too late.
+
+2002-02-22 23:35 ivan
+
+ * httemplate/browse/part_pkg.cgi: i really should just start moving
+ things to templates
+
+2002-02-22 23:32 ivan
+
+ * httemplate/browse/: part_pkg.cgi, part_svc.cgi: UI nit fixes -
+ misaligned columns when viewing disabled services/packages
+
+2002-02-22 23:00 ivan
+
+ * FS/FS/UID.pm: nit
+
+2002-02-22 18:14 jeff
+
+ * FS/FS/UID.pm, bin/svc_acct.export,
+ httemplate/search/report_cc.cgi,
+ httemplate/search/report_credit.cgi,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/report_tax.cgi: report fixes and cruft removal
+
+2002-02-22 18:02 ivan
+
+ * httemplate/: index.html, docs/install.html, docs/upgrade8.html:
+ UI work on main menu, remove Archive::Tar from docs
+
+2002-02-22 15:18 jeff
+
+ * FS/MANIFEST, FS/bin/freeside-cc-receipts-report,
+ FS/bin/freeside-credit-report,
+ FS/bin/freeside-receivables-report, FS/bin/freeside-tax-report,
+ conf/report_template, httemplate/classic.html,
+ httemplate/index.html, httemplate/search/report_cc.cgi,
+ httemplate/search/report_cc.html,
+ httemplate/search/report_credit.cgi,
+ httemplate/search/report_credit.html,
+ httemplate/search/report_receivables.cgi,
+ httemplate/search/report_tax.cgi,
+ httemplate/search/report_tax.html: add some reporting features
+
+2002-02-22 15:08 ivan
+
+ * FS/FS/cust_pay_batch.pm: fix i18n zip
+
+2002-02-22 14:13 ivan
+
+ * httemplate/edit/cust_main.cgi: billing vs. shipping states
+ weren't sorted in the same order. UI glitch only
+
+2002-02-22 04:31 ivan
+
+ * httemplate/config/: config-process.cgi, config-view.cgi: fixup
+ <SELECT> configuration editing, fixes Bug#350
+
+2002-02-22 04:13 ivan
+
+ * httemplate/index.html: close </FORM> tags
+
+2002-02-22 01:01 ivan
+
+ * FS/FS/svc_acct.pm: correctly disable/enable accounts @ CP
+
+2002-02-22 00:58 ivan
+
+ * FS/FS/svc_acct.pm: freeside *SUSPENDED* -> CP set_mailbox_status
+ OTHER/OTHER_BOUNCE
+
+2002-02-21 23:50 ivan
+
+ * bin/fs-setup: doh
+
+2002-02-21 22:42 ivan
+
+ * FS/FS/queue.pm: UI in joblisting: don't split ( retry | remove )
+ links
+
+2002-02-21 22:39 ivan
+
+ * FS/FS/queue.pm: don't error out on bad svcnum's, just silently
+ remove them
+
+2002-02-21 22:23 ivan
+
+ * FS/FS/svc_acct.pm: don't leak perl line numbers on cp
+ provisioning errors
+
+2002-02-21 21:56 ivan
+
+ * FS/FS/svc_acct.pm: fix bugs in CP mailbox changes: cp_change and
+ cp_rename
+
+2002-02-21 17:07 ivan
+
+ * FS/FS/Conf.pm, httemplate/view/cust_main.cgi,
+ httemplate/view/cust_pkg.cgi: UI work:
+
+ make all functions of view/cust_pkg.cgi available on
+ view/cust_main.cgi - having them one link down in "Edit" is
+ confusing.
+
+ closes: Bug#325
+
+2002-02-21 15:17 ivan
+
+ * bin/fs-setup: queue.svcnum is nullable too, oops
+
+2002-02-21 13:43 ivan
+
+ * bin/fs-setup: looks like statustext field is missing NULL flag in
+ fs-setup
+
+2002-02-20 14:03 ivan
+
+ * httemplate/index.html: invoice reports belong here too
+
+2002-02-20 02:39 ivan
+
+ * FS/FS/CGI.pm: fixes eidiot under Mason, closes: Bug#344
+
+2002-02-20 01:44 ivan
+
+ * httemplate/view/cust_main.cgi: don't display full card in
+ webinterface
+
+2002-02-19 19:17 jeff
+
+ * FS/FS/cust_main.pm: correct sense of tax generation
+
+2002-02-19 17:03 ivan
+
+ * CREDITS, README.1.4.0pre11, README.1.4.0pre8, FS/FS/CGI.pm,
+ FS/FS/Record.pm, FS/FS/queue.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_domain.pm, FS/FS/svc_forward.pm,
+ FS/bin/freeside-queued, bin/fs-setup, htetc/global.asa,
+ htetc/handler.pl, httemplate/index.html,
+ httemplate/browse/queue.cgi, httemplate/misc/queue.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_domain.cgi,
+ httemplate/view/svc_forward.cgi, httemplate/view/svc_www.cgi: use
+ Net::SSH::ssh_cmd for all job queueing rather than local
+ duplicated ssh subs
+
+ queue daemon updates: retry & remove links work, bubble up error
+ message to webinterface, link to svcnum & have job listings on
+ view/svc_* pages, closes: Bug#280
+
+ s/option/optionname/ schema change, dumb mysql, closes: Bug#334
+
+2002-02-19 15:43 ivan
+
+ * httemplate/docs/: install.html, schema.html, upgrade8.html: set
+ EVERYTHING=1 for your own mod_perl compile
+
+2002-02-18 23:51 ivan
+
+ * httemplate/index.html: oops
+
+2002-02-18 23:00 ivan
+
+ * httemplate/classic.html: TMTOWTDI
+
+2002-02-18 20:43 ivan
+
+ * httemplate/index.html: new main menu!
+
+2002-02-18 19:22 jeff
+
+ * FS/FS/cust_refund.pm: fix refund posting
+
+2002-02-18 19:15 ivan
+
+ * FS/FS/cust_refund.pm: <rluser> ut_number instead of ut_numbern
+
+2002-02-18 19:06 ivan
+
+ * FS/FS/cust_refund.pm: need to use FS::Record qw(qsearch) !
+
+2002-02-18 18:57 ivan
+
+ * httemplate/: edit/part_pkg.cgi, view/cust_main.cgi: allow custom
+ packages to edit service quantities also
+
+2002-02-18 12:09 ivan
+
+ * httemplate/edit/part_svc.cgi: bad warning, causing errors with
+ strict
+
+2002-02-18 10:07 ivan
+
+ * FS/FS/prepay_credit.pm: document 'seconds'
+
+2002-02-18 02:14 ivan
+
+ * httemplate/edit/svc_www.cgi: oops!
+
+2002-02-18 00:53 ivan
+
+ * Makefile: make release and make update-webdemo targets
+
+2002-02-18 00:39 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_bill_event.pm, FS/FS/part_pkg.pm,
+ htetc/global.asa, httemplate/edit/part_pkg.cgi: safe web demo
+ operation! closes: Bug#217
+
+ fix bug in edit/part_pkg: s/bkg/pkg/
+
+ edit/part_pkg.cgi - plan <SELECT> is now properly stick on
+ errors, closes: Bug#323
+
+2002-02-17 19:45 ivan
+
+ * httemplate/edit/part_svc.cgi: fix modified <SELECT>s under
+ netcape4, use one for svc_acct.popnum too
+
+2002-02-17 17:26 ivan
+
+ * README.1.4.0pre11, httemplate/docs/install.html,
+ httemplate/docs/upgrade8.html: rsync docs
+
+2002-02-17 16:21 jeff
+
+ * Makefile: keep accidentally checking in Makefile changes, gotta
+ do something about that...
+
+2002-02-17 16:13 jeff
+
+ * Makefile, FS/FS/Conf.pm, bin/svc_acct.export, eg/vpopmailrestart:
+ trading in tar for rsync for improved vpopmail support
+
+2002-02-17 13:01 ivan
+
+ * FS/MANIFEST: removing CGIwrapper.pm
+
+2002-02-17 11:12 ivan
+
+ * README.1.4.0pre9, FS/MANIFEST, FS/FS/CGIwrapper.pm,
+ FS/t/CGIwrapper.t: get ride of CGIwrapper.pm
+
+2002-02-17 11:07 jeff
+
+ * FS/FS/svc_forward.pm: queue svc_forward remote commands; better
+ commands too
+
+2002-02-16 13:47 ivan
+
+ * htetc/global.asa: work with current Apache::ASP
+
+2002-02-16 10:14 ivan
+
+ * TODO: now in RT2!
+
+2002-02-15 23:27 ivan
+
+ * httemplate/docs/install.html: install warnings about mysql
+
+2002-02-15 12:21 jeff
+
+ * bin/svc_acct.export: remove arbitary uid requirement for vpasswd
+ generation
+
+2002-02-15 11:34 ivan
+
+ * Makefile: keep accidentally checking in Makefile changes, gotta
+ do something about that...
+
+2002-02-15 11:33 ivan
+
+ * Makefile, FS/FS/Conf.pm, FS/FS/svc_acct.pm: CP provisioning!!
+
+2002-02-14 14:37 jeff
+
+ * bin/svc_acct.export: fix bug in multiline radiusprepend
+
+2002-02-14 10:06 ivan
+
+ * bin/: fs-radius-add-check, fs-radius-add-reply: docs? haha
+
+2002-02-13 17:12 ivan
+
+ * FS/FS/cust_pay_batch.pm: don't require state (i18n)
+
+2002-02-12 10:56 ivan
+
+ * FS/FS/cust_bill.pm: more information in "cant send invoice email"
+ error message
+
+2002-02-12 10:47 ivan
+
+ * FS/FS/cust_main.pm: fixes:
+
+ Error running invoice event ($cust_main->charge( 10.00, 'Overdue
+ Bill' );): Illegal or empty (text) comment: at
+ /usr/local/lib/perl5/site_perl/5.005/FS/cust_main.pm line 1141.
+
+2002-02-12 10:37 ivan
+
+ * bin/svc_acct.export: fixes:
+
+ In string, @domain now must be written as \@domain at
+ ./svc_acct.export line 292, near "^append @domain" Global symbol
+ "@domain" requires explicit package name at ./svc_acct.export
+ line 292. Execution of ./svc_acct.export aborted due to
+ compilation errors.
+
+2002-02-11 21:58 ivan
+
+ * README.1.4.0pre9, bin/fs-setup, httemplate/docs/admin.html:
+ fixes: bug#331
+
+2002-02-11 20:49 ivan
+
+ * httemplate/edit/part_bill_event.cgi: oops
+
+2002-02-11 19:29 ivan
+
+ * README.1.4.0pre8, README.1.4.0pre9: 1.4.0pre9!!!
+
+2002-02-11 18:11 ivan
+
+ * FS/FS/Conf.pm, bin/svc_acct.export, httemplate/config/config.cgi:
+ add username_policy "@append domain"
+
+ add "select" config type, mmm
+
+2002-02-11 18:06 ivan
+
+ * FS/FS/svc_acct.pm: that's not a bug anymore, don't list it in the
+ BUGS section
+
+2002-02-11 17:25 ivan
+
+ * httemplate/edit/part_svc.cgi: red warning for unknown type :)
+
+2002-02-11 17:13 ivan
+
+ * httemplate/edit/part_svc.cgi: service definition domsvc is now a
+ domain pulldown closes: Bug#328
+
+2002-02-11 15:01 ivan
+
+ * FS/FS/svc_forward.pm: oops, code hidden by pod
+
+2002-02-11 14:57 ivan
+
+ * fs_signup/FS-SignupClient/SignupClient.pm: remove bad doc link
+
+2002-02-11 13:51 ivan
+
+ * httemplate/edit/svc_acct.cgi: don't display useless finger and
+ shell fields if uid is set to fixed & blank in the service
+ definition - causes: Error: Can't have finger-name without uid
+
+2002-02-11 11:38 ivan
+
+ * FS/FS/Conf.pm, FS/FS/svc_www.pm, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/process/svc_www.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_www.cgi:
+ svc_www is working!
+
+ also auto-create and add A records if necessary using apacheip
+ config file.
+
+ and show all domain_records on view/svc_domain.cgi page
+
+2002-02-10 14:31 ivan
+
+ * httemplate/edit/svc_acct.cgi: ui
+
+2002-02-10 14:21 ivan
+
+ * httemplate/edit/part_pkg.cgi: slighly different wording
+
+2002-02-10 14:06 ivan
+
+ * FS/FS/cust_svc.pm: another bug in quantity checking
+
+2002-02-10 13:37 ivan
+
+ * FS/FS/cust_svc.pm: import qsearch() so the quantity checking
+ works
+
+2002-02-10 13:30 ivan
+
+ * FS/FS/Conf.pm, FS/FS/part_pkg.pm, conf/agent_defaultpkg: add new
+ package definitions to all agent types by default
+
+ config option to restore current behaviour (must explicitly add
+ new package definitions to each agent type)
+
+ closes: Bug#324
+
+2002-02-10 11:58 ivan
+
+ * FS/MANIFEST, FS/bin/freeside-bill, FS/bin/freeside-daily,
+ httemplate/docs/billing.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/process/part_bill_event.cgi: update billing
+ documentation for the new world of invoice events added
+ freeside-daily replacing freeside-bill for the new world of
+ invoice events
+
+2002-02-10 10:56 ivan
+
+ * README.1.4.0pre9, FS/FS/cust_pay.pm, bin/fs-setup,
+ httemplate/docs/upgrade8.html, httemplate/edit/cust_pay.cgi: use
+ unique tokens to prevent double-submission of payments in the web
+ UI (closes: Bug#320)
+
+2002-02-10 09:30 ivan
+
+ * httemplate/search/cust_main.cgi: eliminate duplicate cusomters
+ before figuring to display a list or redirect. eliiminates "2
+ matching found" displayed but only one in list.
+
+2002-02-10 09:02 ivan
+
+ * FS/FS/cust_main_invoice.pm: allow + in email addresses
+
+2002-02-10 08:49 ivan
+
+ * FS/FS/cust_main_invoice.pm: okay, for now, don't try to transform
+ email addresses into svcnum-linked destinations
+
+2002-02-10 08:40 ivan
+
+ * Makefile, httemplate/edit/svc_acct.cgi:
+ fix "no previous account to recall hidden password from" error
+ when adding new accounts & get an error on first try
+
+2002-02-10 08:14 ivan
+
+ * Makefile, httemplate/index.html,
+ httemplate/browse/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_pop.cgi: s/POP/Access Number/ in the
+ webui
+
+2002-02-10 08:05 ivan
+
+ * htetc/handler.pl, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/cust_pay_batch.cgi, httemplate/browse/nas.cgi,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/browse/queue.cgi,
+ httemplate/browse/svc_acct_pop.cgi,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ httemplate/edit/REAL_cust_pkg.cgi, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_type.cgi,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/part_referral.cgi,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/misc/bill.cgi, httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/catchall.cgi,
+ httemplate/misc/delete-customer.cgi, httemplate/misc/link.cgi,
+ httemplate/misc/process/link.cgi,
+ httemplate/search/cust_bill.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pay.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_domain.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_forward.cgi,
+ httemplate/view/svc_www.cgi: *finally* seems to be working under
+ Mason. sheesh. *finally* seems to be working under Mason.
+ sheesh. *finally* seems to be working under Mason. sheesh.
+ *finally* seems to be working under Mason. sheesh. *finally*
+ seems to be working under Mason. sheesh. *finally* seems to be
+ working under Mason. sheesh. *finally* seems to be working
+ under Mason. sheesh. *finally* seems to be working under Mason.
+ sheesh.
+
+2002-02-10 05:21 ivan
+
+ * htetc/handler.pl, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/cust_pay_batch.cgi, httemplate/browse/nas.cgi,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/browse/queue.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_type.cgi,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/part_referral.cgi,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/edit/process/agent.cgi,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/cust_main_county-collapse.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/part_referral.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/svc_acct_sm.cgi,
+ httemplate/edit/process/svc_domain.cgi,
+ httemplate/edit/process/svc_forward.cgi,
+ httemplate/misc/bill.cgi, httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/cancel_pkg.cgi, httemplate/misc/catchall.cgi,
+ httemplate/misc/delete-cust_pay.cgi,
+ httemplate/misc/delete-customer.cgi,
+ httemplate/misc/expire_pkg.cgi, httemplate/misc/link.cgi,
+ httemplate/misc/print-invoice.cgi, httemplate/misc/susp_pkg.cgi,
+ httemplate/misc/unsusp_pkg.cgi,
+ httemplate/misc/process/catchall.cgi,
+ httemplate/misc/process/delete-customer.cgi,
+ httemplate/misc/process/link.cgi,
+ httemplate/search/cust_bill.cgi, httemplate/search/cust_pay.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_domain.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_forward.cgi,
+ httemplate/view/svc_www.cgi: removed <!-- $Id$ --> from all files
+ to fix any redirects, whew
+
+ Mason handler.pl overrides CGI::redirect
+
+ fixed strict; problems in edit/part_pkg.cgi &
+ edit/process/part_pkg.cgi
+
+2002-02-09 18:28 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi,
+ httemplate/view/cust_main.cgi: hide SS# unless you turn it on via
+ config file
+
+2002-02-09 18:16 ivan
+
+ * Makefile, FS/FS/Conf.pm, FS/FS/cust_bill.pm,
+ FS/FS/cust_bill_event.pm, FS/FS/cust_main.pm, htetc/handler.pl,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_bill_event.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/view/cust_bill.cgi: pro-rating w/ web interface,
+ tested (closes: Bug#313).
+
+ view/cust_bill.cgi invoice view shows invoice events!
+
+ fix bug where adding events with no name silently failed instead
+ of giving an error
+
+ add new comission plans
+
+2002-02-09 17:47 ivan
+
+ * README.1.4.0pre8, httemplate/docs/upgrade8.html,
+ FS/bin/freeside-bill: remove -i option from freeside-bill
+ (obsoleted by invoice events)
+
+2002-02-09 10:24 ivan
+
+ * FS/FS/CGI.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/search/cust_main.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/search/svc_domain.cgi: no more exit() in templates
+
+2002-02-09 10:09 ivan
+
+ * FS/FS/svc_domain.pm: okay all external export from .pm files is
+ queued! (closes: Bug#249)
+
+2002-02-09 09:45 ivan
+
+ * FS/FS/cust_svc.pm, httemplate/misc/process/link.cgi: have
+ FS::cust_svc::check look up & check pkg_svc.quantity like
+ httemplate/view/cust_pkg.cgi (closes: Bug#43)
+
+2002-02-09 09:03 ivan
+
+ * FS/FS/CGI.pm, htetc/global.asa, htetc/handler.pl: okay, both
+ Apache::ASP and Mason should set no-cache headers now (closes:
+ Bug#23)
+
+2002-02-07 14:30 ivan
+
+ * Makefile: oops, reversing bad Makefile patch
+
+2002-02-07 14:29 ivan
+
+ * Makefile, FS/FS/Conf.pm, FS/FS/cust_bill_pay.pm,
+ FS/FS/cust_pay.pm, httemplate/browse/agent_type.cgi,
+ httemplate/browse/nas.cgi, httemplate/misc/delete-cust_pay.cgi,
+ httemplate/view/cust_main.cgi: delete payments
+
+2002-02-06 07:55 ivan
+
+ * FS/FS/cust_main.pm, bin/pod2x: doc updates and pod2x fix to skip
+ blib/ files
+
+2002-02-06 07:50 ivan
+
+ * FS/FS/cust_bill.pm: pod typo
+
+2002-02-06 07:49 ivan
+
+ * Makefile, httemplate/docs/install.html: documentation building
+ Makefile patch
+
+2002-02-06 07:36 ivan
+
+ * FS/FS/part_bill_event.pm: part_bill_event.plan can contain
+ punctuation
+
+2002-02-06 07:07 ivan
+
+ * bin/fs-setup: tyop
+
+2002-02-06 06:58 ivan
+
+ * FS/bin/freeside-adduser: fix for non-file auth
+
+2002-02-05 12:25 ivan
+
+ * FS/FS/Record.pm: better error messages if you haven't run
+ fs-setup ?
+
+2002-02-05 10:24 ivan
+
+ * httemplate/docs/install.html: &nbsp; for commands; confusing
+ otherwise
+
+2002-02-05 10:04 ivan
+
+ * httemplate/docs/install.html: doc
+
+2002-02-05 08:48 ivan
+
+ * fs_passwd/fs_passwd, fs_passwd/fs_passwd.cgi,
+ fs_passwd/fs_passwd.html, httemplate/docs/passwd.html: web-based
+ password changer!
+
+2002-02-05 03:06 ivan
+
+ * httemplate/docs/upgrade8.html: don't need DBIx::DataSource for
+ upgrades
+
+2002-02-05 01:46 ivan
+
+ * httemplate/docs/: install.html, upgrade8.html: doc
+
+2002-02-04 23:57 ivan
+
+ * README.1.4.0pre8, httemplate/docs/upgrade8.html: fix
+ part_export_option indices
+
+2002-02-04 10:12 ivan
+
+ * httemplate/docs/install.html: doc update
+
+2002-02-04 09:12 ivan
+
+ * httemplate/docs/man/FS/: Bill.html, Invoice.html: ancient files
+
+2002-02-04 09:06 ivan
+
+ * Makefile, README.1.4.0pre4567-8, README.1.4.0pre8: 1.4.0pre8!
+
+2002-02-04 09:04 ivan
+
+ * bin/fs-setup, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_bill_event.cgi: have fs-setup create the
+ necessary "default" billing events documentation on necessary
+ "default" billing events
+
+2002-02-04 08:44 ivan
+
+ * httemplate/docs/install.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/view/cust_bill.cgi, FS/FS/cust_bill.pm,
+ FS/FS/cust_main.pm: billing events!
+
+2002-01-30 10:22 ivan
+
+ * httemplate/: browse/part_bill_event.cgi,
+ edit/part_bill_event.cgi, edit/process/part_bill_event.cgi: fully
+ working invoice event web interface
+
+2002-01-30 06:18 ivan
+
+ * FS/FS/CGI.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/browse/agent.cgi, httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/cust_pay_batch.cgi, httemplate/browse/nas.cgi,
+ httemplate/browse/part_bill_event.cgi,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/browse/queue.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/docs/install.html,
+ httemplate/edit/agent.cgi, httemplate/edit/agent_type.cgi,
+ httemplate/edit/cust_bill_pay.cgi,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_referral.cgi, httemplate/edit/part_svc.cgi,
+ httemplate/edit/svc_acct.cgi, httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi,
+ httemplate/edit/process/agent.cgi,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/cust_bill_pay.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/cust_main_county-collapse.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/part_referral.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/svc_acct_sm.cgi,
+ httemplate/edit/process/svc_domain.cgi,
+ httemplate/edit/process/svc_forward.cgi,
+ httemplate/misc/bill.cgi, httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/cancel_pkg.cgi, httemplate/misc/catchall.cgi,
+ httemplate/misc/delete-customer.cgi,
+ httemplate/misc/expire_pkg.cgi, httemplate/misc/link.cgi,
+ httemplate/misc/print-invoice.cgi, httemplate/misc/susp_pkg.cgi,
+ httemplate/misc/unsusp_pkg.cgi,
+ httemplate/misc/process/catchall.cgi,
+ httemplate/misc/process/delete-customer.cgi,
+ httemplate/misc/process/link.cgi,
+ httemplate/search/cust_bill.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pay.cgi, httemplate/search/cust_pkg.cgi,
+ httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_domain.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_forward.cgi,
+ httemplate/view/svc_www.cgi: remove use Module; and $cgi =
+ new CGI; &cgisuidsetup(); from all templates. should work
+ better under Mason.
+
+2002-01-29 09:46 ivan
+
+ * httemplate/docs/man/: FS.html, FS/CGI.html, FS/CGIwrapper.html,
+ FS/Conf.html, FS/Record.html, FS/SessionClient.html,
+ FS/SignupClient.html, FS/UID.html, FS/agent.html,
+ FS/agent_type.html, FS/cust_bill.html, FS/cust_bill_pkg.html,
+ FS/cust_credit.html, FS/cust_main.html, FS/cust_main_county.html,
+ FS/cust_main_invoice.html, FS/cust_pay.html,
+ FS/cust_pay_batch.html, FS/cust_pkg.html, FS/cust_refund.html,
+ FS/cust_svc.html, FS/domain_record.html, FS/nas.html,
+ FS/part_pkg.html, FS/part_referral.html, FS/part_svc.html,
+ FS/pkg_svc.html, FS/port.html, FS/prepay_credit.html,
+ FS/session.html, FS/svc_Common.html, FS/svc_acct.html,
+ FS/svc_acct_pop.html, FS/svc_acct_sm.html, FS/svc_domain.html,
+ FS/svc_www.html, FS/type_pkgs.html, FS/UI/Base.html,
+ FS/UI/CGI.html, FS/UI/Gtk.html, FS/UI/agent.html: these are all
+ auto-generated by the installation; don't check them into CVS
+ (probably should generate them for a release tarball though)
+
+2002-01-29 09:42 ivan
+
+ * README.1.4.0pre4567-8, FS/FS/part_bill_event.pm, bin/fs-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html,
+ httemplate/docs/man/FS/SessionClient.html,
+ httemplate/docs/man/FS/UID.html,
+ httemplate/docs/man/FS/agent.html,
+ httemplate/docs/man/FS/agent_type.html,
+ httemplate/docs/man/FS/cust_bill.html,
+ httemplate/docs/man/FS/cust_bill_pkg.html,
+ httemplate/docs/man/FS/cust_credit.html,
+ httemplate/docs/man/FS/cust_main.html,
+ httemplate/docs/man/FS/cust_main_county.html,
+ httemplate/docs/man/FS/cust_main_invoice.html,
+ httemplate/docs/man/FS/cust_pay.html,
+ httemplate/docs/man/FS/cust_pay_batch.html,
+ httemplate/docs/man/FS/cust_pkg.html,
+ httemplate/docs/man/FS/cust_refund.html,
+ httemplate/docs/man/FS/cust_svc.html,
+ httemplate/docs/man/FS/domain_record.html,
+ httemplate/docs/man/FS/nas.html,
+ httemplate/docs/man/FS/part_pkg.html,
+ httemplate/docs/man/FS/part_referral.html,
+ httemplate/docs/man/FS/part_svc.html,
+ httemplate/docs/man/FS/pkg_svc.html,
+ httemplate/docs/man/FS/port.html,
+ httemplate/docs/man/FS/prepay_credit.html,
+ httemplate/docs/man/FS/session.html,
+ httemplate/docs/man/FS/svc_Common.html,
+ httemplate/docs/man/FS/svc_acct.html,
+ httemplate/docs/man/FS/svc_acct_pop.html,
+ httemplate/docs/man/FS/svc_acct_sm.html,
+ httemplate/docs/man/FS/svc_domain.html,
+ httemplate/docs/man/FS/svc_www.html,
+ httemplate/docs/man/FS/type_pkgs.html,
+ httemplate/docs/man/FS/UI/Base.html,
+ httemplate/docs/man/FS/UI/CGI.html,
+ httemplate/docs/man/FS/UI/Gtk.html: weight, plan and plandata
+ fields in part_bill_event
+
+2002-01-29 08:33 ivan
+
+ * Makefile, FS/FS.pm, FS/FS/Record.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm,
+ FS/FS/svc_acct.pm, bin/pod2x, htetc/global.asa, htetc/handler.pl,
+ httemplate/index.html, httemplate/browse/part_bill_event.cgi,
+ httemplate/docs/install.html, httemplate/docs/man/FS.html,
+ httemplate/docs/man/FS/CGI.html,
+ httemplate/docs/man/FS/Conf.html,
+ httemplate/docs/man/FS/Record.html,
+ httemplate/docs/man/FS/SessionClient.html,
+ httemplate/docs/man/FS/SignupClient.html,
+ httemplate/docs/man/FS/UID.html,
+ httemplate/docs/man/FS/agent.html,
+ httemplate/docs/man/FS/agent_type.html,
+ httemplate/docs/man/FS/cust_bill.html,
+ httemplate/docs/man/FS/cust_bill_pkg.html,
+ httemplate/docs/man/FS/cust_credit.html,
+ httemplate/docs/man/FS/cust_main.html,
+ httemplate/docs/man/FS/cust_main_county.html,
+ httemplate/docs/man/FS/cust_main_invoice.html,
+ httemplate/docs/man/FS/cust_pay.html,
+ httemplate/docs/man/FS/cust_pay_batch.html,
+ httemplate/docs/man/FS/cust_pkg.html,
+ httemplate/docs/man/FS/cust_refund.html,
+ httemplate/docs/man/FS/cust_svc.html,
+ httemplate/docs/man/FS/domain_record.html,
+ httemplate/docs/man/FS/nas.html,
+ httemplate/docs/man/FS/part_pkg.html,
+ httemplate/docs/man/FS/part_referral.html,
+ httemplate/docs/man/FS/part_svc.html,
+ httemplate/docs/man/FS/pkg_svc.html,
+ httemplate/docs/man/FS/port.html,
+ httemplate/docs/man/FS/prepay_credit.html,
+ httemplate/docs/man/FS/session.html,
+ httemplate/docs/man/FS/svc_Common.html,
+ httemplate/docs/man/FS/svc_acct.html,
+ httemplate/docs/man/FS/svc_acct_pop.html,
+ httemplate/docs/man/FS/svc_acct_sm.html,
+ httemplate/docs/man/FS/svc_domain.html,
+ httemplate/docs/man/FS/svc_www.html,
+ httemplate/docs/man/FS/type_pkgs.html,
+ httemplate/docs/man/FS/UI/Base.html,
+ httemplate/docs/man/FS/UI/CGI.html,
+ httemplate/docs/man/FS/UI/Gtk.html,
+ httemplate/edit/part_bill_event.cgi,
+ httemplate/edit/part_pkg.cgi,
+ httemplate/edit/process/part_bill_event.cgi: - web interface for
+ hourly account charges! (FS::cust_pkg, FS::cust_svc and
+ FS::svc_acct seconds_since methods) - Makefile target to
+ regenerate HTML manpages on install - FS.pm doc update -
+ $FS::Record::Debug now dumps all SQL - new FS::cust_main methods:
+ ->cancel, ->invoicing_list_addpost - start of a billing event web
+ interface - cust_pay::upgrade_replace doesn't error out if
+ history includes overapplied payments
+
+2002-01-29 03:11 ivan
+
+ * bin/fs-setup: oops bad column type for part_bill_event.payby
+
+2002-01-28 03:24 ivan
+
+ * FS/FS/Record.pm: oops, syntax error in new() check for missing
+ subclass table sub (eek)
+
+2002-01-27 22:57 ivan
+
+ * README.1.4.0pre4567-8, FS/FS/cust_bill.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_refund.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_svc.pm, bin/fs-setup, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html: book closing schema changes
+
+2002-01-27 21:15 ivan
+
+ * README.1.4.0pre4567-8, FS/FS/part_export.pm,
+ FS/FS/part_export_option.pm, bin/fs-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html:
+ part_export schema changes
+
+2002-01-25 17:52 ivan
+
+ * FS/FS/cust_credit_refund.pm: another bug spotted by jeff
+
+2002-01-24 09:02 ivan
+
+ * FS/FS/Record.pm: emit a warning in this unlikely case again
+
+2002-01-24 08:58 ivan
+
+ * FS/FS/: cust_bill_pay.pm, cust_credit.pm, cust_credit_bill.pm,
+ cust_credit_refund.pm, cust_pay.pm, cust_refund.pm: <rluser>
+ rather than == 0 in the ::check's .... <rluser> you might
+ consider <= 0
+
+2002-01-24 08:54 ivan
+
+ * FS/FS/cust_credit_refund.pm: stack traces help alot
+
+2002-01-24 03:52 ivan
+
+ * FS/FS/: cust_credit_refund.pm, cust_pay.pm, cust_refund.pm:
+ jeff's on a bugfinding roll here, thanks!
+
+2002-01-24 03:43 ivan
+
+ * FS/FS/cust_credit_refund.pm: <rluser> and it seems that
+ cust_credit_refund::cust_credit should exist..
+
+2002-01-23 22:52 ivan
+
+ * FS/FS/cust_refund.pm: from jeff@fix <rluser> in
+ FS::cust_refund::check 'amount' should probably be replaced with
+ +'refund' in two places
+
+2002-01-23 22:46 ivan
+
+ * FS/FS/cust_refund.pm: more updates to cust_refund::update_replace
+
+2002-01-23 18:26 ivan
+
+ * FS/FS/cust_refund.pm: fix cust_refund::insert
+
+2002-01-22 07:57 ivan
+
+ * FS/FS/: cust_credit.pm, cust_pay.pm, cust_refund.pm: don't allow
+ $0.00 in credits/payments/refunds
+
+2002-01-22 06:55 ivan
+
+ * FS/FS/part_svc.pm: docu
+
+2002-01-22 06:53 ivan
+
+ * FS/FS/svc_acct.pm: silly compilation problem
+
+2002-01-22 06:42 ivan
+
+ * httemplate/docs/: index.html, upgrade.html, upgrade2.html,
+ upgrade3.html: remove old upgrade docs
+
+2002-01-21 03:30 ivan
+
+ * FS/FS/cust_pkg.pm: include FS::svc_forward in kludgy preload
+
+2002-01-19 07:16 ivan
+
+ * FS/FS/UID.pm: error message update
+
+2002-01-16 07:37 ivan
+
+ * FS/FS/svc_acct.pm: doc
+
+2002-01-14 12:28 ivan
+
+ * FS/FS/Conf.pm, FS/FS/svc_acct.pm, httemplate/docs/export.html:
+ pay some attention to 1.4 RADIUS SQL export
+
+2002-01-14 06:29 ivan
+
+ * FS/bin/freeside-overdue: fix -l option
+
+2002-01-11 23:23 ivan
+
+ * httemplate/docs/upgrade8.html: fix upgrade8.html to be in
+ agreement with fs-setup
+
+2002-01-09 05:29 ivan
+
+ * FS/FS/cust_main.pm, httemplate/search/cust_main.cgi: update fuzzy
+ cache files on customer replace.
+
+ do an exact search along with the fuzzy search (webui)
+
+2002-01-03 09:40 ivan
+
+ * README.1.4.0pre2-3, README.1.4.0pre3-4, README.1.4.0pre4567-8,
+ FS/MANIFEST, FS/FS/cust_bill_event.pm, FS/FS/part_bill_event.pm,
+ FS/t/cust_bill_event.t, FS/t/part_bill_event.t, bin/fs-setup,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html: more
+ schema changes: part_bill_event and cust_bill_event tables
+
+ remove old 1.4.0pre READMEs
+
+2001-12-28 07:17 ivan
+
+ * FS/bin/freeside-overdue: update usage message
+
+2001-12-28 07:14 ivan
+
+ * FS/: FS/cust_main.pm, bin/freeside-overdue: force printing in
+ freeside-overdue
+
+2001-12-28 06:40 ivan
+
+ * FS/FS/cust_main.pm, FS/bin/freeside-bill,
+ FS/bin/freeside-overdue, httemplate/edit/cust_main.cgi,
+ httemplate/edit/part_pkg.cgi: add more options to
+ freeside-overdue
+
+ add charge method to FS::cust_main
+
+ one-off packages default to disabled
+
+ billing payname defaults to first and last, not "Accounts
+ Payable"
+
+2001-12-27 01:26 ivan
+
+ * README.1.4.0pre4567-8, FS/FS/Record.pm, FS/FS/part_pkg.pm,
+ FS/FS/part_svc.pm, FS/bin/freeside-overdue, bin/fs-setup,
+ fs_signup/fs_signup_server, htetc/global.asa,
+ httemplate/browse/part_pkg.cgi, httemplate/browse/part_svc.cgi,
+ httemplate/edit/agent_type.cgi, httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_pkg.cgi, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/view/cust_main.cgi: service and package disable!
+
+2001-12-26 15:59 ivan
+
+ * httemplate/docs/: install.html, schema.html, upgrade8.html: doc
+
+2001-12-26 07:41 ivan
+
+ * httemplate/view/cust_main.cgi: remove warnings
+
+2001-12-26 07:11 ivan
+
+ * httemplate/edit/process/cust_credit.cgi: apply credits!!
+
+2001-12-26 07:08 ivan
+
+ * FS/: MANIFEST, bin/freeside-overdue: add freeside-overdue
+
+2001-12-26 07:07 ivan
+
+ * httemplate/edit/: cust_credit.cgi, process/cust_credit.cgi: fix
+ posting credit
+
+2001-12-26 03:47 ivan
+
+ * FS/bin/freeside-overdue: don't provide example crontabs that run
+ at 4:20 _PM_
+
+2001-12-26 03:17 ivan
+
+ * FS/FS/cust_main.pm, FS/bin/freeside-overdue,
+ httemplate/docs/billing.html: (untested eek) freeside-overdue
+ script & cust_main balance_date & total_owed_date methods
+
+2001-12-26 01:18 ivan
+
+ * httemplate/: index.html, search/cust_pay.cgi,
+ search/cust_pay.html, view/cust_main.cgi: search by check #
+
+2001-12-25 23:53 ivan
+
+ * FS/FS/cust_pay.pm: doc
+
+2001-12-25 22:02 ivan
+
+ * httemplate/edit/cust_pay.cgi: UI
+
+2001-12-25 21:19 ivan
+
+ * httemplate/: index.html, edit/cust_pay.cgi,
+ edit/process/cust_pay.cgi, search/cust_main-payinfo.html,
+ search/cust_main-quickpay.html, search/cust_main.cgi,
+ search/cust_main.html: expedited check entry
+
+2001-12-25 21:02 ivan
+
+ * CREDITS: still missing tons of folks, i am sure
+
+2001-12-25 20:52 ivan
+
+ * httemplate/search/: cust_bill.html, svc_acct.html,
+ svc_domain.html, cust_main.html: same look as rest of search
+ pages
+
+2001-12-25 20:25 ivan
+
+ * FS/FS/CGI.pm, httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_pay.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_pay.cgi: auto-apply payments and
+ credits, post credit UI overhaul
+
+2001-12-25 18:33 ivan
+
+ * httemplate/edit/cust_pay.cgi: fix service display for duplicates
+
+2001-12-21 18:41 ivan
+
+ * httemplate/docs/install.html: doco on creating database manually
+
+2001-12-21 13:40 ivan
+
+ * FS/FS/cust_bill.pm, httemplate/edit/cust_pay.cgi,
+ httemplate/view/cust_main.cgi: add name/address to post payment
+ screen
+
+ get rid of some $-0.00 yay for ieee fp
+
+2001-12-21 12:55 ivan
+
+ * FS/FS/cust_bill_pay.pm: fixes
+
+ total cust_bill_pay.amount and cust_credit_bill.amount 19.95
+ for invnum 1659
+ greater than cust_bill.charged 19.95 at
+ /usr/local/lib/perl5/site_perl/5.005/FS/cust_main.pm line 1519.
+
+2001-12-19 21:34 ivan
+
+ * FS/FS/Record.pm: work better with DBIx::Profile
+
+2001-12-19 18:09 ivan
+
+ * FS/FS/svc_acct.pm: don't error trying to suspend accounts with
+ '*' password
+
+2001-12-19 18:07 ivan
+
+ * FS/FS/svc_acct.pm: quiet warnings
+
+2001-12-19 06:33 ivan
+
+ * FS/FS/svc_acct.pm: alas, a 5.6-ism
+
+2001-12-19 06:30 ivan
+
+ * FS/FS/svc_acct.pm: surpress warnings
+
+2001-12-18 11:36 ivan
+
+ * httemplate/edit/cust_bill_pay.cgi: another dum tyop
+
+2001-12-18 11:34 ivan
+
+ * httemplate/edit/cust_bill_pay.cgi: typo
+
+2001-12-18 11:32 ivan
+
+ * httemplate/edit/cust_bill_pay.cgi: declar vars
+
+2001-12-18 11:30 ivan
+
+ * httemplate/edit/: cust_bill_pay.cgi, cust_credit_bill.cgi,
+ process/cust_bill_pay.cgi, process/cust_credit_bill.cgi: apply
+ payment webinterface
+
+2001-12-17 23:12 ivan
+
+ * httemplate/search/cust_pkg.cgi: really working dates on package
+ browse. ouch.
+
+2001-12-17 23:08 ivan
+
+ * httemplate/search/cust_pkg.cgi: working dates on package browse
+
+2001-12-17 22:45 ivan
+
+ * httemplate/search/cust_pkg.cgi: oops. *sigh*
+
+2001-12-17 22:38 ivan
+
+ * httemplate/search/cust_pkg.cgi: show dates on package browse
+
+2001-12-17 22:29 ivan
+
+ * FS/FS/svc_acct_pop.pm: full number in POP pulldown
+
+2001-12-17 17:49 ivan
+
+ * FS/: MANIFEST, FS/svc_acct.pm: add freeside-setinvoice to
+ MANIFEST
+
+ fix warning:
+
+ FS::cust_main_invoice=HASH(0x90c86c4) at
+ /usr/local/lib/perl5/site_perl/5.005/FS/svc_acct.pm line 419.
+
+2001-12-17 15:59 ivan
+
+ * FS/FS/cust_bill.pm: fixes
+
+ Argument "" isn't numeric in ncmp at
+ /usr/local/lib/perl5/site_perl/5.005/FS/cust_bill.pm line 254.
+
+2001-12-16 15:50 ivan
+
+ * FS/FS/cust_main.pm: eek nasty bug
+
+2001-12-15 16:55 ivan
+
+ * FS/FS/cust_bill_pay.pm: fix weird rounding error: total
+ cust_bill_pay.amount 39.9 for paynum 240 greater than
+ cust_pay.paid 39.90
+
+2001-12-15 14:59 ivan
+
+ * httemplate/view/svc_acct.cgi: style
+
+2001-12-15 14:58 ivan
+
+ * FS/FS/cust_svc.pm: meaningful FS::cust_svc::label for svc_www
+ records
+
+2001-12-15 14:56 ivan
+
+ * httemplate/view/svc_www.cgi: view svc_www.cgi from Dave Burgess
+ <burgess@www.cynjut.net>, thanks
+
+2001-12-15 14:47 ivan
+
+ * httemplate/edit/cust_main.cgi: allow entering of referral
+ customer by number as well as by link off the view page, courtesy
+ of Dave Burgess <burgess@www.cynjut.net>
+
+2001-12-14 16:17 ivan
+
+ * FS/FS/cust_main.pm: style changes
+
+2001-12-13 10:37 ivan
+
+ * FS/bin/freeside-setinvoice: okay, it should really work now
+
+2001-12-13 09:52 ivan
+
+ * FS/bin/freeside-setinvoice: fix setinvoice script
+
+2001-12-13 01:17 ivan
+
+ * FS/bin/freeside-setinvoice: added util to set invoice
+ destinations
+
+2001-12-12 11:42 ivan
+
+ * httemplate/edit/: cust_main.cgi, svc_acct.cgi: allow >8 character
+ passwords in web interface
+
+2001-12-11 23:59 ivan
+
+ * bin/svc_acct.export: use pwd_mkdb to install
+ /etc/master.passwd.new instead of moving it into place
+
+2001-12-11 13:26 ivan
+
+ * httemplate/search/svc_acct.cgi: missing space in SQL, oops
+
+2001-12-11 02:38 ivan
+
+ * bin/svc_acct.export, httemplate/docs/install.html: radiusprepend
+ config file for export add Archive::Tar to docs
+
+2001-12-10 04:18 ivan
+
+ * FS/FS/Record.pm: Pg datatype pain
+
+2001-12-09 20:54 ivan
+
+ * httemplate/index.html: typo noticed by Dave Burgess
+ <burgess@www.cynjut.net>, thanks.
+
+2001-12-09 16:44 ivan
+
+ * httemplate/search/svc_acct.cgi: visual glitch: oops, $pager
+ wasn't getting substitued.
+
+2001-12-09 15:31 ivan
+
+ * httemplate/search/svc_acct.cgi: harmless? missing ;
+
+2001-12-08 02:08 ivan
+
+ * httemplate/config/config.cgi: need a POST here; browsers
+ (especially IE) are unhappy with the default GET
+
+2001-12-08 02:07 ivan
+
+ * FS/FS/cust_pay.pm: get custnum from invnum before trying to use
+ custnum!
+
+2001-12-08 02:03 ivan
+
+ * FS/FS/cust_main.pm: fix logic error creating invoice line items
+
+2001-12-08 02:01 ivan
+
+ * FS/FS/Conf.pm: radiusprepend config file for DEFAULT entries etc.
+
+2001-12-04 05:10 ivan
+
+ * httemplate/edit/svc_forward.cgi: from Dave Burgess
+ <burgess@neonramp.com>:
+
+ I had to change line 104 in /edit/svc_forward.cgi and add 'my'
+ as the
+ qualifier on the LHS of the assignment. This also solves the
+ problem with a similar error on the RHS of line 105. It also
+ seems to make
+ the routine work fairly reliably (it has been problematic for me
+ in the
+ past).
+
+2001-12-03 03:33 ivan
+
+ * httemplate/search/: cust_main.cgi, cust_pkg.cgi, svc_acct.cgi:
+ paged service browse!!
+
+2001-12-03 02:59 ivan
+
+ * httemplate/search/: cust_main.cgi, cust_pkg.cgi: paged package
+ browse
+
+2001-12-03 00:43 ivan
+
+ * httemplate/search/cust_main.cgi: paged customer browse!
+
+2001-12-03 00:41 ivan
+
+ * FS/FS/Conf.pm, FS/FS/Record.pm, conf/maxsearchrecordsperpage,
+ httemplate/search/cust_main.cgi: maxsearchrecordsperpage config
+ option paged implementation of customer browse!
+
+2001-11-29 16:04 ivan
+
+ * FS/FS/: cust_pkg.pm, cust_svc.pm, svc_Common.pm: more link
+ methods
+
+2001-11-20 19:42 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi: a more reasonalbe
+ name (!)
+
+2001-11-20 19:40 ivan
+
+ * FS/FS/Conf.pm, httemplate/edit/cust_main.cgi:
+ postalinvoicedefault config file
+
+2001-11-16 02:22 ivan
+
+ * httemplate/docs/billing.html: update link to Text::Template docs
+
+2001-11-13 13:27 ivan
+
+ * FS/: MANIFEST, bin/freeside-print-batch: remove
+ freeside-print-batch
+
+2001-11-12 05:19 ivan
+
+ * FS/FS/cust_main.pm: import hack to be less strict
+
+2001-11-09 10:26 ivan
+
+ * httemplate/docs/install.html: Pg7 dependancy
+
+2001-11-08 07:26 ivan
+
+ * FS/bin/freeside-queued: harmless typo noticed by "Edward
+ Shabotinsky" <lanshark@bsinet.net>, thanks
+
+2001-11-06 10:45 ivan
+
+ * httemplate/edit/process/part_pkg.cgi: remove gratuitous warnings
+
+2001-11-06 10:35 ivan
+
+ * Makefile: i REALLY suck at Makefiles
+
+2001-11-06 10:34 ivan
+
+ * Makefile: i suck at Makefiles
+
+2001-11-06 10:22 ivan
+
+ * Makefile: make foo for htetc/global.asa
+
+2001-11-06 09:58 ivan
+
+ * FS/FS/UID.pm: fix error message for s/htdocs/httemplate/
+
+2001-11-06 09:48 ivan
+
+ * bin/fs-setup: payinfo changed from length 16 to $char_d for
+ future expansion
+
+2001-11-05 13:30 ivan
+
+ * Makefile: more fixes for fresh installation
+
+2001-11-05 13:26 ivan
+
+ * Makefile: yet more Make
+
+2001-11-05 13:24 ivan
+
+ * Makefile: make create-database fix
+
+2001-11-05 12:12 ivan
+
+ * Makefile, FS/FS/Record.pm: makefile fixups
+
+2001-11-05 10:23 ivan
+
+ * httemplate/docs/install.html: doc
+
+2001-11-05 09:00 jeff
+
+ * FS/FS/svc_acct.pm: improved svc_acct replacement
+
+2001-11-05 08:42 ivan
+
+ * FS/FS/Record.pm: AUTOLOAD optimizations broke things rather
+ badly, oops
+
+2001-11-05 06:04 ivan
+
+ * FS/bin/freeside-bill: fixup getopt
+
+2001-11-05 06:03 ivan
+
+ * Makefile: move sys-dependant stuff to vars
+
+2001-11-05 05:57 ivan
+
+ * FS/FS/svc_acct.pm: doc tyop
+
+2001-11-05 04:07 ivan
+
+ * bin/svc_domain.import: this is unfinished and untested anyway,
+ but this corrects a silly typo
+
+2001-11-05 03:55 ivan
+
+ * FS/FS/cust_main.pm: better error messages for eval'ed setup/recur
+ expressions remove debugging warn output
+
+2001-11-03 09:49 ivan
+
+ * FS/MANIFEST, FS/FS/Record.pm, FS/FS/SearchCache.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pkg.pm, FS/FS/cust_svc.pm,
+ FS/FS/svc_acct.pm, FS/t/SearchCache.t,
+ httemplate/search/cust_main.cgi: new 'jsearch' call for big
+ joined searches & caching support preliminary customer browse
+ optimizations, much faster!
+
+2001-11-02 00:14 ivan
+
+ * FS/bin/freeside-print-batch: silence pod complaints
+
+2001-11-01 21:28 ivan
+
+ * httemplate/config/config.cgi: note config changes need
+ apache/freeside-queued restart to take effect
+
+2001-11-01 21:11 ivan
+
+ * FS/FS/Record.pm: depend on DBIx::DBSchema 0.19
+
+2001-11-01 20:55 ivan
+
+ * httemplate/config/config-view.cgi, httemplate/config/config.cgi,
+ FS/FS/Conf.pm: config web GUI updates. almost usable now.
+
+2001-10-31 16:16 ivan
+
+ * httemplate/search/cust_main.cgi: hit the database slightly less.
+ this page still takes forever with lots of customers.
+
+2001-10-31 08:52 ivan
+
+ * httemplate/browse/queue.cgi: queue display works again, even if
+ those links don't
+
+2001-10-30 11:05 ivan
+
+ * FS/FS/cust_pay_batch.pm, bin/fs-setup, httemplate/index.html,
+ httemplate/browse/cust_pay_batch.cgi,
+ httemplate/docs/schema.html: depriciate cust_pay_batch.trancode
+ web interface to view pending batch
+
+2001-10-30 07:42 ivan
+
+ * httemplate/edit/cust_main.cgi: put default country up top
+
+2001-10-30 07:41 ivan
+
+ * httemplate/edit/cust_main.cgi: precedence oops
+
+2001-10-30 07:39 ivan
+
+ * httemplate/edit/cust_main.cgi: better ordering of state selection
+ on new customer screen
+
+2001-10-30 06:54 ivan
+
+ * htetc/handler.pl, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/nas.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi, httemplate/browse/queue.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_type.cgi, httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_referral.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/misc/catchall.cgi,
+ httemplate/misc/delete-customer.cgi, httemplate/misc/link.cgi,
+ httemplate/search/cust_bill.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_domain.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_forward.cgi:
+ get rid of header foo in individual templates
+
+2001-10-30 06:28 ivan
+
+ * httemplate/docs/: install.html, upgrade8.html: docu
+
+2001-10-30 06:20 ivan
+
+ * htetc/handler.pl, httemplate/config/config-view.cgi,
+ httemplate/config/config.cgi: web config should workish now
+
+2001-10-30 05:49 ivan
+
+ * Makefile: work with CVS version too
+
+2001-10-30 05:48 ivan
+
+ * Makefile: make
+
+2001-10-30 05:47 ivan
+
+ * Makefile, FS/bin/freeside-adduser, conf/address, conf/domain,
+ conf/secrets, conf/shells, conf/smtpmachine,
+ httemplate/docs/install.html: `make create-config' installs
+ default config (conf dir update) freeside-adduser uses default
+ secrets file
+
+2001-10-30 04:38 ivan
+
+ * Makefile: make
+
+2001-10-30 04:35 ivan
+
+ * Makefile, httemplate/docs/install.html: makefile typo
+
+2001-10-30 03:47 ivan
+
+ * Makefile, FS/bin/freeside-adduser, httemplate/docs/admin.html,
+ httemplate/docs/config.html, httemplate/docs/index.html,
+ httemplate/docs/install.html: whew more install docs and
+ automation
+
+2001-10-30 02:20 ivan
+
+ * Makefile, FS/MANIFEST, FS/FS/Conf.pm, FS/bin/freeside-adduser,
+ httemplate/docs/install.html: setup/config updates. getting
+ easier...
+
+2001-10-29 13:22 ivan
+
+ * Makefile: fix make clean
+
+2001-10-29 12:54 ivan
+
+ * httemplate/docs/install.html: doc typo
+
+2001-10-29 12:53 ivan
+
+ * FS/FS/svc_forward.pm: methods for getting the associated svc_acct
+ records
+
+2001-10-29 09:17 ivan
+
+ * Makefile: automate a tiny bit more
+
+2001-10-26 03:24 ivan
+
+ * FS/FS/CGI.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/browse/agent.cgi, httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/nas.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi, httemplate/browse/queue.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_type.cgi, httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_referral.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/misc/catchall.cgi,
+ httemplate/misc/delete-customer.cgi, httemplate/misc/link.cgi,
+ httemplate/search/cust_bill.cgi, httemplate/search/cust_main.cgi,
+ httemplate/search/cust_pkg.cgi, httemplate/search/svc_acct.cgi,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_domain.cgi, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi, httemplate/view/svc_forward.cgi:
+ cache foo *sigh*
+
+2001-10-26 02:50 ivan
+
+ * httemplate/config/config-process.cgi: otherwise people will have
+ problems with `0' zero
+
+2001-10-25 14:24 ivan
+
+ * httemplate/edit/svc_domain.cgi: remove ancient tld cruft
+
+2001-10-25 09:13 ivan
+
+ * FS/FS/cust_main_invoice.pm: & in email addresses
+
+2001-10-25 01:41 ivan
+
+ * FS/FS/Conf.pm: remove debugging cruft
+
+2001-10-24 08:45 ivan
+
+ * httemplate/config/config-process.cgi: correct for browser
+ munching
+
+2001-10-24 08:29 ivan
+
+ * FS/FS.pm, FS/MANIFEST, FS/FS/Conf.pm, FS/FS/ConfItem.pm,
+ FS/FS/svc_acct.pm, FS/FS/svc_domain.pm, FS/t/ConfItem.t,
+ bin/fs-setup, bin/svc_acct.export, conf/registries/internic/from,
+ conf/registries/internic/nameservers,
+ conf/registries/internic/tech_contact,
+ conf/registries/internic/template, conf/registries/internic/to,
+ fs_webdemo/registerd.Pg, httemplate/index.html,
+ httemplate/config/config-process.cgi,
+ httemplate/config/config-view.cgi, httemplate/docs/config.html,
+ httemplate/docs/install.html, httemplate/search/svc_acct.cgi:
+ preliminary web config editor
+
+ new config files: username-ampersand, passwordmax
+
+ fs-setup updates
+
+ get rid of old and crufty and unused registries/ config foo
+
+ documentation updates
+
+2001-10-23 17:59 ivan
+
+ * httemplate/browse/queue.cgi: Can't find string terminator "!"
+ anywhere before EOF at queue.cgi line 42
+
+2001-10-23 13:53 ivan
+
+ * FS/bin/freeside-queued: Pg: FOR UPDATE LIMIT 1 mysql: LIMIT 1 FOR
+ UPDATE
+
+ greeeat.
+
+2001-10-23 11:57 ivan
+
+ * httemplate/docs/: config.html, install.html: document how to set
+ MySQL with BDB default tables
+
+2001-10-23 11:15 ivan
+
+ * bin/fs-setup: mysql fixes
+
+2001-10-22 07:48 ivan
+
+ * FS/FS/svc_acct.pm: fix dir check
+
+2001-10-22 05:22 ivan
+
+ * FS/FS/svc_domain.pm: fix delete method for new databases
+
+2001-10-22 01:31 ivan
+
+ * FS/FS/cust_main.pm: tyop
+
+2001-10-22 01:29 ivan
+
+ * FS/FS/: cust_main.pm, cust_pkg.pm: better delete customer code &
+ warnings, delete package ability (& warning)
+
+2001-10-20 05:17 ivan
+
+ * README.1.4.0pre3-4, FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ bin/fs-setup, htetc/global.asa, htetc/handler.pl,
+ httemplate/browse/part_pkg.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/svc_acct.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/part_pkg.cgi: setup and recurring fee tax
+ exempt flags, UI to edit rework part_pkg editing UI some more
+
+2001-10-18 08:49 jeff
+
+ * fs_selfadmin/FS-MailAdminServer/cgi/mailadmin.cgi: tyop ... or
+ something
+
+2001-10-18 08:30 jeff
+
+ * fs_selfadmin/README: rudimentary self-admin instructions
+
+2001-10-18 08:04 jeff
+
+ * fs_selfadmin/: fs_mailadmin_server,
+ FS-MailAdminServer/MailAdminClient.pm,
+ FS-MailAdminServer/fs_mailadmind,
+ FS-MailAdminServer/cgi/mailadmin.cgi: preliminary self
+ administration
+
+2001-10-16 13:33 jeff
+
+ * bin/svc_acct.export: added slipip insertion for icradius and
+ vpopmail restart config
+
+2001-10-15 07:58 ivan
+
+ * FS/FS/cust_pkg.pm, htetc/global.asa, htetc/handler.pl,
+ httemplate/edit/REAL_cust_pkg.cgi,
+ httemplate/edit/process/REAL_cust_pkg.cgi,
+ httemplate/view/cust_pkg.cgi: date editing
+
+2001-10-15 05:16 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_main.pm, FS/FS/cust_pkg.pm,
+ httemplate/misc/bill.cgi: print reasons with credits on invoices
+
+ use straight eval, not Safe::reval in cust_main::bill for now, as
+ i have no idea how to call methods on a share()'ed scalar.
+ hmm.
+
+ add cust_pkg::cust_main method
+
+ s/eidiot/idiot/ in httemplate/misc/bill.cgi
+
+2001-10-15 04:39 ivan
+
+ * httemplate/edit/part_pkg.cgi: remove errant javascript alert()
+ plan ||= 'flat' for custom pricing 9clone) package definitions
+ too
+
+2001-10-15 04:35 ivan
+
+ * httemplate/edit/cust_main.cgi: visual fix
+
+2001-10-15 03:42 ivan
+
+ * README.1.4.0pre3-4, FS/FS/cust_main.pm, FS/FS/part_pkg.pm,
+ bin/fs-setup, httemplate/browse/part_pkg.cgi,
+ httemplate/docs/config.html, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/part_pkg.cgi,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_pkg.cgi: price plans web gui 1st
+ pass, oh my
+
+2001-10-12 08:26 ivan
+
+ * httemplate/browse/queue.cgi: add (as yet inactive) retry & remove
+ links
+
+2001-10-11 10:46 ivan
+
+ * htetc/: global.asa, handler.pl: price plan uI!
+
+2001-10-11 10:44 ivan
+
+ * httemplate/edit/part_pkg.cgi: "price plans" UP support.CVS:
+ ----------------------------------------------------------------------
+
+2001-10-09 23:22 thalakan
+
+ * httemplate/search/cust_main.cgi: Reverted.
+
+2001-10-09 22:59 thalakan
+
+ * httemplate/search/cust_main.cgi: Stupid mistake. Works now.
+
+2001-10-09 22:42 ivan
+
+ * httemplate/search/cust_main.cgi: revert silly changes
+
+2001-10-09 22:33 thalakan
+
+ * httemplate/search/cust_main.cgi: Change to use ut_name instead.
+
+2001-10-09 22:24 ivan
+
+ * FS/FS/Record.pm: embarassing doc fix, thanks jason
+
+2001-10-09 16:10 ivan
+
+ * README.1.4.0pre3-4, FS/FS/cust_credit.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_pkg.pm,
+ httemplate/docs/config.html, httemplate/docs/install.html,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html,
+ bin/fs-setup: add `unsuspendauto' config file: enable the
+ automatic unsuspension of suspended packages when a customer's
+ balance due changes from positive to zero or negative as the
+ result of a payment or credit
+
+ add cust_pkg.manual_flag to disable this behaviour per customer
+ package (no UI to set this yet)
+
+2001-10-09 06:16 ivan
+
+ * httemplate/docs/install.html: update mysql links
+
+2001-10-09 00:16 ivan
+
+ * httemplate/edit/process/part_svc.cgi: that was a confusing bug to
+ fix
+
+2001-10-08 20:11 ivan
+
+ * FS/FS/cust_pkg.pm: fix syntax error in newly-enabled insert sub,
+ sheesh
+
+2001-10-02 13:07 ivan
+
+ * httemplate/docs/upgrade8.html: doc clarification (?)
+
+2001-10-02 09:00 jeff
+
+ * README.1.4.0pre3-4, FS/FS/cust_pay_batch.pm, bin/fs-setup,
+ httemplate/docs/upgrade8.html: add pkey to batch payments and fix
+ a doc typo
+
+2001-10-02 04:10 ivan
+
+ * FS/FS/svc_acct.pm: allow some more characters in GECOS... showing
+ up in fix.net's password files
+
+2001-10-01 03:31 ivan
+
+ * FS/FS/cust_pkg.pm: oops
+
+2001-09-30 15:35 ivan
+
+ * FS/FS/svc_acct.pm: arg
+
+2001-09-30 15:19 ivan
+
+ * FS/FS/svc_acct.pm: $1 doesn't seem to last very long...
+
+2001-09-30 13:30 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/docs/config.html:
+ username-uppercase config file
+
+2001-09-30 00:55 ivan
+
+ * fs_webdemo/registerd.Pg: purge message
+
+2001-09-27 21:33 ivan
+
+ * httemplate/docs/install.html: ssh recommendations
+
+2001-09-27 14:49 ivan
+
+ * FS/FS/svc_acct_pop.pm: not used
+
+2001-09-27 14:37 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: it's 2001 now.
+
+2001-09-27 14:32 ivan
+
+ * fs_signup/FS-SignupClient/cgi/: signup.cgi, signup.html:
+ popSELECTOR!
+
+2001-09-27 14:12 ivan
+
+ * httemplate/edit/: cust_main.cgi, svc_acct.cgi: popSELECTOR
+
+2001-09-27 13:41 ivan
+
+ * httemplate/edit/cust_main.cgi, httemplate/edit/svc_acct.cgi,
+ FS/FS/svc_acct_pop.pm, httemplate/view/svc_acct.cgi: pop
+ selector!
+
+2001-09-27 11:33 ivan
+
+ * httemplate/view/svc_acct.cgi: fix for pre-1.4.0 accounts with no
+ domsvc
+
+2001-09-26 04:34 ivan
+
+ * README.1.4.0pre3-4: index oops
+
+2001-09-26 02:17 ivan
+
+ * README.1.4.0pre3-4, FS/FS.pm, FS/MANIFEST,
+ FS/FS/cust_credit_bill.pm, FS/FS/cust_main.pm,
+ FS/FS/part_pop_local.pm, FS/FS/svc_acct_pop.pm,
+ FS/t/part_pop_local.t, bin/fs-setup, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html: add part_pop_local table
+
+2001-09-25 11:03 ivan
+
+ * FS/FS/cust_main.pm:
+ ror
+
+2001-09-25 11:01 ivan
+
+ * FS/FS/cust_main.pm, httemplate/docs/config.html: add
+ emailinvoiceonly config file and begin to use it
+
+2001-09-25 08:55 ivan
+
+ * FS/FS/cust_main.pm, httemplate/docs/config.html:
+ Business::OnlinePayment::BankOfAmerica
+
+2001-09-24 17:05 ivan
+
+ * FS/bin/freeside-queued: better REAPER
+
+2001-09-23 20:23 ivan
+
+ * FS/: FS/UID.pm, bin/freeside-queued: queue daemon forks now
+
+2001-09-20 20:47 ivan
+
+ * httemplate/view/cust_main.cgi: show company and name (instead of
+ just company) for referring customers that have a company
+
+2001-09-19 17:13 ivan
+
+ * FS/FS/cust_main.pm: really fix fuzzy searching
+
+2001-09-19 17:10 ivan
+
+ * FS/FS/cust_main.pm: fix fuzzy searching
+
+2001-09-19 14:51 ivan
+
+ * FS/bin/freeside-queued: set real uid too. whew. ssh now
+ working.
+
+2001-09-19 14:06 ivan
+
+ * README.1.4.0pre3-4, FS/MANIFEST, FS/FS/svc_acct.pm,
+ FS/bin/freeside-apply-credits, httemplate/docs/config.html:
+ directory hashing remove jeff's lib patch from
+ freeside-apply-credits add freeside-apply-credits to MANIFEST
+ README for pre3-4
+
+2001-09-19 12:41 ivan
+
+ * FS/FS/svc_acct.pm: tyop
+
+2001-09-19 12:39 ivan
+
+ * FS/FS/svc_acct.pm: hopefully report some sort of ssh error
+
+2001-09-19 12:28 ivan
+
+ * FS/FS/svc_acct.pm: ;args
+
+2001-09-19 12:19 ivan
+
+ * FS/FS/svc_acct.pm: FS::svc_acct::ssh
+
+2001-09-19 12:00 ivan
+
+ * FS/bin/freeside-queued: set $ENV{HOME}
+
+2001-09-18 17:24 ivan
+
+ * FS/FS/svc_acct.pm: icradius transactional password changes
+ (suspensions, unsuspensions)
+
+2001-09-16 05:45 ivan
+
+ * FS/FS/Record.pm, FS/FS/cust_main_invoice.pm, FS/FS/svc_acct.pm,
+ httemplate/index.html, httemplate/docs/config.html,
+ httemplate/search/cust_main.cgi, httemplate/view/cust_main.cgi:
+ fix oops in FS::cust_main_invoice::replace preventing package
+ cancellation
+
+ add toggle switch to cust_main searching to show/hide cancelled
+ customers. hidecancelledcustomers config file is just which
+ state it starts in.
+
+ add signupurl config file to enable showing of the customer's
+ signup URL on the view page.
+
+2001-09-14 12:54 ivan
+
+ * FS/FS/svc_acct.pm: fix for no svc_acct_sm!!!
+
+2001-09-14 11:05 ivan
+
+ * FS/FS/Record.pm: s/croak/confess/
+
+2001-09-12 08:54 ivan
+
+ * httemplate/docs/: install.html, upgrade8.html: mason warnings
+
+2001-09-12 08:45 ivan
+
+ * FS/FS/part_svc.pm: oops
+
+2001-09-11 16:44 ivan
+
+ * FS/FS/part_svc.pm, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/svc_forward.cgi, httemplate/view/svc_acct.cgi:
+ radius attributes & default/fixed values should work again now
+
+2001-09-11 15:20 ivan
+
+ * FS/FS/svc_Common.pm, bin/fs-radius-add-check,
+ bin/fs-radius-add-reply, bin/fs-setup, bin/svc_acct.export: fix
+ radius attribute adding
+
+2001-09-11 14:58 ivan
+
+ * FS/bin/freeside-queued: usage sub
+
+2001-09-11 13:59 ivan
+
+ * httemplate/edit/svc_acct_sm.cgi: persistance problem not clearing
+ variables between runs
+
+2001-09-11 13:44 ivan
+
+ * httemplate/search/svc_acct.cgi: getting "you should run the
+ bin/fs-migrate-svc_acct_sm" message unexpectedly
+
+2001-09-11 12:16 ivan
+
+ * httemplate/edit/part_svc.cgi: forgot closing form tag, breaks ie,
+ others?
+
+2001-09-11 06:10 ivan
+
+ * FS/FS/svc_acct.pm: transactional job-queued icradius/freeradius
+ export
+
+2001-09-11 05:46 ivan
+
+ * httemplate/edit/process/part_svc.cgi: more service edit fix
+
+2001-09-11 05:42 ivan
+
+ * httemplate/edit/part_svc.cgi: fix service editing
+
+2001-09-11 05:25 ivan
+
+ * FS/FS/queue.pm: queue clean fix
+
+2001-09-11 05:24 ivan
+
+ * FS/FS/queue.pm: job queue fix
+
+2001-09-11 05:10 ivan
+
+ * FS/FS/cust_main.pm: fuzzyfix
+
+2001-09-11 05:06 ivan
+
+ * FS/FS/svc_acct.pm: better logging
+
+2001-09-11 05:00 ivan
+
+ * FS/FS/svc_acct.pm: cyrus fix!
+
+2001-09-11 04:52 ivan
+
+ * FS/bin/freeside-queued: rar
+
+2001-09-11 04:28 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: signup server fix!
+
+2001-09-11 04:03 ivan
+
+ * fs_signup/FS-SignupClient/cgi/: signup.cgi, signup.html: missing
+ quote in new template
+
+2001-09-11 03:05 ivan
+
+ * httemplate/edit/process/quick-cust_pkg.cgi: s/die/ediot/
+
+2001-09-11 02:56 ivan
+
+ * README.1.4.0pre2-3, httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/view/cust_main.cgi: fix quick order
+
+2001-09-10 21:44 ivan
+
+ * httemplate/browse/queue.cgi: web queue view
+
+2001-09-10 21:17 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/docs/config.html: username-noperiod
+ config file
+
+2001-09-10 20:15 ivan
+
+ * README.1.4.0pre2-3, FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ FS/bin/freeside-queued, httemplate/docs/config.html,
+ httemplate/docs/export.html, httemplate/edit/part_svc.cgi: cyrus
+ support
+
+2001-09-10 18:09 ivan
+
+ * FS/bin/freeside-queued: working queued
+
+2001-09-10 17:08 ivan
+
+ * README.1.4.0pre2-3, FS/FS.pm, FS/MANIFEST, FS/FS/Record.pm,
+ FS/FS/cust_credit_bill.pm, FS/FS/cust_main.pm, FS/FS/part_svc.pm,
+ FS/FS/queue.pm, FS/FS/queue_arg.pm, FS/bin/freeside-bill,
+ FS/bin/freeside-queued, FS/t/queue.t, FS/t/queue_arg.t,
+ htetc/handler.pl, httemplate/index.html,
+ httemplate/browse/part_svc.cgi, httemplate/docs/install.html,
+ httemplate/docs/schema.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/search/cust_main.cgi: faster (cached) fuzzy searches
+ prelim. job queues! fixed part_svc editing
+
+2001-09-10 17:07 ivan
+
+ * bin/: freeside-init, fs-migrate-part_svc, fs-setup: fixing
+ fs-migrate-part_svc updateing fs-setup for job queues
+ freeside-init for starting freeside-queued
+
+2001-09-07 17:28 khoff
+
+ * bin/fs-setup: First post. Sorry. Missing comma.
+
+2001-09-07 13:49 ivan
+
+ * FS/FS/part_svc_column.pm: oops, forgot to add this
+
+2001-09-07 13:26 ivan
+
+ * FS/FS/raddb.pm, FS/FS/svc_acct.pm, bin/generate-raddb: tyops
+
+2001-09-07 13:19 ivan
+
+ * FS/MANIFEST: tyop
+
+2001-09-07 13:17 ivan
+
+ * FS/MANIFEST, FS/FS/raddb.pm, FS/FS/svc_acct.pm, FS/t/raddb.t,
+ bin/fs-radius-add-check, bin/fs-radius-add-reply, bin/fs-setup,
+ bin/generate-raddb: fix RADIUS attribute capitalization
+
+2001-09-06 14:43 ivan
+
+ * httemplate/docs/: install.html, postgresql.html: no more pg
+ RADIUS silliness
+
+2001-09-06 14:20 ivan
+
+ * FS/FS/svc_acct.pm, httemplate/docs/schema.html: doc
+
+2001-09-06 13:41 ivan
+
+ * README.1.4.0pre2-3, FS/FS.pm, FS/MANIFEST, FS/FS/UID.pm,
+ FS/FS/part_svc.pm, FS/FS/svc_Common.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_acct_sm.pm, FS/FS/svc_domain.pm, FS/FS/svc_forward.pm,
+ FS/FS/svc_www.pm, FS/t/part_svc_column.t,
+ bin/fs-migrate-part_svc, bin/fs-migrate-payref,
+ bin/fs-radius-add-check, bin/fs-radius-add-reply, bin/fs-setup,
+ httemplate/browse/part_svc.cgi, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/part_svc.cgi,
+ httemplate/edit/process/part_svc.cgi: finally fix part_svc!!!
+
+2001-09-04 08:12 ivan
+
+ * httemplate/docs/admin.html: tyop
+
+2001-09-04 08:06 ivan
+
+ * httemplate/edit/: agent_type.cgi, process/cust_main.cgi: oops
+ indeed
+
+2001-09-04 07:44 ivan
+
+ * FS/FS/cust_pkg.pm, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_svc.cgi, httemplate/docs/admin.html,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/process/quick-cust_pkg.cgi,
+ httemplate/view/cust_main.cgi: new admin documentation, quick
+ one-pkg order
+
+2001-09-04 04:15 ivan
+
+ * bin/fs-setup: rar
+
+2001-09-04 04:15 ivan
+
+ * bin/fs-setup: much better
+
+2001-09-04 04:14 ivan
+
+ * bin/fs-setup: tyops
+
+2001-09-04 04:03 ivan
+
+ * bin/fs-setup, httemplate/docs/config.html: silly syntax error and
+ doc updates
+
+2001-09-04 02:55 ivan
+
+ * httemplate/docs/install.html: better installation instructions
+
+2001-09-04 02:54 ivan
+
+ * htetc/global.asa: hehe, this should help out everybody without
+ DBIx::Profile (i.e. everybody)
+
+2001-09-03 15:16 ivan
+
+ * bin/fs-setup: this too
+
+2001-09-03 15:07 ivan
+
+ * FS/FS/cust_bill.pm, FS/FS/cust_bill_pay.pm, FS/FS/cust_main.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_svc.pm, FS/bin/freeside-bill,
+ httemplate/docs/signup.html, httemplate/docs/upgrade8.html,
+ httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/cust_pay.cgi,
+ httemplate/edit/process/cust_pay.cgi, httemplate/misc/bill.cgi,
+ httemplate/view/cust_bill.cgi, httemplate/view/cust_main.cgi: fix
+ more bugs
+
+2001-09-02 00:57 ivan
+
+ * CREDITS: credito
+
+2001-09-02 00:57 ivan
+
+ * bin/generate-tests: gawl
+
+2001-09-02 00:49 ivan
+
+ * FS/FS/cust_bill_pay.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_credit_bill.pm, FS/FS/cust_credit_refund.pm,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/view/cust_main.cgi: things are starting to work again,
+ sorta.
+
+2001-09-01 22:38 ivan
+
+ * FS/FS/cust_bill_pay.pm, FS/FS/cust_credit_refund.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_refund.pm, bin/fs-migrate-payref:
+ migration. ugh.
+
+2001-09-01 21:51 ivan
+
+ * FS/FS/: cust_svc.pm, svc_acct.pm: better error msgs
+
+2001-09-01 21:25 ivan
+
+ * FS/: FS.pm, MANIFEST, test.pl, FS/cust_bill_pay.pm,
+ FS/cust_main.pm, FS/cust_refund.pm, t/CGI.t, t/CGIwrapper.t,
+ t/Conf.t, t/Record.t, t/UID.t, t/agent.t, t/agent_type.t,
+ t/cust_bill.t, t/cust_bill_pay.t, t/cust_bill_pkg.t,
+ t/cust_credit.t, t/cust_credit_bill.t, t/cust_credit_refund.t,
+ t/cust_main.t, t/cust_main_county.t, t/cust_main_invoice.t,
+ t/cust_pay.t, t/cust_pay_batch.t, t/cust_pkg.t, t/cust_refund.t,
+ t/cust_svc.t, t/domain_record.t, t/nas.t, t/part_pkg.t,
+ t/part_referral.t, t/part_svc.t, t/pkg_svc.t, t/port.t,
+ t/prepay_credit.t, t/session.t, t/svc_Common.t, t/svc_acct.t,
+ t/svc_acct_pop.t, t/svc_acct_sm.t, t/svc_domain.t,
+ t/svc_forward.t, t/svc_www.t, t/type_pkgs.t: lame testsuite and
+ the embarassing fixes in it found
+
+2001-09-01 20:42 ivan
+
+ * httemplate/docs/upgrade8.html: really. backup.
+
+2001-09-01 20:20 ivan
+
+ * httemplate/docs/upgrade8.html: upgrade
+
+2001-09-01 19:53 jeff
+
+ * FS/bin/freeside-apply-credits: adding a credit apply utility
+
+2001-09-01 19:46 ivan
+
+ * FS/FS/cust_bill_pay.pm, FS/FS/cust_main.pm, FS/FS/cust_pay.pm,
+ FS/FS/cust_refund.pm, bin/fs-setup, httemplate/docs/schema.html,
+ httemplate/docs/upgrade8.html: cust_refund and cust_pay get
+ custnums
+
+2001-09-01 18:27 ivan
+
+ * FS/FS/: cust_bill.pm, cust_bill_pay.pm, cust_credit.pm,
+ cust_credit_bill.pm, cust_credit_refund.pm, cust_main.pm,
+ cust_refund.pm: more udpates for the new world of unapplied
+ stuff. yay.
+
+2001-09-01 16:41 ivan
+
+ * httemplate/docs/upgrade8.html: cust_bill_pay and
+ cust_credit_refund
+
+2001-09-01 15:28 jeff
+
+ * FS/FS/cust_main.pm, httemplate/docs/upgrade8.html: haste makes
+ waste... and left a method out
+
+2001-09-01 15:18 ivan
+
+ * FS/FS/cust_credit_bill.pm, bin/fs-setup: add primary key
+
+2001-09-01 15:01 ivan
+
+ * FS/MANIFEST: cust_bill_pay & cust_credit_refund
+
+2001-09-01 14:55 jeff
+
+ * FS/FS/cust_bill_pay.pm: oops.. need this too
+
+2001-09-01 14:52 jeff
+
+ * FS/MANIFEST, FS/FS/cust_bill.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_credit_bill.pm, FS/FS/cust_main.pm, bin/fs-setup,
+ httemplate/docs/upgrade8.html,
+ httemplate/edit/cust_credit_bill.cgi,
+ httemplate/edit/process/cust_credit_bill.cgi,
+ httemplate/view/cust_main.cgi: add cust_credit_bill relating
+ multiple invoices to credits
+
+2001-09-01 13:11 ivan
+
+ * FS/FS/cust_bill_pay.pm, FS/FS/cust_credit_refund.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pay.pm, FS/FS/cust_refund.pm,
+ bin/fs-setup, httemplate/docs/schema.html: cust_bill_pay and
+ cust_credit_refund. payments can apply to multiple invoices and
+ refunds can apply to multiple credits.
+
+2001-09-01 05:35 ivan
+
+ * httemplate/search/cust_bill.cgi: totals
+
+2001-08-31 02:20 ivan
+
+ * FS/FS/Record.pm: check US zips more strictly
+
+2001-08-31 01:43 ivan
+
+ * httemplate/browse/svc_acct_pop.cgi: > Order by City might be
+ better
+ state, city, then number
+
+2001-08-31 00:28 ivan
+
+ * httemplate/edit/cust_main_county-expand.cgi: better error message
+ for nonexistant cust_main_county records
+
+2001-08-31 00:17 ivan
+
+ * httemplate/edit/process/cust_main_county-expand.cgi: fixes:
+ > US UT expand state
+ > Submit (no data entered)
+ > US UT is gone frome the list.
+
+2001-08-30 09:23 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi,
+ fs_signup/FS-SignupClient/cgi/signup.html,
+ fs_signup/FS-SignupClient/cgi/success.html,
+ httemplate/docs/signup.html: update signup server: template form
+ and success html, document
+
+2001-08-30 08:30 ivan
+
+ * httemplate/edit/part_svc.cgi: slighly more docu
+
+2001-08-29 02:11 ivan
+
+ * httemplate/edit/agent.cgi: ui
+
+2001-08-29 01:45 ivan
+
+ * bin/fs-setup, httemplate/docs/upgrade8.html: catchall *can* be
+ NULL
+
+2001-08-28 09:58 ivan
+
+ * fs_signup/fs_signup_server,
+ fs_signup/FS-SignupClient/SignupClient.pm,
+ fs_signup/FS-SignupClient/fs_signupd,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ httemplate/docs/signup.html, httemplate/docs/upgrade8.html,
+ httemplate/search/cust_main.cgi: customer-to-customer referrals
+ in singup server
+
+2001-08-28 07:34 ivan
+
+ * FS/FS/cust_main.pm, httemplate/docs/config.html,
+ httemplate/docs/upgrade8.html, httemplate/edit/cust_main.cgi,
+ httemplate/search/cust_main.cgi, httemplate/view/cust_main.cgi:
+ customer-to-customer referrals!
+
+2001-08-25 22:06 ivan
+
+ * FS/FS/: cust_credit.pm, cust_main.pm: brainfart
+
+2001-08-25 22:05 ivan
+
+ * FS/FS/cust_credit.pm: reason can't be null
+
+2001-08-22 23:17 ivan
+
+ * FS/FS/cust_main.pm: no need to be y1.9k complient
+
+2001-08-21 03:27 ivan
+
+ * httemplate/edit/: svc_acct.cgi, svc_forward.cgi: fix these up,
+ most everything is working svc_forward-wise now
+
+2001-08-21 02:34 ivan
+
+ * FS/FS/Record.pm, FS/FS/UID.pm, FS/bin/freeside-bill,
+ htetc/global.asa, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/svc_acct_pop.cgi: no more &swapuid
+
+2001-08-20 20:03 ivan
+
+ * FS/FS/svc_acct.pm: fix domain method, and it works against old
+ databases now too
+
+2001-08-20 19:44 ivan
+
+ * FS/FS/domain_record.pm, FS/FS/prepay_credit.pm, FS/FS/svc_www.pm,
+ FS/bin/freeside-print-batch, eg/TEMPLATE_cust_main.import,
+ eg/table_template-svc.pm: remove $Log$
+
+2001-08-20 19:43 ivan
+
+ * bin/: dbdef-create, fs-migrate-svc_acct_sm, svc_acct_sm.import: i
+ think svc_acct_sm.import should go away, but...
+
+2001-08-20 19:32 ivan
+
+ * test/cgi-test: remove $Log$
+
+2001-08-20 19:31 ivan
+
+ * httemplate/: browse/agent.cgi, browse/agent_type.cgi,
+ browse/part_pkg.cgi, browse/part_referral.cgi,
+ browse/svc_acct_pop.cgi, edit/agent.cgi, edit/agent_type.cgi,
+ edit/cust_credit.cgi, edit/cust_main_county-expand.cgi,
+ edit/cust_main_county.cgi, edit/cust_pay.cgi, edit/cust_pkg.cgi,
+ edit/part_pkg.cgi, edit/part_referral.cgi, edit/svc_acct_pop.cgi,
+ edit/svc_acct_sm.cgi, edit/svc_domain.cgi, edit/svc_forward.cgi,
+ edit/process/agent.cgi, edit/process/agent_type.cgi,
+ edit/process/cust_credit.cgi, edit/process/cust_main_county.cgi,
+ edit/process/cust_pay.cgi, edit/process/cust_pkg.cgi,
+ edit/process/part_pkg.cgi, edit/process/part_referral.cgi,
+ edit/process/svc_acct.cgi, edit/process/svc_acct_pop.cgi,
+ edit/process/svc_acct_sm.cgi, edit/process/svc_domain.cgi,
+ edit/process/svc_forward.cgi, misc/bill.cgi,
+ misc/cancel-unaudited.cgi, misc/cancel_pkg.cgi,
+ misc/catchall.cgi, misc/delete-customer.cgi, misc/expire_pkg.cgi,
+ misc/link.cgi, misc/print-invoice.cgi, misc/susp_pkg.cgi,
+ misc/unsusp_pkg.cgi, misc/process/catchall.cgi,
+ misc/process/delete-customer.cgi, misc/process/link.cgi,
+ search/cust_bill.cgi, search/svc_acct_sm.cgi,
+ search/svc_domain.cgi, view/cust_bill.cgi, view/cust_pkg.cgi,
+ view/svc_acct.cgi, view/svc_acct_sm.cgi, view/svc_domain.cgi,
+ view/svc_forward.cgi: remove $Log$ messages. whew.
+
+2001-08-20 19:16 ivan
+
+ * httemplate/search/svc_acct.cgi: fix to work against 1.3.x
+ databases, with a warning
+
+2001-08-20 19:03 ivan
+
+ * httemplate/search/cust_pkg.cgi: deal with databases w/o separate
+ shipping address
+
+2001-08-20 17:39 ivan
+
+ * FS/FS/: svc_acct.pm, svc_domain.pm, svc_forward.pm: fix some
+ silly syntax errors
+
+2001-08-20 11:43 jeff
+
+ * htdocs/docs/upgrade8.html: one that got away
+
+2001-08-20 06:10 ivan
+
+ * FS/FS/svc_domain.pm: use var
+
+2001-08-20 05:15 ivan
+
+ * httemplate/edit/svc_acct.cgi: #
+
+2001-08-20 05:13 ivan
+
+ * httemplate/edit/svc_acct.cgi: only show domains associated with
+ this customer.
+
+2001-08-20 04:18 ivan
+
+ * FS/FS/cust_svc.pm: labels for svc_acct accounts are now fully
+ qualified!
+
+2001-08-20 04:04 ivan
+
+ * FS/FS/: svc_acct.pm, svc_domain.pm, svc_forward.pm: more
+ svc_forward work
+
+2001-08-20 02:41 ivan
+
+ * FS/FS/: svc_acct.pm, svc_acct_sm.pm, svc_domain.pm,
+ svc_forward.pm: dtrt when deleting accouts wrt forwards,
+ catchalls & other references to svc_acct records
+
+ depreciate svc_acct_sm further; move qmail catchall handling to
+ svc_domain
+
+2001-08-20 02:38 ivan
+
+ * httemplate/docs/: config.html, export.html, schema.html:
+ documentation updates
+
+2001-08-19 08:53 jeff
+
+ * FS/MANIFEST, FS/FS/cust_svc.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_forward.pm, httemplate/edit/part_svc.cgi,
+ httemplate/edit/svc_acct.cgi, httemplate/edit/svc_forward.cgi,
+ httemplate/edit/process/svc_forward.cgi,
+ httemplate/misc/catchall.cgi,
+ httemplate/misc/process/catchall.cgi,
+ httemplate/search/svc_acct.cgi, httemplate/search/svc_domain.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_domain.cgi,
+ httemplate/view/svc_forward.cgi: added user interface for
+ svc_forward and vpopmail support
+
+2001-08-19 06:50 ivan
+
+ * bin/fs-setup, httemplate/docs/upgrade8.html: indices on cust_main
+ ship_last and ship_country
+
+2001-08-19 03:25 ivan
+
+ * bin/svc_acct.import: add system shells to @FS::svc_acct:shells on
+ the fly, fixes: ticket #88
+
+2001-08-19 02:08 ivan
+
+ * TODO: this is what i fed to RT, might as well check it in.
+
+ no further modifications to TODO. everything is in the ticketing
+ system now.
+
+2001-08-19 01:32 ivan
+
+ * httemplate/search/cust_pkg.cgi: display bill and service
+ name/company, and services
+
+2001-08-19 01:18 ivan
+
+ * FS/FS/: svc_acct.pm, svc_domain.pm: ->setfixed untaints svcnum
+
+2001-08-19 01:15 ivan
+
+ * FS/FS/svc_acct.pm: set fixed fields before checking domsvc
+
+2001-08-18 17:48 ivan
+
+ * FS/FS/: Record.pm, cust_main.pm: country fields will now accept
+ names and change them to two-letter codes
+
+2001-08-17 04:33 ivan
+
+ * FS/FS/Record.pm: ut_phonen: fallback to ut_textn, instead of
+ ut_alphan for non-US/CA phone numbers
+
+2001-08-17 04:28 ivan
+
+ * FS/FS/Record.pm: canada has same phone# rules as US
+
+2001-08-17 04:05 ivan
+
+ * httemplate/: browse/cust_main_county.cgi,
+ edit/cust_main_county.cgi,
+ edit/process/cust_main_county-collapse.cgi,
+ edit/process/cust_main_county-expand.cgi: clean up tax rate
+ editing: sort by country->state->county, add "collapse state"
+ if the tax rates are the same statewide, redirect "expand
+ state" to the browse, not edit screen
+
+2001-08-17 03:57 ivan
+
+ * bin/: dbdef-create, svc_acct.export, svc_acct.import: gah
+
+2001-08-17 03:57 ivan
+
+ * FS/FS/svc_domain.pm: document catchall and untaint everything
+
+2001-08-17 03:55 ivan
+
+ * FS/FS/cust_main.pm, httemplate/docs/config.html:
+ Business::OnlinePayment
+
+2001-08-17 03:53 ivan
+
+ * Makefile: alldocs target
+
+2001-08-17 03:53 ivan
+
+ * CREDITS: thanks jeff!
+
+2001-08-17 03:52 ivan
+
+ * fs_signup/fs_signup_server: fix email invoice to the
+ being-creted-account bug
+
+2001-08-15 03:04 ivan
+
+ * httemplate/search/: cust_pkg.cgi, svc_acct.cgi: remove (some of
+ the) bad direct exit; calls
+
+2001-08-13 16:15 ivan
+
+ * httemplate/view/cust_main.cgi: don't display empty comment box
+
+2001-08-13 16:10 ivan
+
+ * httemplate/edit/process/cust_main.cgi: properly massage
+ ship_state & work okay when no initial pkg is selected
+
+2001-08-12 18:07 ivan
+
+ * htdocs/: docs/config.html, index.html, browse/agent.cgi,
+ browse/agent_type.cgi, browse/cust_main_county.cgi,
+ browse/nas.cgi, browse/part_pkg.cgi, browse/part_referral.cgi,
+ browse/part_svc.cgi, browse/svc_acct_pop.cgi, docs/admin.html,
+ docs/billing.html, docs/export.html, docs/index.html,
+ docs/install.html, docs/legacy.html, docs/overview.dia,
+ docs/overview.png, docs/passwd.html, docs/postgresql.html,
+ docs/schema.html, docs/session.html, docs/signup.html,
+ docs/trouble.html, docs/upgrade.html, docs/upgrade2.html,
+ docs/upgrade3.html, docs/upgrade4.html, docs/upgrade5.html,
+ docs/upgrade6.html, docs/upgrade7.html, docs/man/FS.html,
+ docs/man/FS/Bill.html, docs/man/FS/CGI.html,
+ docs/man/FS/CGIwrapper.html, docs/man/FS/Conf.html,
+ docs/man/FS/Invoice.html, docs/man/FS/Record.html,
+ docs/man/FS/SSH.html, docs/man/FS/SessionClient.html,
+ docs/man/FS/SignupClient.html, docs/man/FS/UID.html,
+ docs/man/FS/agent.html, docs/man/FS/agent_type.html,
+ docs/man/FS/cust_bill.html, docs/man/FS/cust_bill_pkg.html,
+ docs/man/FS/cust_credit.html, docs/man/FS/cust_main.html,
+ docs/man/FS/cust_main_county.html,
+ docs/man/FS/cust_main_invoice.html, docs/man/FS/cust_pay.html,
+ docs/man/FS/cust_pay_batch.html, docs/man/FS/cust_pkg.html,
+ docs/man/FS/cust_refund.html, docs/man/FS/cust_svc.html,
+ docs/man/FS/dbdef.html, docs/man/FS/dbdef_colgroup.html,
+ docs/man/FS/dbdef_column.html, docs/man/FS/dbdef_index.html,
+ docs/man/FS/dbdef_table.html, docs/man/FS/dbdef_unique.html,
+ docs/man/FS/domain_record.html, docs/man/FS/nas.html,
+ docs/man/FS/part_pkg.html, docs/man/FS/part_referral.html,
+ docs/man/FS/part_svc.html, docs/man/FS/pkg_svc.html,
+ docs/man/FS/port.html, docs/man/FS/prepay_credit.html,
+ docs/man/FS/session.html, docs/man/FS/svc_Common.html,
+ docs/man/FS/svc_acct.html, docs/man/FS/svc_acct_pop.html,
+ docs/man/FS/svc_acct_sm.html, docs/man/FS/svc_domain.html,
+ docs/man/FS/svc_www.html, docs/man/FS/type_pkgs.html,
+ docs/man/FS/UI/Base.html, docs/man/FS/UI/CGI.html,
+ docs/man/FS/UI/Gtk.html, docs/man/FS/UI/agent.html,
+ edit/agent.cgi, edit/agent_type.cgi, edit/cust_credit.cgi,
+ edit/cust_main.cgi, edit/cust_main_county-expand.cgi,
+ edit/cust_main_county.cgi, edit/cust_pay.cgi, edit/cust_pkg.cgi,
+ edit/part_pkg.cgi, edit/part_referral.cgi, edit/part_svc.cgi,
+ edit/svc_acct.cgi, edit/svc_acct_pop.cgi, edit/svc_acct_sm.cgi,
+ edit/svc_domain.cgi, edit/process/agent.cgi,
+ edit/process/agent_type.cgi, edit/process/cust_credit.cgi,
+ edit/process/cust_main.cgi,
+ edit/process/cust_main_county-expand.cgi,
+ edit/process/cust_main_county.cgi, edit/process/cust_pay.cgi,
+ edit/process/cust_pkg.cgi, edit/process/part_pkg.cgi,
+ edit/process/part_referral.cgi, edit/process/part_svc.cgi,
+ edit/process/svc_acct.cgi, edit/process/svc_acct_pop.cgi,
+ edit/process/svc_acct_sm.cgi, edit/process/svc_domain.cgi,
+ images/mid-logo.png, images/small-logo.png, misc/bill.cgi,
+ misc/cancel-unaudited.cgi, misc/cancel_pkg.cgi,
+ misc/delete-customer.cgi, misc/expire_pkg.cgi, misc/link.cgi,
+ misc/print-invoice.cgi, misc/susp_pkg.cgi, misc/unsusp_pkg.cgi,
+ misc/process/delete-customer.cgi, misc/process/link.cgi,
+ search/cust_bill.cgi, search/cust_bill.html,
+ search/cust_main-payinfo.html, search/cust_main.cgi,
+ search/cust_main.html, search/cust_pkg.cgi, search/svc_acct.cgi,
+ search/svc_acct.html, search/svc_acct_sm.cgi,
+ search/svc_acct_sm.html, search/svc_domain.cgi,
+ search/svc_domain.html, view/cust_bill.cgi, view/cust_main.cgi,
+ view/cust_pkg.cgi, view/svc_acct.cgi, view/svc_acct_sm.cgi,
+ view/svc_domain.cgi, .htaccess: removing
+
+2001-08-12 18:00 ivan
+
+ * httemplate/docs/schema.html: add svc_forward, depriciate
+ svc_acct_sm
+
+2001-08-12 17:21 ivan
+
+ * FS/FS/svc_acct.pm: untaint svcnum & domsvc
+
+2001-08-12 17:19 ivan
+
+ * bin/fs-setup: depriciate svc_acct_sm, add unique index for
+ username+domsvc on svc_acct, remove silly $Log$
+
+2001-08-12 12:41 jeff
+
+ * FS/FS/svc_acct.pm, FS/FS/svc_domain.pm, FS/FS/svc_forward.pm,
+ bin/fs-migrate-svc_acct_sm, bin/fs-setup, bin/svc_acct.export,
+ bin/svc_acct_sm.export, htdocs/docs/config.html,
+ htdocs/docs/upgrade8.html, httemplate/docs/config.html,
+ httemplate/docs/upgrade8.html: merging vpopmail support branch
+
+2001-08-12 01:56 ivan
+
+ * httemplate/edit/process/part_svc.cgi: don't use
+ Apache::ASP-specific $Redirect object
+
+2001-08-11 18:26 ivan
+
+ * httemplate/docs/postgresql.html: i did get it working
+
+2001-08-11 17:07 ivan
+
+ * httemplate/edit/: cust_main.cgi, process/cust_main.cgi: use
+ transactional invoice_list setting & eliminate non-sticky "first
+ package"!
+
+2001-08-11 17:07 ivan
+
+ * FS/FS/cust_main.pm: transactional invoice_list setting yay!!!
+
+2001-08-11 17:06 ivan
+
+ * FS/FS/cust_main_invoice.pm: better error msgs
+
+2001-08-11 16:19 ivan
+
+ * httemplate/edit/part_svc.cgi: better error checking, fix scalar
+ context to $cgi->keywords
+
+2001-08-11 16:18 ivan
+
+ * httemplate/browse/part_svc.cgi: missed a variable interpolation
+
+2001-08-10 22:53 ivan
+
+ * bin/fs-setup, httemplate/docs/upgrade8.html: add comments field
+
+2001-08-10 22:52 ivan
+
+ * httemplate/: edit/cust_main.cgi, view/cust_main.cgi: add customer
+ comments fields
+
+2001-08-10 22:52 ivan
+
+ * FS/FS/cust_main.pm: add comments field, fix ship_ address
+ handling (don't consider a value for ship_state field to mean
+ something meaningful is in ship_*)
+
+2001-08-10 22:51 ivan
+
+ * FS/FS/part_svc.pm: better error msg
+
+2001-08-10 22:50 ivan
+
+ * FS/FS/Record.pm: allow newlines in ut_anything fields fix example
+ for ut_anything
+
+2001-08-10 21:55 ivan
+
+ * httemplate/edit/part_svc.cgi: don't have any other choices in
+ svcdb dropdown for existing services, since you can't change it
+ anyway
+
+2001-08-10 21:29 ivan
+
+ * FS/FS/CGI.pm: that's what $etc is for!
+
+2001-08-10 21:15 ivan
+
+ * httemplate/misc/delete-customer.cgi: better docs
+
+2001-08-10 17:01 ivan
+
+ * FS/FS/cust_main_invoice.pm: "fixes"
+
+ Can't call method "username" on an undefined value at
+ /usr/lib/perl5/site_perl/5.6.0/FS/cust_main_invoice.pm line 162.
+
+ but cust_main_invoice records should probably be updated when
+ svc_acct records are deleted :/
+
+2001-08-08 02:47 ivan
+
+ * httemplate/docs/passwd.html: doc clarification
+
+2001-08-07 21:44 ivan
+
+ * FS/FS/Record.pm: better error msg
+
+2001-08-03 13:34 jeff
+
+ * FS/FS/cust_bill.pm:
+
+ added the tax method
+
+2001-07-30 03:43 ivan
+
+ * FS/FS/CGI.pm: Apache::ASP eidiot fix
+
+2001-07-30 03:41 ivan
+
+ * FS/FS/Record.pm, FS/FS/cust_main.pm,
+ httemplate/search/cust_main.cgi, httemplate/view/cust_main.cgi:
+ shipping address additions
+
+2001-07-30 02:53 ivan
+
+ * httemplate/docs/upgrade8.html: Pg primary key upgrade fix (create
+ fix in new DBIx::DBSchema)
+
+2001-07-30 01:03 ivan
+
+ * httemplate/: .htaccess, docs/overview.dia, docs/overview.png:
+ forgotten files
+
+2001-07-30 01:02 ivan
+
+ * htetc/: global.asa, handler.pl: template stuffs
+
+2001-07-30 01:01 ivan
+
+ * Makefile: need this too!
+
+2001-07-30 00:42 ivan
+
+ * bin/fs-setup: need an DBIx::DBSchema with delcolumn
+
+2001-07-30 00:36 ivan
+
+ * httemplate/index.html, httemplate/browse/agent.cgi,
+ httemplate/browse/agent_type.cgi,
+ httemplate/browse/cust_main_county.cgi,
+ httemplate/browse/nas.cgi, httemplate/browse/part_pkg.cgi,
+ httemplate/browse/part_referral.cgi,
+ httemplate/browse/part_svc.cgi,
+ httemplate/browse/svc_acct_pop.cgi, httemplate/docs/admin.html,
+ httemplate/docs/billing.html, httemplate/docs/config.html,
+ httemplate/docs/export.html, httemplate/docs/index.html,
+ httemplate/docs/install.html, httemplate/docs/legacy.html,
+ httemplate/docs/passwd.html, httemplate/docs/postgresql.html,
+ httemplate/docs/schema.html, httemplate/docs/session.html,
+ httemplate/docs/signup.html, httemplate/docs/trouble.html,
+ httemplate/docs/upgrade.html, httemplate/docs/upgrade2.html,
+ httemplate/docs/upgrade3.html, httemplate/docs/upgrade4.html,
+ httemplate/docs/upgrade5.html, httemplate/docs/upgrade6.html,
+ httemplate/docs/upgrade7.html, httemplate/docs/upgrade8.html,
+ httemplate/docs/man/FS.html, httemplate/docs/man/FS/Bill.html,
+ httemplate/docs/man/FS/CGI.html,
+ httemplate/docs/man/FS/CGIwrapper.html,
+ httemplate/docs/man/FS/Conf.html,
+ httemplate/docs/man/FS/Invoice.html,
+ httemplate/docs/man/FS/Record.html,
+ httemplate/docs/man/FS/SessionClient.html,
+ httemplate/docs/man/FS/SignupClient.html,
+ httemplate/docs/man/FS/UID.html,
+ httemplate/docs/man/FS/agent.html,
+ httemplate/docs/man/FS/agent_type.html,
+ httemplate/docs/man/FS/cust_bill.html,
+ httemplate/docs/man/FS/cust_bill_pkg.html,
+ httemplate/docs/man/FS/cust_credit.html,
+ httemplate/docs/man/FS/cust_main.html,
+ httemplate/docs/man/FS/cust_main_county.html,
+ httemplate/docs/man/FS/cust_main_invoice.html,
+ httemplate/docs/man/FS/cust_pay.html,
+ httemplate/docs/man/FS/cust_pay_batch.html,
+ httemplate/docs/man/FS/cust_pkg.html,
+ httemplate/docs/man/FS/cust_refund.html,
+ httemplate/docs/man/FS/cust_svc.html,
+ httemplate/docs/man/FS/domain_record.html,
+ httemplate/docs/man/FS/nas.html,
+ httemplate/docs/man/FS/part_pkg.html,
+ httemplate/docs/man/FS/part_referral.html,
+ httemplate/docs/man/FS/part_svc.html,
+ httemplate/docs/man/FS/pkg_svc.html,
+ httemplate/docs/man/FS/port.html,
+ httemplate/docs/man/FS/prepay_credit.html,
+ httemplate/docs/man/FS/session.html,
+ httemplate/docs/man/FS/svc_Common.html,
+ httemplate/docs/man/FS/svc_acct.html,
+ httemplate/docs/man/FS/svc_acct_pop.html,
+ httemplate/docs/man/FS/svc_acct_sm.html,
+ httemplate/docs/man/FS/svc_domain.html,
+ httemplate/docs/man/FS/svc_www.html,
+ httemplate/docs/man/FS/type_pkgs.html,
+ httemplate/docs/man/FS/UI/Base.html,
+ httemplate/docs/man/FS/UI/CGI.html,
+ httemplate/docs/man/FS/UI/Gtk.html,
+ httemplate/docs/man/FS/UI/agent.html, bin/fs-setup, bin/masonize,
+ bin/pod2x, httemplate/edit/agent.cgi,
+ httemplate/edit/agent_type.cgi, httemplate/edit/cust_credit.cgi,
+ httemplate/edit/cust_main.cgi,
+ httemplate/edit/cust_main_county-expand.cgi,
+ httemplate/edit/cust_main_county.cgi,
+ httemplate/edit/cust_pay.cgi, httemplate/edit/cust_pkg.cgi,
+ httemplate/edit/part_pkg.cgi, httemplate/edit/part_referral.cgi,
+ httemplate/edit/part_svc.cgi, httemplate/edit/svc_acct.cgi,
+ httemplate/edit/svc_acct_pop.cgi,
+ httemplate/edit/svc_acct_sm.cgi, httemplate/edit/svc_domain.cgi,
+ httemplate/edit/process/agent.cgi,
+ httemplate/edit/process/agent_type.cgi,
+ httemplate/edit/process/cust_credit.cgi,
+ httemplate/edit/process/cust_main.cgi,
+ httemplate/edit/process/cust_main_county-expand.cgi,
+ httemplate/edit/process/cust_main_county.cgi,
+ httemplate/edit/process/cust_pay.cgi,
+ httemplate/edit/process/cust_pkg.cgi,
+ httemplate/edit/process/part_pkg.cgi,
+ httemplate/edit/process/part_referral.cgi,
+ httemplate/edit/process/part_svc.cgi,
+ httemplate/edit/process/svc_acct.cgi,
+ httemplate/edit/process/svc_acct_pop.cgi,
+ httemplate/edit/process/svc_acct_sm.cgi,
+ httemplate/edit/process/svc_domain.cgi,
+ httemplate/images/mid-logo.png, httemplate/images/small-logo.png,
+ httemplate/misc/bill.cgi, httemplate/misc/cancel-unaudited.cgi,
+ httemplate/misc/cancel_pkg.cgi,
+ httemplate/misc/delete-customer.cgi,
+ httemplate/misc/expire_pkg.cgi, httemplate/misc/link.cgi,
+ httemplate/misc/print-invoice.cgi, httemplate/misc/susp_pkg.cgi,
+ httemplate/misc/unsusp_pkg.cgi,
+ httemplate/misc/process/delete-customer.cgi,
+ httemplate/misc/process/link.cgi,
+ httemplate/search/cust_bill.cgi,
+ httemplate/search/cust_bill.html,
+ httemplate/search/cust_main-payinfo.html,
+ httemplate/search/cust_main.cgi,
+ httemplate/search/cust_main.html, httemplate/search/cust_pkg.cgi,
+ httemplate/search/svc_acct.cgi, httemplate/search/svc_acct.html,
+ httemplate/search/svc_acct_sm.cgi,
+ httemplate/search/svc_acct_sm.html,
+ httemplate/search/svc_domain.cgi,
+ httemplate/search/svc_domain.html, httemplate/view/cust_bill.cgi,
+ httemplate/view/cust_main.cgi, httemplate/view/cust_pkg.cgi,
+ httemplate/view/svc_acct.cgi, httemplate/view/svc_acct_sm.cgi,
+ httemplate/view/svc_domain.cgi: templates!!!
+
+2001-07-30 00:33 ivan
+
+ * FS/FS/: Record.pm, svc_acct.pm: podnitfix
+
+2001-07-30 00:14 ivan
+
+ * INSTALL, README: templates!
+
+2001-07-30 00:13 ivan
+
+ * TODO: todocruft
+
+2001-07-29 23:28 ivan
+
+ * FS/FS/svc_acct.pm: allow !! as password for disabled accounts
+
+2001-07-29 23:07 ivan
+
+ * bin/: svc_acct.export, svc_acct.import: allow !! for locked
+ accounts instead of changing to *SUSPENDED*
+
+2001-07-27 10:16 ivan
+
+ * FS/FS/cust_main_invoice.pm: clarification
+
+2001-07-26 23:17 thalakan
+
+ * FS/FS/cust_main_invoice.pm: Documented some subtle behavior of
+ the checkdest method.
+
+2001-07-24 18:06 thalakan
+
+ * htdocs/docs/schema.html: Added documentation for
+ cust_main_invoice.
+
+2001-07-24 00:00 ivan
+
+ * htdocs/docs/config.html: autocapnames never worked anyway
+
+2001-06-21 09:27 ivan
+
+ * FS/FS/UID.pm: better error message
+
+2001-06-20 01:33 ivan
+
+ * bin/svc_acct.export: > Use of uninitialized value in
+ concatenation (.) at svc_acct.export line
+ > 276.
+
+2001-06-10 02:28 ivan
+
+ * htdocs/docs/billing.html: doc
+
+2001-06-06 15:22 ivan
+
+ * TODO: templating thoughts
+
+2001-06-05 14:40 ivan
+
+ * debian/: README.Debian, changelog, conffiles.ex, control,
+ copyright, cron.d.ex, dirs, docs, ex.doc-base.package,
+ freeside-doc.docs, freeside-doc.files, init.d.ex, manpage.1.ex,
+ manpage.sgml.ex, menu.ex, postinst.ex, postrm.ex, preinst.ex,
+ prerm.ex, rules, watch.ex: add deb packaging foo (doesn't work
+ yet)
+
+2001-06-03 10:22 ivan
+
+ * FS/FS/svc_domain.pm: SOA serial number problem with Date::Format
+ %e: no leading zero
+
+2001-06-03 07:29 ivan
+
+ * htdocs/docs/index.html: oops!
+
+2001-06-03 07:21 ivan
+
+ * htdocs/docs/: index.html, upgrade7.html: 1.3.1!!!
+
+2001-06-03 07:16 ivan
+
+ * README: 1.3.1!!!
+
+2001-06-03 07:16 ivan
+
+ * bin/fs-setup: allow empty refund reasons
+
+2001-06-03 07:15 ivan
+
+ * TODO: yes yes
+
+2001-06-03 05:36 ivan
+
+ * FS/FS/svc_acct.pm, htdocs/docs/config.html: add username-letter
+ and username-letterfirst config files
+
+2001-06-03 04:40 ivan
+
+ * htdocs/view/cust_main.cgi: inline doc clarification
+
+2001-06-03 04:37 ivan
+
+ * FS/FS/svc_acct.pm: fixes
+
+ Can't locate object method "setfield" via package "svc_acct_sm"
+ at /usr/local/lib/perl5/site_perl/5.005/FS/Record.pm line 318
+
+2001-06-03 04:27 ivan
+
+ * FS/FS/Record.pm: track down
+
+ Can't locate object method "setfield" via package "svc_acct_sm"
+ at
+ /usr/local/lib/perl5/site_perl/5.005/FS/Record.pm line 318.
+
+ errors
+
+2001-06-03 03:51 ivan
+
+ * FS/FS/cust_main.pm: fixes "Error reval-ing" and won't bill errors
+
+2001-05-30 08:17 ivan
+
+ * FS/FS/CGI.pm: use Apache inside an eval BLOCK was mucking things
+ up for the non-mod_perl folks
+
+2001-05-30 07:42 ivan
+
+ * htdocs/edit/part_svc.cgi: Adam Rose <adamr@eaze.net>: "In the
+ /edit/part_svc.cgi is there a need to add another section for
+ svc_www?". Yes. Thanks Adam.
+
+2001-05-24 17:36 ivan
+
+ * htdocs/docs/install.html: tyop forgot closing </a>
+
+2001-05-23 07:04 ivan
+
+ * htdocs/docs/admin.html: setting up at least one referral is not
+ optional
+
+2001-05-23 06:47 ivan
+
+ * htdocs/edit/cust_main.cgi: bugfix for defaultcountry
+
+2001-05-22 09:43 ivan
+
+ * FS/FS/svc_domain.pm: oops, s/mx/MX/ noticed by "Shane Chrisp"
+ <shane@2000cn.com.au>, thanks!
+
+2001-05-18 07:08 ivan
+
+ * FS/FS/domain_record.pm: tyop
+
+2001-05-15 00:52 ivan
+
+ * FS/bin/freeside-email: simple program to list all email addresses
+
+2001-05-08 03:44 ivan
+
+ * bin/: svc_acct.export, svc_acct_sm.export: fix for OO Net::SCP
+
+2001-05-07 08:42 ivan
+
+ * FS/FS/Record.pm: tyop
+
+2001-05-07 08:36 ivan
+
+ * FS/FS/Record.pm: start to track down
+
+ Insecure dependency in eval while running with -T switch at
+ /usr/local/lib/site_perl/FS/Record.pm line 202.
+
+ errors
+
+2001-05-07 08:24 ivan
+
+ * bin/svc_acct.import: s/!/*/
+
+2001-05-06 19:07 ivan
+
+ * FS/FS/cust_main.pm, fs_signup/fs_signup_server:
+ http://www.sisd.com/freeside/list-archive/msg01906.html
+
+2001-05-05 01:51 ivan
+
+ * bin/svc_acct.import:
+ http://www.sisd.com/freeside/list-archive/msg01915.html
+
+2001-05-03 03:28 ivan
+
+ * htdocs/docs/: install.html, upgrade6.html: documentation updates
+ for add'l perl dependencies. thanks to "Mike McCauley"
+ <mikem@open.com.au> from Radiator
+
+2001-04-25 19:28 ivan
+
+ * fs_webdemo/registerd.Pg: argh
+
+2001-04-25 19:23 ivan
+
+ * fs_webdemo/registerd.Pg: arfuckingargh
+
+2001-04-25 19:21 ivan
+
+ * fs_webdemo/registerd.Pg: ARG
+
+2001-04-25 19:20 ivan
+
+ * fs_webdemo/registerd.Pg: arg
+
+2001-04-25 19:18 ivan
+
+ * fs_webdemo/registerd.Pg: argh
+
+2001-04-25 17:17 ivan
+
+ * fs_webdemo/: registerd.Pg: sigh
+
+2001-04-24 18:06 ivan
+
+ * htdocs/docs/man/FS/SessionClient.html: missing docs
+
+2001-04-23 12:50 ivan
+
+ * FS/FS/cust_credit.pm: the real
+
+ Can't locate object method "setfield" via package "cust_refund"
+ at /usr/local/lib/site_perl/FS/Record.pm line 315.
+
+ fix
+
+2001-04-23 12:27 ivan
+
+ * FS/FS/cust_credit.pm: *sigh*
+
+2001-04-23 12:21 ivan
+
+ * FS/FS/cust_credit.pm: webdemo bugfix
+
+2001-04-23 09:25 ivan
+
+ * fs_webdemo/registerd.Pg: working registerd.Pg
+
+2001-04-23 09:07 ivan
+
+ * htdocs/search/cust_main.cgi: fix Insecure dependency in eval
+ while running with -T switch at
+ /usr/local/lib/site_perl/FS/Record.pm line 202.
+
+2001-04-23 08:37 ivan
+
+ * FS/MANIFEST: 1.3.1 sigh
+
+2001-04-23 06:09 ivan
+
+ * htdocs/docs/upgrade6.html: hehe, last minute upgrade instruction
+ fixes
+
+2001-04-23 05:44 ivan
+
+ * bin/freeside-session-kill: session killer implemeting timed
+ access
+
+2001-04-23 05:41 ivan
+
+ * htdocs/docs/man/FS/: CGIwrapper.html, SignupClient.html,
+ domain_record.html, nas.html, port.html, prepay_credit.html,
+ session.html, svc_www.html: new API documentation
+
+2001-04-23 05:40 ivan
+
+ * FS/FS.pm, fs_webdemo/registerd.Pg, htdocs/docs/schema.html,
+ htdocs/docs/man/FS.html, htdocs/docs/man/FS/CGI.html,
+ htdocs/docs/man/FS/Conf.html, htdocs/docs/man/FS/Record.html,
+ htdocs/docs/man/FS/UID.html, htdocs/docs/man/FS/agent.html,
+ htdocs/docs/man/FS/agent_type.html,
+ htdocs/docs/man/FS/cust_bill.html,
+ htdocs/docs/man/FS/cust_bill_pkg.html,
+ htdocs/docs/man/FS/cust_credit.html,
+ htdocs/docs/man/FS/cust_main.html,
+ htdocs/docs/man/FS/cust_main_county.html,
+ htdocs/docs/man/FS/cust_main_invoice.html,
+ htdocs/docs/man/FS/cust_pay.html,
+ htdocs/docs/man/FS/cust_pay_batch.html,
+ htdocs/docs/man/FS/cust_pkg.html,
+ htdocs/docs/man/FS/cust_refund.html,
+ htdocs/docs/man/FS/cust_svc.html,
+ htdocs/docs/man/FS/part_pkg.html,
+ htdocs/docs/man/FS/part_referral.html,
+ htdocs/docs/man/FS/part_svc.html,
+ htdocs/docs/man/FS/pkg_svc.html,
+ htdocs/docs/man/FS/svc_Common.html,
+ htdocs/docs/man/FS/svc_acct.html,
+ htdocs/docs/man/FS/svc_acct_pop.html,
+ htdocs/docs/man/FS/svc_acct_sm.html,
+ htdocs/docs/man/FS/svc_domain.html,
+ htdocs/docs/man/FS/type_pkgs.html,
+ htdocs/docs/man/FS/UI/Base.html, htdocs/docs/man/FS/UI/CGI.html,
+ htdocs/docs/man/FS/UI/Gtk.html, htdocs/docs/man/FS/UI/agent.html:
+ documentation and webdemo updates
+
+2001-04-23 02:00 ivan
+
+ * FS/FS/UID.pm: "shouldn't hurt" (famous last words)
+
+2001-04-23 00:12 ivan
+
+ * FS/FS/cust_main.pm, htdocs/edit/svc_domain.cgi,
+ htdocs/edit/process/svc_domain.cgi: better error message (if
+ kludgy) for no referral remove outdated NSI foo from domain
+ ordering. also, fuck NSI.
+
+2001-04-21 18:56 ivan
+
+ * README, FS/FS.pm, FS/MANIFEST, FS/FS/SSH.pm, FS/FS/svc_acct.pm,
+ FS/FS/svc_acct_sm.pm, FS/FS/svc_domain.pm, FS/FS/svc_www.pm,
+ bin/svc_acct.export, bin/svc_acct.import, bin/svc_acct_sm.export,
+ bin/svc_acct_sm.import, bin/svc_domain.import,
+ fs_passwd/fs_passwd_server, fs_signup/fs_signup_server,
+ htdocs/docs/install.html: get rid of FS::SSH.pm (became Net::SSH
+ and Net::SCP on CPAN)
+
+2001-04-21 18:38 ivan
+
+ * TODO, FS/FS/svc_domain.pm, htdocs/search/cust_bill.cgi,
+ htdocs/view/cust_main.cgi: svc_domain needs to import dbh sub
+ from Record view/cust_main.cgi needs to use ->owed method, not
+ check (depriciated) owed field search/cust_bill.cgi redirect
+ error when there's only one invoice
+
+2001-04-21 17:49 ivan
+
+ * FS/FS/svc_Common.pm: need to import dbh sub from Record
+
+2001-04-21 17:45 ivan
+
+ * htdocs/docs/: config.html, install.html: update postgres examples
+
+2001-04-21 16:53 ivan
+
+ * FS/MANIFEST: no more dbdef
+
+2001-04-15 10:35 ivan
+
+ * htdocs/docs/upgrade6.html: dbdef doesn't use mysql-specific
+ syntax
+
+2001-04-15 06:56 ivan
+
+ * TODO, htdocs/docs/session.html: [no log message]
+
+2001-04-15 06:35 ivan
+
+ * FS/FS/: nas.pm, session.pm, svc_Common.pm, svc_domain.pm:
+ transactions part deux
+
+2001-04-15 05:56 ivan
+
+ * TODO, FS/FS/Record.pm, FS/FS/dbdef.pm, FS/FS/dbdef_colgroup.pm,
+ FS/FS/dbdef_column.pm, FS/FS/dbdef_index.pm,
+ FS/FS/dbdef_table.pm, FS/FS/dbdef_unique.pm, bin/dbdef-create,
+ bin/fs-setup: s/dbdef/DBIx::DBSchema/
+
+2001-04-15 05:53 ivan
+
+ * htdocs/docs/install.html: update urls
+
+2001-04-15 05:35 ivan
+
+ * htdocs/: index.html, docs/install.html: documentation updates
+
+2001-04-15 04:25 ivan
+
+ * htdocs/docs/index.html: ui nit
+
+2001-04-15 04:09 ivan
+
+ * htdocs/images/: mid-logo.gif, mid-logo.png, small-logo.gif,
+ small-logo.png: BURN OFF EVERY GIF
+
+2001-04-15 03:33 ivan
+
+ * CREDITS, TODO, htdocs/docs/config.html: better docs for the worst
+ bit, finally
+
+2001-04-15 02:36 ivan
+
+ * bin/fs-setup:
+ http://www.sisd.com/freeside/list-archive/msg01450.html
+
+2001-04-15 00:25 ivan
+
+ * fs_sesmon/FS-SessionClient/cgi/: login.cgi, logout.cgi: oops,
+ extraneous code causing problems, thanks to Mack for bugreport
+
+2001-04-09 16:05 ivan
+
+ * TODO, FS/FS/cust_bill.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_main.pm, FS/FS/cust_pay.pm, FS/FS/cust_pkg.pm,
+ FS/FS/cust_refund.pm, FS/FS/session.pm, FS/FS/svc_Common.pm,
+ bin/fs-setup, htdocs/docs/index.html, htdocs/docs/install.html,
+ htdocs/docs/schema.html, htdocs/docs/upgrade6.html,
+ htdocs/edit/process/part_pkg.cgi,
+ htdocs/misc/cancel-unaudited.cgi: Transactions Part I!!!
+
+2001-04-09 08:50 ivan
+
+ * CREDITS, TODO, FS/MANIFEST: rar
+
+2001-04-02 07:32 ivan
+
+ * htdocs/docs/install.html: changed url over at apache.org
+
+2001-03-30 09:33 ivan
+
+ * FS/FS/cust_bill.pm, htdocs/docs/config.html: config value
+ money_char:
+
+ Presto! Now you can consider all numbers to be
+ shillings.
+
+ If you need to change the currency symbol, you can hunt
+ down the
+ instances of literal '$' in FS::cust_bill::print_text and
+ replace them
+ with your currency symbol. I guess this should turn into
+ a
+ configuration value.
+
+2001-02-26 16:59 ivan
+
+ * FS/FS/session.pm: silly typo, fix sent by Mack <mackn@mackn.net>,
+ thanks!
+
+2001-02-21 15:48 ivan
+
+ * bin/svc_acct.export, htdocs/docs/config.html: add
+ icradius_secrets config file to export to a non-Freeside MySQL
+ database for ICRADIUS
+
+2001-02-20 17:48 ivan
+
+ * FS/bin/freeside-print-batch: stupid pod errors
+
+2001-02-20 17:46 ivan
+
+ * FS/FS/: Bill.pm, Invoice.pm: cruft
+
+2001-02-20 17:45 ivan
+
+ * FS/FS/nas.pm: pod tyop
+
+2001-02-20 17:45 ivan
+
+ * FS/FS/UID.pm: DBI autocommit needs 0, not true string 'false',
+ duh
+
+2001-02-20 08:31 ivan
+
+ * FS/FS/Record.pm: don't use prepare_cached for now
+
+2001-02-13 21:18 ivan
+
+ * README: add devel mailing list
+
+2001-02-13 20:33 ivan
+
+ * FS/FS/port.pm: get rid of gratuitous HISTORY
+
+2001-02-12 22:39 ivan
+
+ * htdocs/docs/schema.html: tyop
+
+2001-02-11 09:34 ivan
+
+ * FS/FS/cust_bill_pkg.pm, htdocs/docs/schema.html: more doc updates
+ from jason
+
+2001-02-11 09:17 ivan
+
+ * CREDITS, FS/FS/cust_bill.pm, FS/FS/cust_credit.pm,
+ FS/FS/cust_pay.pm, FS/FS/cust_refund.pm, htdocs/docs/schema.html:
+ documentation updates from jason
+
+2001-02-07 11:45 ivan
+
+ * htdocs/search/cust_main.cgi: tyop
+
+2001-02-03 06:03 ivan
+
+ * FS/FS/Record.pm, FS/FS/UID.pm, FS/FS/cust_main.pm, bin/fs-setup,
+ bin/generate-prepay, fs_sesmon/fs_session_server,
+ fs_signup/fs_signup_server, htdocs/docs/session.html,
+ htdocs/docs/signup.html, htdocs/docs/upgrade6.html: time-based
+ prepaid cards, session monitor. woop!
+
+2001-01-30 23:21 ivan
+
+ * TODO, FS/FS/cust_main.pm, FS/FS/svc_acct.pm,
+ htdocs/view/svc_acct.cgi: fix tyops
+
+2001-01-30 01:08 ivan
+
+ * FS/FS/port.pm: tyop, thanks to Mack Nagashima <mackn@moaner.org>
+
+2001-01-22 21:03 ivan
+
+ * FS/FS/cust_main.pm: harmless tyop
+
+2001-01-15 01:00 ivan
+
+ * htdocs/docs/install.html: tyop
+
+2000-12-26 15:51 ivan
+
+ * CREDITS, TODO, htdocs/docs/config.html,
+ htdocs/edit/cust_main.cgi: statedefault & referraldefault config
+ files
+
+2000-12-20 21:22 ivan
+
+ * htdocs/edit/process/cust_main_county-expand.cgi: perldoc -f split
+
+2000-12-11 13:57 ivan
+
+ * htdocs/docs/: index.html, overview.dia, overview.png: might as
+ well put this nice picture in the docs
+
+2000-12-10 17:30 ivan
+
+ * TODO: more ancient todo stuff from my inbox
+
+2000-12-10 17:10 ivan
+
+ * TODO: ancient stuff out of my inbox
+
+2000-12-10 13:16 ivan
+
+ * fs_sesmon/FS-SessionClient/fs_sessiond: fix uninitialized value
+ errors
+
+2000-12-08 18:53 ivan
+
+ * fs_sesmon/FS-SessionClient/cgi/login.cgi: layout nicely thanks to
+ matt peterson <matt@peterson.org>
+
+2000-12-08 14:22 ivan
+
+ * FS/FS/session.pm, htdocs/docs/config.html,
+ htdocs/docs/session.html: session callbacks
+
+2000-12-06 02:21 ivan
+
+ * FS/FS/Record.pm: DESTROY sub
+
+2000-12-03 16:13 ivan
+
+ * bin/fs-setup: fix nas.last type
+
+2000-12-03 13:45 ivan
+
+ * fs_sesmon/FS-SessionClient/MANIFEST: tyop
+
+2000-12-03 13:31 ivan
+
+ * htdocs/docs/session.html: directions for webapp session foo
+
+2000-12-03 13:13 ivan
+
+ * fs_sesmon/FS-SessionClient/cgi/: login.cgi, logout.cgi: oops,
+ forgot the web apps
+
+2000-12-03 12:25 ivan
+
+ * TODO, FS/FS/Record.pm, FS/FS/nas.pm, FS/FS/port.pm,
+ FS/FS/session.pm, fs_sesmon/fs_session_server,
+ fs_sesmon/FS-SessionClient/MANIFEST,
+ fs_sesmon/FS-SessionClient/Makefile.PL,
+ fs_sesmon/FS-SessionClient/SessionClient.pm,
+ fs_sesmon/FS-SessionClient/fs_sessiond,
+ fs_sesmon/FS-SessionClient/test.pl,
+ fs_sesmon/FS-SessionClient/bin/freeside-login,
+ fs_sesmon/FS-SessionClient/bin/freeside-logoff,
+ fs_sesmon/FS-SessionClient/bin/freeside-logout,
+ htdocs/browse/nas.cgi, htdocs/view/svc_acct.cgi: session monitor
+ updates
+
+2000-12-03 07:14 ivan
+
+ * CREDITS, FS/FS/cust_bill.pm, bin/svc_acct_sm.import,
+ htdocs/view/svc_domain.cgi: bugfixes from Jeff Finucane
+ <jeff@cmh.net>, thanks!
+
+2000-12-03 06:29 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: template bugfix from
+ Jason Spence <thalakan@frys.com>
+
+2000-12-03 05:45 ivan
+
+ * FS/FS/agent.pm, htdocs/docs/admin.html, htdocs/docs/config.html,
+ htdocs/docs/index.html, htdocs/docs/install.html,
+ htdocs/edit/cust_main.cgi: patch from Jason Spence
+ <thalakan@frys.com>: admin.html doc, autocapgen
+
+2000-12-03 05:44 ivan
+
+ * FS/FS/port.pm, htdocs/index.html, htdocs/browse/nas.cgi:
+ beginnings of web status for session monitor
+
+2000-12-03 02:09 ivan
+
+ * FS/: MANIFEST, FS/CGIwrapper.pm: bad caches!
+
+2000-12-01 14:58 ivan
+
+ * htdocs/docs/session.html: oops
+
+2000-12-01 10:34 ivan
+
+ * bin/fs-setup: another tyop
+
+2000-12-01 10:33 ivan
+
+ * bin/fs-setup: tyop
+
+2000-11-22 15:30 ivan
+
+ * FS/FS/svc_www.pm: tyop
+
+2000-11-07 07:00 ivan
+
+ * FS/MANIFEST, FS/FS/Record.pm, FS/FS/nas.pm, FS/FS/session.pm,
+ bin/fs-setup, fs_sesmon/fs_session_server,
+ fs_sesmon/FS-SessionClient/MANIFEST,
+ fs_sesmon/FS-SessionClient/Makefile.PL,
+ fs_sesmon/FS-SessionClient/SessionClient.pm,
+ fs_sesmon/FS-SessionClient/bin/freeside-login,
+ fs_sesmon/FS-SessionClient/bin/freeside-logoff,
+ htdocs/docs/index.html, htdocs/docs/schema.html: session monitor
+
+2000-10-30 02:47 ivan
+
+ * bin/fs-setup: nas.last can't be defined NULL if indexed
+
+2000-10-27 13:18 ivan
+
+ * FS/FS/: nas.pm, port.pm, session.pm: oops, also necessary for
+ session monitor
+
+2000-10-27 13:15 ivan
+
+ * TODO, FS/FS/Record.pm, bin/fs-setup, eg/table_template.pm,
+ fs_sesmon/fs_session_server, fs_sesmon/FS-SessionClient/Changes,
+ fs_sesmon/FS-SessionClient/MANIFEST,
+ fs_sesmon/FS-SessionClient/MANIFEST.SKIP,
+ fs_sesmon/FS-SessionClient/Makefile.PL,
+ fs_sesmon/FS-SessionClient/SessionClient.pm,
+ fs_sesmon/FS-SessionClient/fs_sessiond,
+ fs_sesmon/FS-SessionClient/test.pl: session monitor
+
+2000-10-16 06:26 ivan
+
+ * htdocs/index.html: fix typo
+
+2000-10-15 05:58 ivan
+
+ * TODO: roo
+
+2000-10-11 17:44 ivan
+
+ * README: rawr!
+
+2000-09-20 03:35 ivan
+
+ * FS/FS/cust_bill.pm: since printed field isn't updated 'till after
+ print_text method is called, want to print overdue invoices if
+ printed > 0, not > 1
+
+2000-08-24 00:26 ivan
+
+ * TODO, fs_signup/FS-SignupClient/cgi/signup.cgi: untaint template
+ source
+
+2000-08-09 11:40 ivan
+
+ * conf/invoice_template: example invoice template
+
+2000-08-09 11:21 ivan
+
+ * htdocs/docs/: install.html, upgrade6.html: doc updates
+
+2000-08-09 04:30 ivan
+
+ * TODO, FS/FS/cust_bill.pm, htdocs/docs/billing.html,
+ htdocs/docs/config.html: templatable invoices
+
+2000-07-18 09:15 ivan
+
+ * htdocs/docs/overview.dia: dia source
+
+2000-07-17 10:59 ivan
+
+ * htdocs/misc/process/link.cgi: oops
+
+2000-07-17 09:45 ivan
+
+ * htdocs/: index.html, search/cust_bill.cgi, search/cust_main.cgi,
+ search/cust_pkg.cgi: first shot at invoice browsing and some
+ other cleanups
+
+2000-07-17 06:51 ivan
+
+ * FS/FS/svc_acct.pm: silly mistake
+
+2000-07-17 05:49 ivan
+
+ * htdocs/search/cust_pkg.cgi: better error message if a package
+ isn't linked to a customer (that shouldn't happen)
+
+2000-07-17 03:58 ivan
+
+ * htdocs/view/svc_acct_sm.cgi: better error messages if svc_acct or
+ svc_domain records are missing
+
+2000-07-17 03:53 ivan
+
+ * FS/FS/svc_acct.pm: prevent accounts which are the target of mail
+ aliases from being deleted
+
+2000-07-17 03:37 ivan
+
+ * FS/FS/svc_acct.pm: make remote commands configurable
+
+2000-07-17 03:36 ivan
+
+ * CREDITS: rawr!
+
+2000-07-17 03:36 ivan
+
+ * htdocs/docs/: config.html, export.html: documentation updates
+
+2000-07-06 21:05 ivan
+
+ * fs_passwd/fs_passwd_server, fs_signup/fs_signup_server: wait()ing
+ on SIGCHLD causing hangs for some folks
+
+2000-07-06 06:56 ivan
+
+ * FS/FS/svc_acct.pm: mis-PODed =back should have been a =cut in
+ conjunction with AUTOLOAD this was sure a pain to find
+
+2000-07-06 06:23 ivan
+
+ * bin/svc_acct.export: tyop
+
+2000-07-06 06:19 ivan
+
+ * bin/: fs-radius-add-check, fs-radius-add-reply: remove duplicate
+ sql statement causing spurious errors
+
+2000-07-06 01:57 ivan
+
+ * TODO, FS/FS/svc_acct.pm, bin/fs-radius-add,
+ bin/fs-radius-add-check, bin/fs-radius-add-reply, bin/fs-setup,
+ bin/svc_acct.export, htdocs/docs/export.html: support for radius
+ check attributes (except importing). poorly documented.
+
+2000-07-05 20:37 ivan
+
+ * bin/svc_acct_sm.export: don't error out on invalid
+ svc_acct_sm.domuid's that can't be matched in svc_acct.uid - just
+ warn.
+
+2000-07-04 06:42 ivan
+
+ * FS/FS/svc_acct.pm: noted a API inconsistancy
+
+2000-07-03 02:13 ivan
+
+ * bin/svc_acct_sm.export: get rid of double sendmailrestart
+ invocation; no need for multiple sessions
+
+2000-07-03 02:09 ivan
+
+ * bin/svc_acct_sm.export: typo
+
+2000-07-03 02:03 ivan
+
+ * TODO, bin/svc_acct_sm.export, htdocs/docs/config.html: added
+ sendmailrestart and sendmailconfigpath config files
+
+2000-06-30 03:37 ivan
+
+ * FS/FS/svc_acct_sm.pm: maildisablecatchall configuration file
+
+2000-06-30 03:19 ivan
+
+ * htdocs/docs/config.html: maildisablecatchall config file
+
+2000-06-29 08:01 ivan
+
+ * bin/svc_acct.export: another silly typo in svc_acct.export
+
+2000-06-29 07:02 ivan
+
+ * bin/svc_acct_sm.export, htdocs/docs/config.html: add
+ sendmailrestart configuration file
+
+2000-06-29 05:27 ivan
+
+ * bin/svc_acct.import: s/password/_password/ for PostgreSQL wasn't
+ done in the import.
+
+2000-06-29 05:00 ivan
+
+ * bin/fs-setup, htdocs/docs/upgrade6.html: support for
+ pre-encrypted md5 passwords.
+
+2000-06-29 04:56 ivan
+
+ * FS/FS/svc_acct.pm: md5 passwords can are 34 characters long and
+ have $ in them.
+
+2000-06-29 04:12 ivan
+
+ * FS/FS/svc_domain.pm: don't block on $whois_hack trueness when
+ adding new domains.
+
+2000-06-29 03:51 ivan
+
+ * bin/svc_acct_sm.import: oops, silly mistake
+
+2000-06-29 03:48 ivan
+
+ * bin/svc_acct_sm.import: make svc_acct_sm skip blank lines in
+ sendmail import
+
+2000-06-28 05:54 ivan
+
+ * FS/FS/svc_acct.pm: superfluous my()
+
+2000-06-28 05:52 ivan
+
+ * FS/FS/svc_acct.pm: bugfix to accept shells that evaluate to false
+ in perl, like the empty string.
+
+2000-06-28 05:37 ivan
+
+ * bin/svc_acct.export, htdocs/docs/config.html: add support for
+ config option textradiusprepend
+
+2000-06-28 05:32 ivan
+
+ * bin/svc_acct.import: allow RADIUS lines with "Auth-Type = Local"
+ too
+
+2000-06-28 05:03 ivan
+
+ * bin/svc_acct.import: make svc_acct more forgiving about RADIUS
+ users files
+
+2000-06-28 03:51 ivan
+
+ * bin/fs-radius-add: forgot to import a sub
+
+2000-06-28 03:48 ivan
+
+ * bin/fs-radius-add: quick hack to add RADIUS attributes
+
+2000-06-28 03:38 ivan
+
+ * htdocs/docs/upgrade6.html: documentation oops
+
+2000-06-27 05:15 ivan
+
+ * TODO, htdocs/docs/config.html, htdocs/edit/cust_main.cgi: i18n
+
+2000-06-27 05:15 ivan
+
+ * FS/FS/: Record.pm, cust_main.pm: i18
+
+2000-06-27 04:29 ivan
+
+ * FS/FS/Record.pm: fix typo in last patch, and another gratuitous
+ -w pleaser
+
+2000-06-27 04:27 ivan
+
+ * FS/FS/Record.pm: logically identical, but -w safe
+
+2000-06-23 17:28 ivan
+
+ * FS/: FS/cust_main.pm, bin/freeside-bill: don't use Date::Manip;
+ report correct program name in freeside-bill usage msg
+
+2000-06-23 05:25 ivan
+
+ * CREDITS, TODO, FS/FS/Record.pm, FS/FS/UID.pm: FS::Record::qsearch
+ - more portable, doesn't depend on $sth->execute returning a
+ number of rows, uses placeholders and prepare_cached
+
+2000-06-22 03:52 ivan
+
+ * FS/bin/freeside-bill: tyop
+
+2000-06-20 00:57 ivan
+
+ * htdocs/docs/: index.html, upgrade5.html, upgrade6.html:
+ documentation update for 1.2.4 release
+
+2000-06-20 00:13 ivan
+
+ * FS/FS/cust_main_invoice.pm: documentation update
+
+2000-06-17 14:48 ivan
+
+ * FS/FS/cust_pay_batch.pm: fix typo in error message
+
+2000-06-15 07:45 ivan
+
+ * CREDITS, TODO: text updates
+
+2000-06-15 07:07 ivan
+
+ * bin/svc_acct.export: added ICRADIUS radreply table support,
+ courtesy of Kenny Elliott
+
+2000-06-15 07:03 ivan
+
+ * htdocs/docs/install.html: change SSH link from ftp.cs.hut.fi
+ (F-Secure) to www.openssh.com
+
+2000-06-15 06:35 ivan
+
+ * FS/FS/svc_acct.pm: add radius method
+
+2000-06-15 05:38 ivan
+
+ * FS/FS/cust_main.pm: fix for ncancelled_pkgs - when called in
+ scalar context, was only returning second item
+
+2000-06-15 05:30 ivan
+
+ * htdocs/misc/cancel-unaudited.cgi: bugfix from Jeff Finucane,
+ thanks!
+
+2000-06-15 04:10 ivan
+
+ * htdocs/edit/part_svc.cgi: update to the inline documentation,
+ hopefully will make things more clear
+
+2000-06-14 05:24 ivan
+
+ * htdocs/docs/install.html: documentation updates for mysql
+ privledges
+
+2000-06-14 04:51 ivan
+
+ * htdocs/docs/install.html: update link for mysql database
+ creation. i sure wish they'd stop changing these all the time
+
+2000-06-13 20:41 ivan
+
+ * htdocs/docs/billing.html: no longer need to modify Bill.pm to
+ enable real-time credit card processing
+
+2000-06-12 01:37 ivan
+
+ * bin/svc_acct_sm.export: sendmail fix from Jeff Finucane
+
+2000-05-13 14:57 ivan
+
+ * TODO, FS/bin/freeside-print-batch, htdocs/docs/billing.html: add
+ print_batch script from Joel Griffiths
+
+2000-05-13 14:50 ivan
+
+ * FS/FS/: CGI.pm, UID.pm: cgisuidsetup takes an Apache object as
+ well as a CGI object now.
+
+2000-05-13 14:42 ivan
+
+ * CREDITS: add kristian, update joel's entry
+
+2000-05-10 17:04 ivan
+
+ * htdocs/docs/signup.html: Netscape CCK docuementation
+
+2000-05-10 16:57 ivan
+
+ * fs_signup/: cck.template, FS-SignupClient/cgi/signup.cgi:
+ Netscape CCK autoconfiguration support
+
+2000-04-10 17:06 ivan
+
+ * FS/FS/CGI.pm: CGI.pm detects mod_perl and calls appropriate exit
+ (Registry's override doesn't work here)
+
+2000-04-02 19:32 ivan
+
+ * FS/bin/freeside-bill: accept anything in ARGV for -d Date::Parse
+
+2000-03-06 08:38 ivan
+
+ * FS/FS/svc_acct.pm: better error message. bah.
+
+2000-03-06 08:00 ivan
+
+ * bin/svc_acct.export: sync up with working versoin
+
+2000-03-06 07:59 ivan
+
+ * bin/svc_acct.export: finally get MySQL locking working for
+ ICRADIUS export
+
+2000-03-06 07:15 ivan
+
+ * FS/FS/SSH.pm: backout silly change
+
+2000-03-06 07:04 ivan
+
+ * FS/FS/SSH.pm: bug in IPC::Open3 documentation?
+
+2000-03-06 06:59 ivan
+
+ * bin/svc_acct.export: s/sshopen2/sshopen3/ to prevent spurious
+ mysql "Enter password: " dialog from showing up in cron/terminal
+
+2000-03-06 06:51 ivan
+
+ * bin/svc_acct.export: eek
+
+2000-03-06 06:50 ivan
+
+ * bin/svc_acct.export: oop
+
+2000-03-06 06:48 ivan
+
+ * bin/svc_acct.export: s/icradiusmachine/machine/
+
+2000-03-06 06:46 ivan
+
+ * bin/svc_acct.export: not setuid or run by malicious user - no -T
+ necessary
+
+2000-03-06 06:19 ivan
+
+ * bin/svc_acct.export, htdocs/docs/config.html: ICRADIUS export
+ bugfix
+
+2000-03-06 06:12 ivan
+
+ * TODO, bin/svc_acct.export, htdocs/docs/config.html,
+ htdocs/docs/export.html: ICRADIUS export support
+
+2000-03-04 21:03 ivan
+
+ * htdocs/docs/signup.html: link to SISD site for
+ HTTP::Headers::UserAgent instead of CPAN
+
+2000-03-03 10:45 ivan
+
+ * FS/FS/CGI.pm: use Apache::exit instead of exit in &eidiot -
+ Registry wasn't overriding exit in modules
+
+2000-03-03 10:22 ivan
+
+ * fs_webdemo/register.cgi, htdocs/docs/index.html,
+ htdocs/docs/upgrade5.html, htdocs/docs/man/FS.html,
+ htdocs/docs/man/FS/Bill.html, htdocs/docs/man/FS/CGI.html,
+ htdocs/docs/man/FS/Conf.html, htdocs/docs/man/FS/Invoice.html,
+ htdocs/docs/man/FS/Record.html, htdocs/docs/man/FS/SSH.html,
+ htdocs/docs/man/FS/UID.html, htdocs/docs/man/FS/agent.html,
+ htdocs/docs/man/FS/agent_type.html,
+ htdocs/docs/man/FS/cust_bill.html,
+ htdocs/docs/man/FS/cust_bill_pkg.html,
+ htdocs/docs/man/FS/cust_credit.html,
+ htdocs/docs/man/FS/cust_main.html,
+ htdocs/docs/man/FS/cust_main_county.html,
+ htdocs/docs/man/FS/cust_main_invoice.html,
+ htdocs/docs/man/FS/cust_pay.html,
+ htdocs/docs/man/FS/cust_pay_batch.html,
+ htdocs/docs/man/FS/cust_pkg.html,
+ htdocs/docs/man/FS/cust_refund.html,
+ htdocs/docs/man/FS/cust_svc.html, htdocs/docs/man/FS/dbdef.html,
+ htdocs/docs/man/FS/dbdef_colgroup.html,
+ htdocs/docs/man/FS/dbdef_column.html,
+ htdocs/docs/man/FS/dbdef_index.html,
+ htdocs/docs/man/FS/dbdef_table.html,
+ htdocs/docs/man/FS/dbdef_unique.html,
+ htdocs/docs/man/FS/part_pkg.html,
+ htdocs/docs/man/FS/part_referral.html,
+ htdocs/docs/man/FS/part_svc.html,
+ htdocs/docs/man/FS/pkg_svc.html,
+ htdocs/docs/man/FS/svc_Common.html,
+ htdocs/docs/man/FS/svc_acct.html,
+ htdocs/docs/man/FS/svc_acct_pop.html,
+ htdocs/docs/man/FS/svc_acct_sm.html,
+ htdocs/docs/man/FS/svc_domain.html,
+ htdocs/docs/man/FS/type_pkgs.html,
+ htdocs/docs/man/FS/UI/Base.html, htdocs/docs/man/FS/UI/CGI.html,
+ htdocs/docs/man/FS/UI/Gtk.html, htdocs/search/svc_domain.cgi:
+ changes from 1.2.3 release, fixes from webdemo
+
+2000-03-03 10:21 ivan
+
+ * FS/FS/Record.pm: changes backported from 1.2.3 release, bugfix
+ from web demo
+
+2000-03-03 04:27 ivan
+
+ * fs_webdemo/registerd: silly typo
+
+2000-03-02 22:36 ivan
+
+ * fs_webdemo/registerd: [no log message]
+
+2000-03-02 22:28 ivan
+
+ * fs_webdemo/registerd: kludge but effective
+
+2000-03-02 22:10 ivan
+
+ * fs_webdemo/registerd: [no log message]
+
+2000-03-02 22:03 ivan
+
+ * fs_webdemo/registerd: [no log message]
+
+2000-03-02 21:47 ivan
+
+ * fs_webdemo/registerd: [no log message]
+
+2000-03-02 21:32 ivan
+
+ * fs_webdemo/register.cgi: fix silly syntax errors
+
+2000-03-02 21:29 ivan
+
+ * fs_webdemo/: register.cgi, registerd: first pass at separate
+ registerd process
+
+2000-03-02 00:09 ivan
+
+ * htdocs/edit/cust_main.cgi: still need to allow blank expiration
+ dates
+
+2000-03-01 23:44 ivan
+
+ * bin/fs-setup: typo forgot closing '
+
+2000-03-01 00:22 ivan
+
+ * fs_webdemo/: register.html: [no log message]
+
+2000-03-01 00:19 ivan
+
+ * fs_webdemo/register.html: x
+
+2000-03-01 00:15 ivan
+
+ * fs_webdemo/: register.cgi, register.html, registerd: queuing
+ webdemo registration
+
+2000-03-01 00:14 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: cvs cruft
+
+2000-03-01 00:13 ivan
+
+ * FS/: MANIFEST, FS/svc_domain.pm, FS/svc_www.pm: compilation
+ bugfixes
+
+2000-02-24 03:08 ivan
+
+ * fs_webdemo/register.cgi: initial checkin
+
+2000-02-02 21:16 ivan
+
+ * FS/FS/cust_pkg.pm, FS/FS/domain_record.pm, FS/FS/svc_domain.pm,
+ FS/FS/svc_www.pm, bin/fs-setup, bin/svc_acct.import,
+ bin/svc_acct_sm.import, htdocs/docs/config.html,
+ htdocs/docs/install.html, htdocs/docs/schema.html,
+ htdocs/docs/upgrade5.html, bin/svc_domain.import: beginning of
+ DNS and Apache support
+
+2000-02-02 12:22 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/prepay_credit.pm, bin/generate-prepay,
+ fs_signup/fs_signup_server, htdocs/docs/signup.html: bugfix
+ prepayment in signup server
+
+2000-02-01 23:44 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/SignupClient.pm,
+ FS-SignupClient/cgi/signup.cgi: fix some bugs in signup server
+
+2000-01-30 21:22 ivan
+
+ * FS/FS/cust_main.pm, FS/FS/prepay_credit.pm, bin/fs-setup,
+ fs_signup/FS-SignupClient/cgi/signup.cgi,
+ htdocs/docs/schema.html, htdocs/docs/signup.html,
+ htdocs/docs/upgrade5.html: prepaid "internet cards"
+
+2000-01-30 00:18 ivan
+
+ * CREDITS: [no log message]
+
+2000-01-29 22:54 ivan
+
+ * htdocs/edit/cust_main.cgi: credit card expiration dates not
+ sticky bug fixed?
+
+2000-01-29 22:11 ivan
+
+ * TODO: [no log message]
+
+2000-01-29 22:03 ivan
+
+ * bin/fs-setup, htdocs/docs/install.html: postgres 6.5 finally
+ supports decimal(10,2)
+
+2000-01-29 13:10 ivan
+
+ * FS/FS/svc_domain.pm: doc update
+
+2000-01-28 15:02 ivan
+
+ * htdocs/edit/svc_acct_pop.cgi: track full phone number
+
+2000-01-28 14:53 ivan
+
+ * bin/fs-setup, FS/FS/svc_acct_pop.pm,
+ htdocs/browse/svc_acct_pop.cgi: track full phone number
+
+2000-01-28 14:51 ivan
+
+ * htdocs/docs/: index.html, schema.html, signup.html,
+ upgrade5.html: add signup server documentation, track full phone
+ number
+
+2000-01-28 14:49 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: proper IEAK stuff
+
+2000-01-28 14:48 ivan
+
+ * fs_signup/ieak.template: example template
+
+2000-01-28 14:48 ivan
+
+ * fs_signup/: fs_signup_server, FS-SignupClient/SignupClient.pm,
+ FS-SignupClient/fs_signupd: full phone number
+
+2000-01-28 14:47 ivan
+
+ * fs_signup/README: wrote real documentation
+
+2000-01-26 16:53 ivan
+
+ * htdocs/edit/cust_main.cgi: 5.004_04 workaround
+
+2000-01-26 16:37 ivan
+
+ * README: ack
+
+2000-01-26 16:27 ivan
+
+ * TODO: update TODO
+
+1999-12-17 04:03 ivan
+
+ * fs_signup/FS-SignupClient/cgi/signup.cgi: beginning of IEAK
+ support
+
+1999-12-16 18:33 ivan
+
+ * htdocs/edit/cust_main.cgi: argh
+
+1999-11-08 13:38 ivan
+
+ * FS/FS/cust_pkg.pm: remove services using pkg_svc table now, oops!
+
+1999-10-04 01:23 ivan
+
+ * FS/bin/freeside-bill: silly 'use of unitialized value' errors
+
+1999-09-22 15:06 ivan
+
+ * TODO: ya todo update
+
+1999-08-27 15:18 ivan
+
+ * htdocs/view/svc_domain.cgi: point to patrick instead of internic!
+
+1999-08-26 23:25 ivan
+
+ * TODO: [no log message]
+
+1999-08-26 17:26 ivan
+
+ * htdocs/edit/process/svc_acct.cgi: better error messages
+
+1999-08-24 00:56 ivan
+
+ * fs_signup/FS-SignupClient/SignupClient.pm: forgot this file!
+
+1999-08-24 00:40 ivan
+
+ * fs_signup/: README, Signup.pm, fs_signup_server, fs_signupd,
+ FS-SignupClient/Changes, FS-SignupClient/MANIFEST,
+ FS-SignupClient/MANIFEST.SKIP, FS-SignupClient/Makefile.PL,
+ FS-SignupClient/fs_signupd, FS-SignupClient/test.pl,
+ FS-SignupClient/cgi/signup.cgi: initial checkin of signup server
+
+1999-08-23 05:26 ivan
+
+ * test/cgi-test: need to untaint the command line
+
+1999-08-23 00:40 ivan
+
+ * htdocs/edit/cust_main.cgi: missing </TD> flag
+
+1999-08-23 00:08 ivan
+
+ * htdocs/edit/cust_main.cgi: no CGI::Switch for now
+
+1999-08-20 19:14 ivan
+
+ * htdocs/edit/cust_main.cgi: better error message for no agents
+
+1999-08-20 01:27 ivan
+
+ * README, FS/FS/part_pkg.pm: fix for bug noticed by Martin G.
+ Bayerle:
+ > if you eliminate services from any package, to reduce it to
+ only one service,
+ > once gone, they won't reappear.
+
+1999-08-11 21:45 ivan
+
+ * htdocs/search/cust_main.cgi: typo - missed a paren
+
+1999-08-11 21:32 ivan
+
+ * htdocs/: misc/bill.cgi, search/cust_main.cgi:
+ hidecancelledcustomers
+
+1999-08-11 21:16 ivan
+
+ * FS/FS/cust_main.pm, htdocs/docs/config.html,
+ htdocs/view/cust_main.cgi: hidecancelledpackages config option
+
+1999-08-11 17:05 ivan
+
+ * FS/FS/svc_acct.pm, htdocs/docs/config.html: configurable min/max
+ username length, min password length, periods in usernames
+
+1999-08-11 13:57 ivan
+
+ * htdocs/docs/billing.html: [no log message]
+
+1999-08-11 13:51 ivan
+
+ * FS/bin/freeside-bill: [no log message]
+
+1999-08-11 13:41 ivan
+
+ * FS/MANIFEST, FS/Makefile.PL, FS/FS/svc_domain.pm,
+ FS/bin/freeside-bill, bin/bill: new bill script,
+
+1999-08-11 08:38 ivan
+
+ * htdocs/edit/cust_main.cgi: fix for perl 5.004_04
+
+1999-08-11 07:42 ivan
+
+ * bin/backup-freeside, htdocs/docs/install.html: [no log message]
+
+1999-08-11 06:54 ivan
+
+ * htdocs/docs/: install.html, upgrade4.html: documentation updates
+
+1999-08-11 06:13 ivan
+
+ * htdocs/docs/Net-Whois-0.23-ivan1.patch: no longer needed,
+ Net::Whois v1.001 released
+
+1999-08-11 06:12 ivan
+
+ * FS/FS/svc_domain.pm: require a working Net::Whois version
+
+1999-08-10 05:55 ivan
+
+ * fs_signup/: fs_signup_server, fs_signupd: ready for testing
+
+1999-08-10 05:54 ivan
+
+ * htdocs/edit/process/cust_main.cgi: use FS::cust_pkg::pkgpart_href
+
+1999-08-10 05:06 ivan
+
+ * fs_passwd/fs_passwdd: even though you should probably set this
+ for your installation
+
+1999-08-10 04:15 ivan
+
+ * htdocs/edit/cust_main.cgi: corrected a misleading comment
+
+1999-08-05 00:19 ivan
+
+ * htdocs/docs/: install.html, trouble.html: minor documentation
+ update
+
+1999-08-04 05:42 ivan
+
+ * bin/pod2x: new, kludgy-but-working html generator
+
+1999-08-04 05:41 ivan
+
+ * FS/FS.pm: pod fix
+
+1999-08-04 05:39 ivan
+
+ * htdocs/docs/Net-Whois-0.23-ivan1.patch: hopefully not necessary
+ soon
+
+1999-08-04 05:26 ivan
+
+ * htdocs/docs/: install.html, upgrade4.html: updated
+ install/upgrade instructions for new perl module stuff
+
+1999-08-04 05:13 ivan
+
+ * htdocs/docs/man/: Bill.txt, CGI.txt, Conf.txt, FS.html,
+ Invoice.txt, Record.txt, SSH.txt, UID.txt, agent.txt,
+ agent_type.txt, cust_bill.txt, cust_bill_pkg.txt,
+ cust_credit.txt, cust_main.txt, cust_main_county.txt,
+ cust_main_invoice.txt, cust_pay.txt, cust_pay_batch.txt,
+ cust_pkg.txt, cust_refund.txt, cust_svc.txt, dbdef.txt,
+ dbdef_colgroup.txt, dbdef_column.txt, dbdef_index.txt,
+ dbdef_table.txt, dbdef_unique.txt, index.html, part_pkg.txt,
+ part_referral.txt, part_svc.txt, pkg_svc.txt, svc_Common.txt,
+ svc_acct.txt, svc_acct_pop.txt, svc_acct_sm.txt, svc_domain.txt,
+ type_pkgs.txt, FS/Bill.html, FS/CGI.html, FS/Conf.html,
+ FS/Invoice.html, FS/Record.html, FS/SSH.html, FS/UID.html,
+ FS/agent.html, FS/agent_type.html, FS/cust_bill.html,
+ FS/cust_bill_pkg.html, FS/cust_credit.html, FS/cust_main.html,
+ FS/cust_main_county.html, FS/cust_main_invoice.html,
+ FS/cust_pay.html, FS/cust_pay_batch.html, FS/cust_pkg.html,
+ FS/cust_refund.html, FS/cust_svc.html, FS/dbdef.html,
+ FS/dbdef_colgroup.html, FS/dbdef_column.html,
+ FS/dbdef_index.html, FS/dbdef_table.html, FS/dbdef_unique.html,
+ FS/part_pkg.html, FS/part_referral.html, FS/part_svc.html,
+ FS/pkg_svc.html, FS/svc_Common.html, FS/svc_acct.html,
+ FS/svc_acct_pop.html, FS/svc_acct_sm.html, FS/svc_domain.html,
+ FS/type_pkgs.html, FS/UI/Base.html, FS/UI/CGI.html,
+ FS/UI/Gtk.html, FS/UI/agent.html: new HTML manpages
+
+1999-08-04 05:12 ivan
+
+ * htdocs/docs/index.html: correct link to new html documentation
+
+1999-08-04 04:50 ivan
+
+ * FS/FS/cust_pkg.pm: pod syntax
+
+1999-08-04 03:41 ivan
+
+ * FS/FS/Record.pm: some pod syntax update to generate nicer html
+ docs
+
+1999-08-04 02:03 ivan
+
+ * FS/: MANIFEST, MANIFEST.SKIP, README, FS/Bill.pm, FS/CGI.pm,
+ FS/Conf.pm, FS/Invoice.pm, FS/Record.pm, FS/SSH.pm, FS/UID.pm,
+ FS/agent.pm, FS/agent_type.pm, FS/cust_bill.pm,
+ FS/cust_bill_pkg.pm, FS/cust_credit.pm, FS/cust_main.pm,
+ FS/cust_main_county.pm, FS/cust_main_invoice.pm, FS/cust_pay.pm,
+ FS/cust_pay_batch.pm, FS/cust_pkg.pm, FS/cust_refund.pm,
+ FS/cust_svc.pm, FS/dbdef.pm, FS/dbdef_colgroup.pm,
+ FS/dbdef_column.pm, FS/dbdef_index.pm, FS/dbdef_table.pm,
+ FS/dbdef_unique.pm, FS/part_pkg.pm, FS/part_referral.pm,
+ FS/part_svc.pm, FS/pkg_svc.pm, FS/svc_Common.pm, FS/svc_acct.pm,
+ FS/svc_acct_pop.pm, FS/svc_acct_sm.pm, FS/svc_domain.pm,
+ FS/type_pkgs.pm, FS/UI/Base.pm, FS/UI/CGI.pm, FS/UI/Gtk.pm,
+ FS/UI/agent.pm: initial checkin of module files for proper perl
+ installation
+
+1999-08-04 01:03 ivan
+
+ * eg/: table_template-svc.pm, table_template.pm: move table
+ subclass examples out of production directory
+
+1999-08-04 01:00 ivan
+
+ * site_perl/UI/: Base.pm, CGI.pm, Gtk.pm, agent.pm: move to perl
+ installation directory
+
+1999-08-04 00:38 ivan
+
+ * site_perl/: Bill.pm, CGI.pm, Conf.pm, Invoice.pm, Record.pm,
+ SSH.pm, UID.pm, agent.pm, agent_type.pm, cust_bill.pm,
+ cust_bill_pkg.pm, cust_credit.pm, cust_main.pm,
+ cust_main_county.pm, cust_main_invoice.pm, cust_pay.pm,
+ cust_pay_batch.pm, cust_pkg.pm, cust_refund.pm, cust_svc.pm,
+ dbdef.pm, dbdef_colgroup.pm, dbdef_column.pm, dbdef_index.pm,
+ dbdef_table.pm, dbdef_unique.pm, part_pkg.pm, part_referral.pm,
+ part_svc.pm, pkg_svc.pm, svc_Common.pm, svc_acct.pm,
+ svc_acct_pop.pm, svc_acct_sm.pm, svc_domain.pm,
+ table_template-svc.pm, table_template.pm, type_pkgs.pm: move to
+ FS directory: proper Perl module installation has arrived!
+
+1999-08-04 00:34 ivan
+
+ * FS/FS.pm: initial FS manpage
+
+1999-08-03 21:15 ivan
+
+ * FS/: Changes, FS.pm, MANIFEST, Makefile.PL, test.pl: initial h2xs
+
+1999-08-03 00:43 ivan
+
+ * TODO, htdocs/docs/install.html, site_perl/svc_domain.pm: use
+ Net::Whois;
+
+1999-07-29 12:10 ivan
+
+ * fs_signup/fs_signup_server, TODO: [no log message]
+
+1999-07-29 02:07 ivan
+
+ * site_perl/cust_pay.pm: embarassing.
+
+1999-07-29 01:58 ivan
+
+ * htdocs/docs/: index.html, upgrade4.html: upgrade info for 1.2.2
+
+1999-07-29 01:50 ivan
+
+ * bin/fs-setup: wrong type for cust_pay_batch.exp
+
+1999-07-29 01:47 ivan
+
+ * site_perl/svc_acct.pm: more informative illegal shells error.
+
+1999-07-29 00:49 ivan
+
+ * site_perl/cust_pay_batch.pm: fixes for bugs noticed by Joel
+ Griffiths <griff@aver-computer.com>
+
+1999-07-21 00:34 ivan
+
+ * htdocs/edit/cust_pkg.cgi: links to package browse and agent type
+ edit if there aren't any packages to order. thanks to "Tech
+ Account" <techy@orac.hq.org>
+
+1999-07-20 23:32 ivan
+
+ * site_perl/agent_type.pm: workaround for syntax not compatible
+ w/5.004_04 (ok in 5.004_05)
+
+1999-07-20 12:18 ivan
+
+ * fs_signup/: Signup.pm, fs_signup_server, fs_signupd: initial
+ checkin
+
+1999-07-20 03:37 ivan
+
+ * htdocs/edit/cust_main.cgi, site_perl/agent.pm,
+ site_perl/agent_type.pm, site_perl/cust_main.pm,
+ site_perl/cust_main_county.pm, site_perl/cust_pkg.pm,
+ site_perl/part_pkg.pm, site_perl/pkg_svc.pm: cleaned up the new
+ one-screen signup bits in htdocs/edit/cust_main.cgi to prepare
+ for a signup server
+
+1999-07-19 23:24 ivan
+
+ * htdocs/docs/schema.html: oops, forgot cust_main.fax
+
+1999-07-19 23:03 ivan
+
+ * htdocs/search/svc_acct_sm.cgi: s/CGI::Request/CGI/; (how'd i miss
+ that before?)
+
+1999-07-19 23:01 ivan
+
+ * site_perl/dbdef_colgroup.pm: harmless since Exporter was used
+ anyway, but...
+
+1999-07-17 15:02 ivan
+
+ * site_perl/cust_pay_batch.pm: another bug noticed by Steve Gertz
+ <sglist@hollywood.mwis.net>
+
+1999-07-17 03:38 ivan
+
+ * htdocs/search/: cust_main.cgi, cust_pkg.cgi, svc_domain.cgi:
+ scott nelson <scott@ultimanet.com> noticed this
+ mod_perl-triggered bug and gave me a great bugreport at the last
+ rhythmethod
+
+1999-07-16 23:01 ivan
+
+ * htdocs/docs/install.html: perl dependency documentation update
+ from dk smith <dks@spies.com>
+
+1999-07-16 19:24 ivan
+
+ * site_perl/cust_main.pm: bug noticed by Steve Gertz
+ <sglist@hollywood.mwis.net>
+
+1999-07-16 18:34 ivan
+
+ * site_perl/Record.pm: s/croak/confess/; in check method
+
+1999-07-15 17:20 ivan
+
+ * TODO: [no log message]
+
+1999-07-15 16:50 ivan
+
+ * TODO: [no log message]
+
+1999-07-08 04:40 ivan
+
+ * CREDITS, README, TODO: [no log message]
+
+1999-07-07 19:32 ivan
+
+ * bin/svc_acct.import: import fix, noticed by Ben Leibig and Joel
+ Griffiths
+
+1999-07-07 18:49 ivan
+
+ * CREDITS: add joel
+
+1999-07-07 18:49 ivan
+
+ * bin/svc_acct.import: updates to avoid -w warnings from Joel
+ Griffiths <griff@aver-computer.com>
+
+1999-07-07 18:02 ivan
+
+ * TODO: [no log message]
+
+1999-05-12 01:29 ivan
+
+ * htdocs/docs/install.html: don't use threaded or unsupported perl
+ versions
+
+1999-05-11 03:09 ivan
+
+ * site_perl/Conf.pm: try to diagnose strange multiple-line problem
+
+1999-04-29 02:37 ivan
+
+ * TODO: [no log message]
+
+1999-04-29 02:00 ivan
+
+ * htdocs/docs/upgrade3.html: aixelsyd
+
+1999-04-19 03:32 ivan
+
+ * etc/megapop.pl: if you are a megapop customer...
+
+1999-04-18 02:27 ivan
+
+ * htdocs/docs/install.html: out-dated links, fix from "Greg
+ Kuhnert" <gregk@no1.com.au>
+
+1999-04-15 15:46 ivan
+
+ * bin/fs-setup: TT isn't a state!
+
+1999-04-15 09:44 ivan
+
+ * htdocs/docs/config.html, htdocs/misc/delete-customer.cgi,
+ htdocs/misc/process/delete-customer.cgi,
+ htdocs/view/cust_main.cgi, site_perl/cust_main.pm: delete
+ customers
+
+1999-04-15 08:22 ivan
+
+ * site_perl/CGI.pm: make &idiot() work, yuck.
+
+1999-04-15 07:09 ivan
+
+ * htdocs/misc/process/link.cgi: get rid of top-level my() variables
+
+1999-04-15 06:39 ivan
+
+ * htdocs/search/svc_domain.cgi: $cgi->header( '-expires' => 'now' )
+
+1999-04-14 06:14 ivan
+
+ * TODO, htdocs/docs/config.html, htdocs/edit/cust_main.cgi:
+ configuration option to edit referrals of existing customers
+
+1999-04-14 04:27 ivan
+
+ * TODO, htdocs/docs/config.html, htdocs/edit/svc_acct.cgi,
+ htdocs/view/svc_acct.cgi: showpasswords config option to show
+ passwords
+
+1999-04-14 04:25 ivan
+
+ * htdocs/search/svc_acct.cgi: [no log message]
+
+1999-04-14 04:20 ivan
+
+ * htdocs/search/svc_acct.cgi: visual fix
+
+1999-04-14 01:58 ivan
+
+ * TODO: [no log message]
+
+1999-04-14 00:58 ivan
+
+ * bin/fs-setup, site_perl/UID.pm: export getsecrets from FS::UID
+ instead of calling it explicitly
+
+1999-04-14 00:47 ivan
+
+ * htdocs/edit/cust_main.cgi, htdocs/edit/process/cust_main.cgi,
+ site_perl/cust_main.pm: i18n fixes
+
+1999-04-13 18:03 ivan
+
+ * htdocs/edit/cust_pkg.cgi: oops, in 1.2 tree, can't do searches
+ until [cgi|admin]suidsetup, bug is hidden by mod_perl persistance
+
+1999-04-12 15:41 ivan
+
+ * site_perl/UID.pm: bugfix; $user is a global (yuck)
+
+1999-04-12 14:09 ivan
+
+ * site_perl/UID.pm: force username to lowercase
+
+1999-04-10 01:35 ivan
+
+ * site_perl/cust_main.pm: say what the unknown state/county/country
+ are!
+
+1999-04-10 00:38 ivan
+
+ * site_perl/cust_main.pm: _all_ check stuff with illegal data
+ return the bad data too, to help debugging
+
+1999-04-10 00:03 ivan
+
+ * site_perl/Record.pm: return the value with ut_* error messages,
+ to assist in debugging
+
+1999-04-09 23:54 ivan
+
+ * site_perl/cust_main.pm: ditto
+
+1999-04-09 22:27 ivan
+
+ * site_perl/cust_main.pm: display an illegal payby, to assist
+ importing
+
+1999-04-09 18:53 ivan
+
+ * htdocs/search/svc_acct.cgi: oops, search usernames limited to 8
+ chars
+
+1999-04-09 16:43 ivan
+
+ * htdocs/search/svc_acct.cgi: just in case
+
+1999-04-08 21:22 ivan
+
+ * htdocs/: browse/agent.cgi, browse/agent_type.cgi,
+ browse/cust_main_county.cgi, browse/part_pkg.cgi,
+ browse/part_referral.cgi, browse/part_svc.cgi,
+ browse/svc_acct_pop.cgi, edit/cust_main_county.cgi,
+ edit/part_svc.cgi, search/cust_main.cgi, search/svc_acct_sm.cgi,
+ view/cust_main.cgi, view/cust_pkg.cgi: also table()
+
+1999-04-08 20:52 ivan
+
+ * htdocs/: browse/agent.cgi, browse/agent_type.cgi,
+ browse/cust_main_county.cgi, browse/part_pkg.cgi,
+ browse/part_referral.cgi, browse/part_svc.cgi,
+ browse/svc_acct_pop.cgi, edit/cust_main.cgi,
+ edit/cust_main_county.cgi, edit/part_svc.cgi,
+ search/cust_main.cgi, search/svc_acct_sm.cgi, view/cust_main.cgi,
+ view/cust_pkg.cgi: explicit & for table/itable/ntable
+
+1999-04-08 20:52 ivan
+
+ * TODO: [no log message]
+
+1999-04-08 06:39 ivan
+
+ * htdocs/docs/man/: CGI.txt, Conf.txt, Record.txt, UID.txt,
+ agent.txt, agent_type.txt, cust_bill.txt, cust_bill_pkg.txt,
+ cust_credit.txt, cust_main.txt, cust_main_county.txt,
+ cust_main_invoice.txt, cust_pay.txt, cust_pay_batch.txt,
+ cust_pkg.txt, cust_refund.txt, cust_svc.txt, dbdef_column.txt,
+ dbdef_table.txt, index.html, part_pkg.txt, part_referral.txt,
+ part_svc.txt, pkg_svc.txt, svc_Common.txt, svc_acct.txt,
+ svc_acct_pop.txt, svc_acct_sm.txt, svc_domain.txt, type_pkgs.txt:
+ convert from pod for 1.2.0 release
+
+1999-04-08 06:21 ivan
+
+ * CREDITS, conf/address: [no log message]
+
+1999-04-08 06:11 ivan
+
+ * README: 1.2.0
+
+1999-04-08 06:05 ivan
+
+ * test/cgi-test: web interface tester / sample data creator
+
+1999-04-08 06:03 ivan
+
+ * TODO: [no log message]
+
+1999-04-08 06:01 ivan
+
+ * htdocs/edit/part_svc.cgi: [ AND DOCUMENT! ] all svc_acct
+ services should have a default
+ or fixed shell
+
+1999-04-08 05:08 ivan
+
+ * site_perl/Record.pm: fix up PostgreSQL money fields so you can
+ actually use them as numbers. bah.
+
+1999-04-08 05:00 ivan
+
+ * htdocs/view/: cust_pkg.cgi, svc_acct.cgi, svc_acct_sm.cgi,
+ svc_domain.cgi: aesthetic update
+
+1999-04-08 04:31 ivan
+
+ * htdocs/misc/link.cgi: [no log message]
+
+1999-04-08 03:35 ivan
+
+ * htdocs/misc/: cancel_pkg.cgi, susp_pkg.cgi: import necessary
+ subroutines from FS::CGI
+
+1999-04-07 21:04 ivan
+
+ * htdocs/view/cust_main.cgi: eliminate double // in links
+
+1999-04-07 08:22 ivan
+
+ * htdocs/edit/process/: cust_main.cgi, cust_credit.cgi,
+ cust_pkg.cgi: don't use anchor in redirect
+
+1999-04-07 07:58 ivan
+
+ * site_perl/Record.pm: more kludges to get around different
+ null/empty handling in Perl vs. MySQL vs. PostgreSQL etc.
+
+1999-04-07 07:40 ivan
+
+ * site_perl/: svc_acct_sm.pm, svc_domain.pm: use all stuff that's
+ qsearch'ed to avoid warnings
+
+1999-04-07 07:37 ivan
+
+ * site_perl/svc_acct.pm: use FS::part_svc and FS::svc_acct_pop to
+ avoid warnings
+
+1999-04-07 07:32 ivan
+
+ * site_perl/cust_main.pm: more &invoicing_list logic to skip
+ searches when there is no custnum
+
+1999-04-07 06:41 ivan
+
+ * site_perl/cust_main.pm: in &invoicing_list, don't search if
+ there's no custnum yet
+
+1999-04-07 04:43 ivan
+
+ * htdocs/edit/part_referral.cgi: pick up errors right away, leave
+ input
+
+1999-04-07 04:27 ivan
+
+ * htdocs/edit/agent.cgi: avoid perl's silly arguement not numeric
+ error
+
+1999-04-07 04:19 ivan
+
+ * htdocs/edit/agent_type.cgi: silly HTML typo
+
+1999-04-07 04:10 ivan
+
+ * htdocs/browse/agent_type.cgi: harmless typo
+
+1999-04-06 04:16 ivan
+
+ * htdocs/edit/cust_main.cgi: give a meaningful error message if you
+ try to create a customer before you've created an agent
+
+1999-04-06 01:55 ivan
+
+ * htdocs/docs/: install.html, postgresql.html: postgres notes
+
+1999-04-05 23:46 ivan
+
+ * htdocs/docs/install.html: [no log message]
+
+1999-04-03 18:55 ivan
+
+ * htdocs/index.html: [no log message]
+
+1999-04-03 17:53 ivan
+
+ * htdocs/index.html: Change Admin entries to read service/package
+ definitions, for clariy
+
+1999-04-03 17:21 ivan
+
+ * htdocs/docs/install.html: doc clarification
+
+1999-03-29 04:06 ivan
+
+ * site_perl/cust_main.pm: buglet in email invoices fixed
+
+1999-03-29 03:55 ivan
+
+ * site_perl/Record.pm: eliminate warnings in ut_money
+
+1999-03-28 17:29 ivan
+
+ * site_perl/Conf.pm: die unless the configuration directory exists
+
+1999-03-28 17:11 ivan
+
+ * site_perl/cust_pkg.pm: use FS::type_pkgs
+
+1999-03-26 05:15 ivan
+
+ * eg/TEMPLATE_cust_main.import: s/create/new/, use all necessary
+ FS::table_names to avoid warnings
+
+1999-03-26 05:00 ivan
+
+ * fs_passwd/fs_passwd_server: s/create/new/
+
+1999-03-25 05:55 ivan
+
+ * htdocs/edit/: cust_main.cgi, process/cust_main.cgi: one-screen
+ new customer entry (including package and service) for simple
+ packages with one svc_acct service
+
+1999-03-25 05:48 ivan
+
+ * site_perl/cust_pkg.pm: allow empty custnum in sub check (but call
+ that an error in sub insert), for one-screen new customer entry
+
+1999-03-25 05:31 ivan
+
+ * site_perl/svc_Common.pm: added setdefault method (generalized
+ setfixed method to setx method)
+
+1999-03-25 00:42 ivan
+
+ * bin/svc_acct.import, bin/svc_acct_sm.import,
+ htdocs/docs/install.html: import stuff uses Term::Query and spits
+ out (some kinds of) nonsensical input
+
+1999-03-23 21:24 ivan
+
+ * htdocs/docs/install.html: URI unbundled from libwww-perl, so list
+ it separately
+
+1999-03-23 16:51 ivan
+
+ * bin/svc_acct_sm.import: die if no relevant services... cvspain
+
+1999-03-23 16:43 ivan
+
+ * bin/svc_acct.import: die if no relevant services
+
+1999-02-28 12:09 ivan
+
+ * site_perl/cust_main.pm: allow spaces in zip codes, for (at least)
+ canada. pointed out by Clayton Gray <clgray@bcgroup.net>
+
+1999-02-28 11:44 ivan
+
+ * bin/fs-setup: constructors s/create/new/ pointed out by "Bao C.
+ Ha" <bao@hacom.net>
+
+1999-02-27 16:03 ivan
+
+ * htdocs/: edit/cust_credit.cgi, edit/cust_main.cgi,
+ edit/cust_pay.cgi, edit/cust_pkg.cgi, edit/svc_acct.cgi,
+ edit/svc_acct_sm.cgi, edit/svc_domain.cgi,
+ edit/process/cust_credit.cgi, edit/process/cust_main.cgi,
+ edit/process/cust_pay.cgi, edit/process/cust_pkg.cgi,
+ edit/process/svc_acct.cgi, edit/process/svc_acct_sm.cgi,
+ edit/process/svc_domain.cgi, misc/cancel-unaudited.cgi,
+ misc/cancel_pkg.cgi, misc/expire_pkg.cgi, misc/link.cgi,
+ misc/susp_pkg.cgi, misc/unsusp_pkg.cgi, search/cust_bill.cgi,
+ search/cust_main.cgi, search/svc_acct_sm.cgi,
+ search/svc_domain.cgi, view/cust_bill.cgi, view/cust_main.cgi,
+ view/cust_pkg.cgi, view/svc_acct.cgi, view/svc_acct_sm.cgi,
+ view/svc_domain.cgi: removed misleading comments
+
+1999-02-27 13:24 ivan
+
+ * site_perl/cust_main.pm: parse paydate correctly for cybercash
+
+1999-02-27 13:06 ivan
+
+ * bin/fs-setup, htdocs/docs/upgrade3.html: cust_main.paydate should
+ be varchar(10), not @date_type ; problem reported by Ben Leibig
+ <leibig@colorado.edu>
+
+1999-02-23 00:09 ivan
+
+ * TODO, htdocs/docs/config.html, htdocs/edit/cust_main.cgi,
+ htdocs/edit/part_svc.cgi, htdocs/edit/svc_acct.cgi,
+ htdocs/edit/svc_acct_pop.cgi, htdocs/search/svc_domain.cgi,
+ htdocs/view/svc_domain.cgi, site_perl/cust_main.pm: beginnings of
+ one-screen new customer entry and some other miscellania
+
+1999-02-22 23:23 ivan
+
+ * site_perl/UID.pm: oops, don't comment out &swapuid in
+ &adminsuidsetup!
+
+1999-02-10 01:02 ivan
+
+ * etc/sql-reserved-words.txt: some new doc files
+
+1999-02-10 00:27 ivan
+
+ * TODO: [no log message]
+
+1999-02-09 01:56 ivan
+
+ * TODO: [no log message]
+
+1999-02-09 01:55 ivan
+
+ * site_perl/: cust_bill.pm, cust_pkg.pm: invoices show line items
+ for each service in a package (see the label method of
+ FS::cust_svc)
+
+1999-02-09 01:37 ivan
+
+ * htdocs/docs/man/: CGI.txt, Conf.txt, Invoice.txt, Record.txt,
+ UID.txt, agent.txt, agent_type.txt, cust_bill.txt,
+ cust_bill_pkg.txt, cust_credit.txt, cust_main.txt,
+ cust_main_county.txt, cust_pay.txt, cust_pkg.txt,
+ cust_refund.txt, cust_svc.txt, dbdef_column.txt, dbdef_table.txt,
+ index.html, part_pkg.txt, part_referral.txt, part_svc.txt,
+ pkg_svc.txt, svc_acct.txt, svc_acct_pop.txt, svc_acct_sm.txt,
+ svc_domain.txt, type_pkgs.txt: regenerated perl api docs from
+ embedded pod
+
+1999-02-09 01:22 ivan
+
+ * htdocs/: search/cust_pkg.cgi, search/svc_acct_sm.cgi,
+ search/svc_domain.cgi, view/svc_acct_sm.cgi: visual and bugfixes
+
+1999-02-08 21:45 ivan
+
+ * htdocs/docs/CGI-modules-2.76-patch.txt: no longer needed
+
+1999-02-07 01:59 ivan
+
+ * CREDITS, TODO, bin/fs-setup, htdocs/docs/export.html,
+ htdocs/docs/schema.html, htdocs/docs/trouble.html,
+ htdocs/edit/cust_pkg.cgi, htdocs/edit/part_pkg.cgi,
+ htdocs/edit/part_referral.cgi, htdocs/edit/part_svc.cgi,
+ htdocs/edit/svc_acct.cgi, htdocs/edit/svc_acct_pop.cgi,
+ htdocs/edit/svc_acct_sm.cgi, htdocs/edit/svc_domain.cgi,
+ htdocs/edit/process/cust_pkg.cgi,
+ htdocs/edit/process/part_pkg.cgi,
+ htdocs/edit/process/part_referral.cgi,
+ htdocs/edit/process/part_svc.cgi,
+ htdocs/edit/process/svc_acct.cgi,
+ htdocs/edit/process/svc_acct_pop.cgi,
+ htdocs/edit/process/svc_acct_sm.cgi,
+ htdocs/edit/process/svc_domain.cgi,
+ htdocs/misc/cancel-unaudited.cgi, htdocs/misc/process/link.cgi,
+ htdocs/search/cust_main.cgi, htdocs/search/cust_pkg.cgi,
+ htdocs/search/svc_acct.cgi, htdocs/search/svc_domain.cgi,
+ htdocs/view/cust_main.cgi, htdocs/view/svc_acct_sm.cgi,
+ site_perl/CGI.pm, site_perl/part_svc.pm: more mod_perl fixes, and
+ bugfixes Peter Wemm sent via email
+
+1999-02-06 14:43 ivan
+
+ * CREDITS, TODO: don't use [e]idiot; display error messages on the
+ form page
+
+1999-02-03 22:09 ivan
+
+ * bin/fs-setup: add AU provences
+
+1999-02-03 02:42 ivan
+
+ * bin/fs-setup: [no log message]
+
+1999-01-25 04:26 ivan
+
+ * htdocs/view/cust_bill.cgi, htdocs/view/cust_main.cgi,
+ site_perl/CGI.pm, site_perl/Record.pm, site_perl/cust_bill.pm,
+ site_perl/cust_credit.pm, site_perl/cust_main.pm,
+ site_perl/cust_main_invoice.pm, site_perl/cust_pay.pm,
+ site_perl/cust_pkg.pm, site_perl/cust_refund.pm,
+ site_perl/svc_Common.pm, site_perl/svc_acct.pm,
+ site_perl/svc_acct_sm.pm, site_perl/svc_domain.pm: yet more
+ mod_perl stuff
+
+1999-01-25 04:19 ivan
+
+ * htdocs/: edit/process/cust_main_county-expand.cgi,
+ edit/process/cust_main_county.cgi, edit/process/cust_pay.cgi,
+ edit/process/cust_pkg.cgi, search/cust_main.cgi: yet more
+ mod_perl stuff
+
+1999-01-25 04:09 ivan
+
+ * TODO, htdocs/edit/agent.cgi, htdocs/edit/agent_type.cgi,
+ htdocs/edit/cust_credit.cgi, htdocs/edit/cust_main.cgi,
+ htdocs/edit/cust_main_county-expand.cgi,
+ htdocs/edit/cust_main_county.cgi, htdocs/edit/cust_pay.cgi,
+ htdocs/edit/process/agent.cgi,
+ htdocs/edit/process/agent_type.cgi,
+ htdocs/edit/process/cust_credit.cgi,
+ htdocs/edit/process/cust_main.cgi: yet more mod_perl stuff
+
+1999-01-20 01:43 ivan
+
+ * htdocs/browse/agent.cgi: comment out future UI code (but look at
+ it, it's neat!)
+
+1999-01-20 01:30 ivan
+
+ * site_perl/UI/: Base.pm, CGI.pm, Gtk.pm, agent.pm: skeletal
+ cross-UI UI code.
+
+1999-01-20 00:55 ivan
+
+ * htdocs/docs/install.html: documentation update: mod_perl support
+
+1999-01-18 21:13 ivan
+
+ * htdocs/: browse/agent.cgi, browse/agent_type.cgi,
+ browse/cust_main_county.cgi, browse/part_pkg.cgi,
+ browse/part_referral.cgi, browse/part_svc.cgi,
+ browse/svc_acct_pop.cgi, edit/agent.cgi, edit/agent_type.cgi,
+ edit/cust_credit.cgi, edit/cust_main.cgi,
+ edit/cust_main_county-expand.cgi, edit/cust_main_county.cgi,
+ edit/cust_pay.cgi, edit/cust_pkg.cgi, edit/part_pkg.cgi,
+ edit/part_referral.cgi, edit/part_svc.cgi, edit/svc_acct.cgi,
+ edit/svc_acct_pop.cgi, edit/svc_acct_sm.cgi, edit/svc_domain.cgi,
+ edit/process/agent.cgi, edit/process/agent_type.cgi,
+ edit/process/cust_credit.cgi, edit/process/cust_main.cgi,
+ edit/process/cust_main_county-expand.cgi,
+ edit/process/cust_main_county.cgi, edit/process/cust_pay.cgi,
+ edit/process/cust_pkg.cgi, edit/process/part_pkg.cgi,
+ edit/process/part_referral.cgi, edit/process/part_svc.cgi,
+ edit/process/svc_acct.cgi, edit/process/svc_acct_pop.cgi,
+ edit/process/svc_acct_sm.cgi, edit/process/svc_domain.cgi,
+ misc/bill.cgi, misc/cancel-unaudited.cgi, misc/cancel_pkg.cgi,
+ misc/expire_pkg.cgi, misc/link.cgi, misc/print-invoice.cgi,
+ misc/susp_pkg.cgi, misc/unsusp_pkg.cgi, misc/process/link.cgi,
+ search/cust_bill.cgi, search/cust_main.cgi, search/cust_pkg.cgi,
+ search/svc_acct.cgi, search/svc_acct_sm.cgi,
+ search/svc_domain.cgi, view/cust_bill.cgi, view/cust_main.cgi,
+ view/cust_pkg.cgi, view/svc_acct.cgi, view/svc_acct_sm.cgi,
+ view/svc_domain.cgi: for mod_perl: no more top-level my()
+ variables; use vars instead also the last s/create/new/;
+
+1999-01-18 15:05 ivan
+
+ * TODO: update TODO for stuff that was done etc.
+
+1999-01-18 14:47 ivan
+
+ * htdocs/edit/process/: agent.cgi, agent_type.cgi, cust_credit.cgi,
+ cust_main_county-expand.cgi, cust_main_county.cgi, cust_pay.cgi,
+ part_pkg.cgi, part_referral.cgi, part_svc.cgi, svc_acct.cgi,
+ svc_acct_pop.cgi, svc_acct_sm.cgi, svc_domain.cgi:
+ s/create/new/g; and use fields('table_name')
+
+1999-01-18 14:16 ivan
+
+ * site_perl/Invoice.pm: typo
+
+1999-01-18 13:58 ivan
+
+ * site_perl/: cust_bill.pm, cust_credit.pm, cust_main_invoice.pm,
+ cust_pkg.pm, pkg_svc.pm, svc_acct.pm, svc_acct_sm.pm: esthetic:
+ eq and ne were used in a few places instead of == and !=
+
+1999-01-18 01:41 ivan
+
+ * htdocs/browse/agent.cgi, htdocs/browse/agent_type.cgi,
+ htdocs/browse/cust_main_county.cgi, htdocs/browse/part_pkg.cgi,
+ htdocs/browse/part_referral.cgi, htdocs/browse/part_svc.cgi,
+ htdocs/browse/svc_acct_pop.cgi, htdocs/edit/agent.cgi,
+ htdocs/edit/agent_type.cgi, htdocs/edit/cust_credit.cgi,
+ htdocs/edit/cust_main.cgi,
+ htdocs/edit/cust_main_county-expand.cgi,
+ htdocs/edit/cust_main_county.cgi, htdocs/edit/cust_pay.cgi,
+ htdocs/edit/cust_pkg.cgi, htdocs/edit/part_pkg.cgi,
+ htdocs/edit/part_referral.cgi, htdocs/edit/part_svc.cgi,
+ htdocs/edit/svc_acct.cgi, htdocs/edit/svc_acct_pop.cgi,
+ htdocs/edit/svc_acct_sm.cgi, htdocs/edit/svc_domain.cgi,
+ htdocs/misc/link.cgi, htdocs/search/cust_main.cgi,
+ htdocs/search/cust_pkg.cgi, htdocs/search/svc_acct.cgi,
+ htdocs/search/svc_acct_sm.cgi, htdocs/view/cust_bill.cgi,
+ htdocs/view/cust_main.cgi, htdocs/view/cust_pkg.cgi,
+ htdocs/view/svc_acct.cgi, htdocs/view/svc_acct_sm.cgi,
+ htdocs/view/svc_domain.cgi, site_perl/CGI.pm: all $cgi->header
+ calls now include ( '-expires' => 'now' ) for mod_perl (good idea
+ anyway)
+
+1999-01-18 01:22 ivan
+
+ * htdocs/browse/agent.cgi, htdocs/docs/trouble.html,
+ htdocs/docs/upgrade3.html, htdocs/edit/agent_type.cgi,
+ htdocs/edit/cust_main.cgi, htdocs/edit/process/cust_main.cgi,
+ htdocs/search/cust_pkg.cgi, htdocs/search/svc_acct.cgi,
+ htdocs/view/cust_main.cgi, htdocs/view/svc_acct.cgi,
+ site_perl/CGI.pm, site_perl/Record.pm, site_perl/UID.pm,
+ site_perl/cust_main.pm, site_perl/cust_main_invoice.pm: changes
+ to track email addresses for email invoicing
+
+1999-01-16 20:04 ivan
+
+ * site_perl/CGI.pm: itable
+
+1999-01-16 19:13 ivan
+
+ * htdocs/index.html: s/Information/Freeside home page/;
+
+1999-01-16 19:11 ivan
+
+ * bin/fs-setup: remove preliminary completehost changes
+
+1999-01-15 16:24 ivan
+
+ * CREDITS: [no log message]
+
+1999-01-08 21:38 ivan
+
+ * CREDITS: [no log message]
+
+1998-12-30 17:04 ivan
+
+ * site_perl/part_pkg.pm: doc
+
+1998-12-30 15:06 ivan
+
+ * htdocs/browse/part_svc.cgi: typo
+
+1998-12-30 15:03 ivan
+
+ * TODO, htdocs/browse/part_svc.cgi, htdocs/edit/part_svc.cgi,
+ htdocs/edit/svc_acct.cgi, htdocs/edit/svc_acct_sm.cgi,
+ htdocs/edit/svc_domain.cgi, htdocs/edit/process/agent.cgi,
+ htdocs/edit/process/agent_type.cgi,
+ htdocs/edit/process/cust_pay.cgi,
+ htdocs/edit/process/part_pkg.cgi,
+ htdocs/edit/process/part_referral.cgi,
+ htdocs/edit/process/part_svc.cgi,
+ htdocs/edit/process/svc_acct_pop.cgi, htdocs/view/cust_bill.cgi,
+ htdocs/view/cust_main.cgi: bugfixes; fields isn't exported by
+ derived classes
+
+1998-12-29 16:57 ivan
+
+ * htdocs/search/cust_main.cgi: bug
+
+1998-12-29 16:30 ivan
+
+ * site_perl/: Invoice.pm, agent.pm, svc_Common.pm, svc_acct.pm,
+ svc_acct_sm.pm, svc_domain.pm, table_template-svc.pm: svc_ stuff
+ is more properly OO - has a common superclass FS::svc_Common
+
+1998-12-29 03:59 ivan
+
+ * TODO, site_perl/Record.pm, site_perl/agent.pm,
+ site_perl/agent_type.pm, site_perl/cust_bill.pm,
+ site_perl/cust_bill_pkg.pm, site_perl/cust_credit.pm,
+ site_perl/cust_main.pm, site_perl/cust_main_county.pm,
+ site_perl/cust_main_invoice.pm, site_perl/cust_pay.pm,
+ site_perl/cust_pay_batch.pm, site_perl/cust_pkg.pm,
+ site_perl/cust_refund.pm, site_perl/cust_svc.pm,
+ site_perl/part_pkg.pm, site_perl/part_referral.pm,
+ site_perl/part_svc.pm, site_perl/pkg_svc.pm,
+ site_perl/svc_acct.pm, site_perl/svc_acct_pop.pm,
+ site_perl/svc_acct_sm.pm, site_perl/svc_domain.pm,
+ site_perl/table_template-svc.pm, site_perl/table_template.pm,
+ site_perl/type_pkgs.pm: mostly properly OO, some work still to be
+ done with svc_ stuff
+
+1998-12-23 01:41 ivan
+
+ * htdocs/docs/upgrade3.html: typo
+
+1998-12-23 00:08 ivan
+
+ * htdocs/edit/cust_main.cgi: fix typo
+
+1998-12-22 19:11 ivan
+
+ * htdocs/view/cust_pkg.cgi: [no log message]
+
+1998-12-22 19:07 ivan
+
+ * htdocs/view/: cust_bill.cgi, cust_pkg.cgi, svc_acct.cgi,
+ svc_acct_sm.cgi, svc_domain.cgi: $cgi->keywords instead of
+ $cgi->query_string
+
+1998-12-22 19:04 ivan
+
+ * htdocs/: misc/print-invoice.cgi, misc/susp_pkg.cgi,
+ misc/unsusp_pkg.cgi, search/cust_pkg.cgi, search/svc_acct.cgi,
+ search/svc_domain.cgi: $cgi->keywords instead of
+ $cgi->query_string
+
+1998-12-22 19:01 ivan
+
+ * htdocs/misc/: bill.cgi, cancel-unaudited.cgi, cancel_pkg.cgi,
+ link.cgi: $cgi->keywords instead of $cgi->query_string
+
+1998-12-22 18:57 ivan
+
+ * htdocs/edit/: svc_acct_pop.cgi, svc_acct_sm.cgi, svc_domain.cgi:
+ $cgi->keywords instead of $cgi->query_string
+
+1998-12-22 18:42 ivan
+
+ * htdocs/view/cust_main.cgi: remove double '/' in link urls
+
+1998-12-22 18:36 ivan
+
+ * htdocs/view/cust_main.cgi: use FS::cust_refund; to eliminate
+ warning
+
+1998-12-22 18:26 ivan
+
+ * htdocs/edit/cust_credit.cgi: [no log message]
+
+1998-12-22 18:23 ivan
+
+ * site_perl/CGI.pm: popurl always has trailing slash
+
+1998-12-19 18:11 ivan
+
+ * htdocs/docs/install.html: suggest suEXEC as an alternative to
+ suidperl
+
+1998-12-17 01:57 ivan
+
+ * htdocs/view/: cust_bill.cgi, cust_main.cgi, cust_pkg.cgi,
+ svc_acct.cgi, svc_acct_sm.cgi, svc_domain.cgi:
+ s/CGI::(Base|Request)/CGI.pm/;
+
+1998-12-17 01:41 ivan
+
+ * htdocs/search/: cust_bill.cgi, cust_main.cgi, cust_pkg.cgi,
+ svc_acct.cgi, svc_acct_sm.cgi, svc_domain.cgi:
+ s/CGI::(Base|Request)/CGI.pm/;
+
+1998-12-17 01:15 ivan
+
+ * htdocs/misc/process/link.cgi: s/CGI::Request/CGI.pm/;
+
+1998-12-17 01:12 ivan
+
+ * htdocs/misc/: bill.cgi, cancel-unaudited.cgi, cancel_pkg.cgi,
+ expire_pkg.cgi, link.cgi, print-invoice.cgi, susp_pkg.cgi,
+ unsusp_pkg.cgi: s/CGI::(Request|Base)/CGI.pm/;
+
+1998-12-17 00:40 ivan
+
+ * htdocs/edit/process/: agent.cgi, agent_type.cgi, cust_credit.cgi,
+ cust_main.cgi, cust_main_county-expand.cgi, cust_main_county.cgi,
+ cust_pay.cgi, cust_pkg.cgi, part_pkg.cgi, part_referral.cgi,
+ part_svc.cgi, svc_acct.cgi, svc_acct_pop.cgi, svc_acct_sm.cgi,
+ svc_domain.cgi: s/CGI::Request/CGI.pm/; etc
+
+1998-12-16 22:16 ivan
+
+ * htdocs/edit/: agent.cgi, agent_type.cgi, cust_credit.cgi,
+ cust_main.cgi, cust_main_county-expand.cgi, cust_main_county.cgi,
+ cust_pay.cgi, cust_pkg.cgi, part_pkg.cgi, part_referral.cgi,
+ part_svc.cgi, svc_acct.cgi, svc_acct_pop.cgi, svc_acct_sm.cgi,
+ svc_domain.cgi: fix double // in relative URLs, s/CGI::Base/CGI/;
+
+1998-12-16 21:25 ivan
+
+ * htdocs/browse/: agent.cgi, agent_type.cgi, cust_main_county.cgi,
+ part_pkg.cgi, part_referral.cgi, part_svc.cgi, svc_acct_pop.cgi:
+ fix visual and other bugs
+
+1998-12-16 20:54 ivan
+
+ * htdocs/docs/schema.html: [no log message]
+
+1998-12-16 20:47 ivan
+
+ * htdocs/images/sisd.jpg: switch to new logo, no reason to take up
+ space
+
+1998-12-16 20:36 ivan
+
+ * htdocs/browse/svc_acct_pop.cgi: use CGI;, use CGI::Carp, visual
+ changes, relative URLs
+
+1998-12-16 20:32 ivan
+
+ * htdocs/browse/part_referral.cgi: print $cgi->header
+
+1998-12-16 20:31 ivan
+
+ * htdocs/browse/part_referral.cgi: use CGI::Carp
+
+1998-12-16 20:26 ivan
+
+ * htdocs/browse/part_referral.cgi: use CGI; no relative URLs
+
+1998-12-16 01:58 ivan
+
+ * site_perl/: cust_main.pm, cust_main_invoice.pm: library support
+ for editing email invoice destinations (not in sub collect yet)
+
+1998-12-15 23:40 ivan
+
+ * site_perl/cust_main_invoice.pm: new table
+
+1998-12-15 22:05 ivan
+
+ * bin/fs-setup, htdocs/docs/schema.html, htdocs/docs/upgrade3.html:
+ add table cust_main_invoice
+
+1998-12-15 21:38 ivan
+
+ * TODO: [no log message]
+
+1998-12-15 21:32 ivan
+
+ * fs_passwd/fs_passwd_server: adminsuidsetup now requires user
+
+1998-12-15 21:29 ivan
+
+ * eg/TEMPLATE_cust_main.import: adminsuidsetup now need user
+
+1998-12-15 21:24 ivan
+
+ * htdocs/view/: svc_acct.cgi, svc_acct_sm.cgi: use FS::Conf;
+
+1998-12-15 21:20 ivan
+
+ * htdocs/search/svc_acct_sm.cgi: use FS::Conf;
+
+1998-12-15 21:17 ivan
+
+ * htdocs/edit/: svc_acct.cgi, svc_acct_sm.cgi: use FS::Conf
+
+1998-12-15 21:13 ivan
+
+ * htdocs/docs/export.html: visual changes, new config file dir
+
+1998-12-15 20:32 ivan
+
+ * htdocs/docs/legacy.html: oops, removed explicit links to my
+ development machine!
+
+1998-12-14 20:36 ivan
+
+ * bin/fs-setup: s/croak/die/; #oops
+
+1998-12-14 20:33 ivan
+
+ * bin/fs-setup: dies if it isn't running as the freeside user
+
+1998-12-11 22:36 ivan
+
+ * htdocs/docs/trouble.html: hint for mysql systems w/o native
+ threading
+
+1998-12-09 23:23 ivan
+
+ * bin/: svc_acct.export, svc_acct.import, svc_acct_sm.export,
+ svc_acct_sm.import: use FS::Conf, need user (for datasrc)
+
+1998-12-01 17:23 ivan
+
+ * TODO, CREDITS: [no log message]
+
+1998-11-28 15:59 ivan
+
+ * htdocs/docs/install.html: run fs-setup as user freeside
+
+1998-11-22 23:52 ivan
+
+ * htdocs/edit/: agent.cgi, process/agent.cgi: [no log message]
+
+1998-11-22 21:42 ivan
+
+ * site_perl/agent.pm: use FS::cust_main and FS::agent_type to
+ eliminate warnings
+
+1998-11-22 21:29 ivan
+
+ * htdocs/browse/agent.cgi: use CGI::Carp
+
+1998-11-22 21:27 ivan
+
+ * htdocs/browse/agent.cgi: to eliminate warnings
+
+1998-11-20 23:58 ivan
+
+ * htdocs/edit/agent_type.cgi: package names link to them
+
+1998-11-20 23:49 ivan
+
+ * htdocs/edit/process/agent_type.cgi: s/CGI::Request/CGI.pm/
+
+1998-11-20 23:45 ivan
+
+ * htdocs/edit/agent_type.cgi: visual, use FS::table_name when doing
+ qsearch('table_name')
+
+1998-11-20 23:39 ivan
+
+ * htdocs/browse/agent_type.cgi: visual
+
+1998-11-20 23:26 ivan
+
+ * site_perl/Record.pm: "Records identical" carp tells us it is just
+ a warning.
+
+1998-11-20 23:23 ivan
+
+ * htdocs/browse/part_pkg.cgi: visual
+
+1998-11-20 23:17 ivan
+
+ * htdocs/edit/process/part_pkg.cgi: bugfix to work for regular
+ aswell as custom pricing
+
+1998-11-20 23:11 ivan
+
+ * htdocs/edit/: part_pkg.cgi: [no log message]
+
+1998-11-20 23:07 ivan
+
+ * htdocs/edit/part_pkg.cgi: popurl, bugfix
+
+1998-11-20 23:00 ivan
+
+ * htdocs/browse/part_pkg.cgi: visual
+
+1998-11-20 22:43 ivan
+
+ * htdocs/edit/part_svc.cgi: visual
+
+1998-11-20 22:43 ivan
+
+ * htdocs/edit/process/part_svc.cgi: s/CGI::Request/CGI.pm/
+
+1998-11-20 19:16 ivan
+
+ * htdocs/edit/part_svc.cgi: visual
+
+1998-11-20 19:00 ivan
+
+ * htdocs/index.html: visual
+
+1998-11-20 18:26 ivan
+
+ * htdocs/browse/part_svc.cgi: visual
+
+1998-11-20 15:10 ivan
+
+ * htdocs/browse/part_svc.cgi: visual
+
+1998-11-20 00:50 ivan
+
+ * htdocs/browse/: agent.cgi, part_svc.cgi: s/CGI::Base/CGI.pm,
+ visual fixes
+
+1998-11-19 03:17 ivan
+
+ * bin/dbdef-create: adminsuidsetup requires argument
+
+1998-11-18 01:01 ivan
+
+ * CREDITS, TODO, bin/fs-setup, htdocs/index.html,
+ htdocs/browse/cust_main_county.cgi, htdocs/docs/schema.html,
+ htdocs/docs/upgrade3.html, htdocs/edit/cust_main.cgi,
+ htdocs/edit/cust_main_county-expand.cgi,
+ htdocs/edit/cust_main_county.cgi,
+ htdocs/edit/process/cust_main_county-expand.cgi,
+ htdocs/edit/process/cust_main_county.cgi, site_perl/cust_main.pm,
+ site_perl/cust_main_county.pm, site_perl/cust_pay_batch.pm: i18n!
+ i18n!
+
+1998-11-18 00:57 ivan
+
+ * htdocs/edit/process/cust_main.cgi: i18n, s/CGI-modules/CGI.pm/,
+ FS::CGI::idiot instead of inline, FS::CGI::popurl
+
+1998-11-15 05:18 ivan
+
+ * bin/fs-setup: remove debugging
+
+1998-11-15 05:14 ivan
+
+ * htdocs/edit/: part_pkg.cgi, process/part_pkg.cgi: first pass as
+ per-user custom pricing
+
+1998-11-15 05:14 ivan
+
+ * htdocs/view/cust_main.cgi: first pass as per-customer custom
+ pricing
+
+1998-11-15 05:01 ivan
+
+ * site_perl/cust_pkg.pm: allow pkgpart changing (for per-customer
+ custom pricing). warn about it in doc
+
+1998-11-15 05:00 ivan
+
+ * site_perl/part_pkg.pm: bugfix in clone method, clone method doc
+ clarification
+
+1998-11-15 03:23 ivan
+
+ * site_perl/cust_main.pm: use FS::table_name for all searches to
+ eliminate warnings, emit state/county when they don't match
+
+1998-11-15 03:20 ivan
+
+ * htdocs/edit/agent_type.cgi: s/CGI-Base/CGI.pm/ causes
+ s/QUERY_STRING/keywords/;
+
+1998-11-15 03:02 ivan
+
+ * site_perl/Record.pm: bugsquash
+
+1998-11-15 02:56 ivan
+
+ * site_perl/Record.pm: qsearch gets sames "IS NULL" semantics as
+ other WHERE clauses
+
+1998-11-15 01:43 ivan
+
+ * bin/fs-setup: update for new config file syntax, new
+ adminsuidsetup
+
+1998-11-15 01:08 ivan
+
+ * site_perl/part_pkg.pm: added clone method to support per-customer
+ pricing
+
+1998-11-14 21:30 ivan
+
+ * site_perl/: cust_main.pm, Record.pm: bugfix for new config layout
+
+1998-11-14 21:27 ivan
+
+ * site_perl/UID.pm: bugfix for new configuration layout
+
+1998-11-14 21:19 ivan
+
+ * site_perl/cust_pay_batch.pm: long overdue
+
+1998-11-14 20:33 ivan
+
+ * site_perl/: table_template.pm, table_template-svc.pm: updates for
+ newest versoin
+
+1998-11-14 19:48 ivan
+
+ * site_perl/table_template.pm: update for current version
+
+1998-11-14 19:46 ivan
+
+ * site_perl/table_template-unique.pm: [no log message]
+
+1998-11-14 18:53 ivan
+
+ * bin/bill: afterthought
+
+1998-11-14 18:51 ivan
+
+ * bin/bill: adminsuidsetup needs user, pod, cleanup
+
+1998-11-14 16:51 ivan
+
+ * site_perl/UID.pm: eliminated some warnings on certain fatal
+ errors (well, it is less confusing)
+
+1998-11-13 03:28 ivan
+
+ * htdocs/view/cust_main.cgi: s/CGI-modules/CGI.pm/;, relative URL's
+ with popurl
+
+1998-11-13 01:56 ivan
+
+ * TODO, htdocs/docs/man/CGI.txt, htdocs/docs/man/Conf.txt,
+ htdocs/docs/man/Record.txt, htdocs/docs/man/UID.txt,
+ htdocs/docs/man/cust_bill.txt, htdocs/docs/man/cust_main.txt,
+ htdocs/docs/man/cust_pkg.txt, htdocs/docs/man/cust_svc.txt,
+ htdocs/docs/man/dbdef_column.txt,
+ htdocs/docs/man/dbdef_table.txt, htdocs/docs/man/svc_acct.txt,
+ htdocs/docs/man/svc_domain.txt, htdocs/edit/agent_type.cgi,
+ htdocs/edit/svc_acct_pop.cgi, htdocs/edit/svc_domain.cgi,
+ htdocs/view/cust_pkg.cgi, htdocs/view/svc_domain.cgi,
+ site_perl/Record.pm, site_perl/UID.pm, site_perl/cust_bill.pm,
+ site_perl/cust_main.pm, site_perl/svc_acct.pm,
+ site_perl/svc_acct_sm.pm, site_perl/svc_domain.pm: change
+ configuration file layout to support multiple distinct databases
+ (with own set of config files, export, etc.)
+
+1998-11-12 21:15 ivan
+
+ * htdocs/docs/: install.html, upgrade3.html: more documentation
+ updates for new config location
+
+1998-11-12 20:45 ivan
+
+ * htdocs/docs/config.html: secrets files are located in
+ /usr/local/etc/freeside, not just default.
+
+1998-11-12 20:08 ivan
+
+ * site_perl/Conf.pm: no default default_dir (ironic)
+
+1998-11-12 18:43 ivan
+
+ * htdocs/docs/: config.html, upgrade3.html: update documentation
+ for new config file format
+
+1998-11-12 00:10 ivan
+
+ * htdocs/search/cust_main.cgi: CGI.pm instead of CGI-modules
+ relative URLs using popurl got rid of lots of little tables
+ s/agrep/String::Approx/; bubble up packages and services and link
+ (slow)
+
+1998-11-11 23:58 ivan
+
+ * site_perl/cust_svc.pm: added svcdb to label
+
+1998-11-11 23:43 ivan
+
+ * site_perl/CGI.pm: [no log message]
+
+1998-11-11 19:45 ivan
+
+ * site_perl/cust_svc.pm: use FS::table_name for all tables
+ qsearch()'ed
+
+1998-11-11 19:42 ivan
+
+ * site_perl/cust_pkg.pm: added label method
+
+1998-11-11 19:32 ivan
+
+ * site_perl/cust_svc.pm: added label method
+
+1998-11-11 17:53 ivan
+
+ * site_perl/CGI.pm: added table command
+
+1998-11-09 23:45 ivan
+
+ * site_perl/Record.pm: doc clarification
+
+1998-11-09 23:44 ivan
+
+ * site_perl/Record.pm: qsearch returns `FS::TABLE' objects if that
+ module is loaded (i.e. via `use FS::cust_main;') instead of
+ always an FS::Record object
+
+1998-11-09 18:24 ivan
+
+ * htdocs/search/: cust_main.html, cust_main-payinfo.html: [no log
+ message]
+
+1998-11-09 14:24 ivan
+
+ * htdocs/search/cust_main.html: default company_on and last_on
+ CHECKED
+
+1998-11-09 00:51 ivan
+
+ * site_perl/CGI.pm: bug squash
+
+1998-11-09 00:36 ivan
+
+ * site_perl/CGI.pm: haha
+
+1998-11-09 00:29 ivan
+
+ * htdocs/docs/upgrade3.html: 1.2.x
+
+1998-11-09 00:25 ivan
+
+ * htdocs/docs/index.html: upgrade to 1.2.x section
+
+1998-11-09 00:18 ivan
+
+ * htdocs/docs/install.html: s/agrep/String::Approx/
+
+1998-11-08 22:10 ivan
+
+ * site_perl/CGI.pm: added sub url
+
+1998-11-08 21:44 ivan
+
+ * site_perl/CGI.pm: [no log message]
+
+1998-11-08 21:23 ivan
+
+ * site_perl/CGI.pm: [no log message]
+
+1998-11-08 20:55 ivan
+
+ * site_perl/CGI.pm: support depriciated CGI::Base as well as CGI.pm
+ (for now)
+
+1998-11-08 02:50 ivan
+
+ * site_perl/CGI.pm: s/CGI::Base/CGI/; etc.
+
+1998-11-08 02:45 ivan
+
+ * site_perl/UID.pm: got sub cgi for FS::CGI
+
+1998-11-08 02:11 ivan
+
+ * htdocs/browse/agent.cgi: CGI.pm
+
+1998-11-08 01:38 ivan
+
+ * site_perl/UID.pm: cgisuidsetup complains if you pass it a isa
+ CGI::Base instead of an isa CGI (first step in migrating from
+ CGI-modules to CGI.pm)
+
+1998-11-07 17:09 ivan
+
+ * README: 1.1.6 release
+
+1998-11-07 02:24 ivan
+
+ * README, htdocs/index.html, htdocs/browse/agent.cgi,
+ site_perl/CGI.pm, site_perl/cust_bill.pm, site_perl/cust_main.pm:
+ don't use depriciated FS::Bill and FS::Invoice, other miscellania
+
+1998-11-07 00:25 ivan
+
+ * TODO: [no log message]
+
+1998-11-07 00:21 ivan
+
+ * bin/bill: missing use
+
+1998-11-07 00:19 ivan
+
+ * bin/bill:
+ still need to bless into FS::cust_main (for now)
+
+1998-11-07 00:08 ivan
+
+ * bin/bill:
+ Removed depriciated FS::Bill (now in FS::cust_main)
+
+1998-11-06 21:17 ivan
+
+ * site_perl/Record.pm: In sub new, Pg wrapper for money fields from
+ dbdef (FS::Record::fields $table), not keys of supplied hashref.
+
+1998-11-03 18:45 ivan
+
+ * htdocs/docs/CGI-modules-2.76-patch.txt:
+ generated patch with makepatch
+
+1998-10-22 08:51 ivan
+
+ * bin/fs-setup: also varchar with no length specified - postgresql
+ fix broke mysql.
+
+1998-10-22 08:46 ivan
+
+ * bin/fs-setup: now smallint is illegal, so remove that too.
+
+1998-10-14 01:18 ivan
+
+ * site_perl/svc_domain.pm: More informative error messages and
+ better doc for admin contact email stuff
+
+1998-10-14 00:05 ivan
+
+ * README, bin/fs-setup, site_perl/dbdef_table.pm: 1.1.4 release,
+ fix postgresql
+
+1998-10-13 23:52 ivan
+
+ * htdocs/docs/: index.html, upgrade2.html, man/Conf.txt,
+ man/Invoice.txt, man/Record.txt, man/dbdef_column.txt,
+ man/dbdef_table.txt: 1,1,4 release, fix postgresql quirks.
+
+1998-10-13 06:11 ivan
+
+ * htdocs/.htaccess: So new installs have some protection (WDWWC).
+
+1998-10-13 06:04 ivan
+
+ * site_perl/dbdef_column.pm: fixed doc to indicate Pg specific
+ syntax too
+
+1998-10-13 05:49 ivan
+
+ * TODO: [no log message]
+
+1998-10-13 05:07 ivan
+
+ * TODO, bin/svc_acct.import: Assigns password from the shadow file
+ for RADIUS password "UNIX"
+
+1998-10-13 02:17 ivan
+
+ * TODO: [no log message]
+
+1998-10-12 16:40 ivan
+
+ * site_perl/dbdef_column.pm: added Pg-specific behaviour in sub
+ line
+
+1998-10-12 14:22 ivan
+
+ * TODO: [no log message]
+
+1998-10-12 14:15 ivan
+
+ * TODO: [no log message]
+
+1998-10-12 02:12 ivan
+
+ * TODO: remove adding cvs from the todo
+
+1998-10-12 02:09 ivan
+
+ * TODO: [no log message]
+
+1998-10-12 02:09 ivan
+
+ * TODO: Id to Header
+
+1998-10-12 02:07 ivan
+
+ * TODO: Test keyword substitution
+
+1998-10-12 01:59 ivan
+
+ * TODO: Commiting sample change.
+
+1998-10-12 00:18 ivan
+
+ * conf/registries/internic/: to, tech_contact: Initial revision
+
+1998-10-12 00:15 ivan
+
+ * conf/: shells, registries/internic/nameservers,
+ registries/internic/from: Initial revision
+
+1998-10-12 00:12 ivan
+
+ * conf/: address, home, lpr, registries/internic/template, secrets,
+ smtpmachine, domain: Initial revision
+
+1998-10-12 00:08 ivan
+
+ * TODO: Initial revision
+
+1998-10-12 00:03 ivan
+
+ * bin/fs-setup: Initial revision
+
+1998-10-12 00:00 ivan
+
+ * site_perl/: Conf.pm, Invoice.pm: Initial revision
+
+1998-10-11 23:56 ivan
+
+ * README, site_perl/Record.pm: Initial revision
+
+1998-10-06 19:17 ivan
+
+ * htdocs/docs/: upgrade2.html, index.html: Initial revision
+
+1998-10-06 19:13 ivan
+
+ * htdocs/index.html: Initial revision
+
+1998-09-29 11:55 ivan
+
+ * htdocs/view/svc_acct.cgi: Initial revision
+
+1998-09-27 22:16 ivan
+
+ * htdocs/edit/process/svc_domain.cgi: Initial revision
+
+1998-09-27 16:59 ivan
+
+ * htdocs/images/small-logo.gif: Initial revision
+
+1998-09-27 16:52 ivan
+
+ * htdocs/images/mid-logo.gif: Initial revision
+
+1998-09-25 01:51 ivan
+
+ * htdocs/docs/man/Bill.txt, htdocs/docs/man/CGI.txt,
+ htdocs/docs/man/Conf.txt, htdocs/docs/man/Invoice.txt,
+ htdocs/docs/man/Record.txt, htdocs/docs/man/SSH.txt,
+ htdocs/docs/man/UID.txt, htdocs/docs/man/agent.txt,
+ htdocs/docs/man/agent_type.txt, htdocs/docs/man/cust_bill.txt,
+ htdocs/docs/man/cust_bill_pkg.txt,
+ htdocs/docs/man/cust_credit.txt, htdocs/docs/man/cust_main.txt,
+ htdocs/docs/man/cust_main_county.txt,
+ htdocs/docs/man/cust_pay.txt, htdocs/docs/man/cust_pkg.txt,
+ htdocs/docs/man/cust_refund.txt, htdocs/docs/man/cust_svc.txt,
+ htdocs/docs/man/dbdef.txt, htdocs/docs/man/dbdef_colgroup.txt,
+ htdocs/docs/man/dbdef_column.txt,
+ htdocs/docs/man/dbdef_index.txt, htdocs/docs/man/dbdef_table.txt,
+ htdocs/docs/man/dbdef_unique.txt, htdocs/docs/man/part_pkg.txt,
+ htdocs/docs/man/part_referral.txt, htdocs/docs/man/part_svc.txt,
+ htdocs/docs/man/pkg_svc.txt, htdocs/docs/man/svc_acct.txt,
+ htdocs/docs/man/svc_acct_pop.txt,
+ htdocs/docs/man/svc_acct_sm.txt, htdocs/docs/man/svc_domain.txt,
+ htdocs/docs/man/type_pkgs.txt, bin/pod2x,
+ htdocs/docs/man/index.html: Initial revision
+
+1998-09-25 01:28 ivan
+
+ * site_perl/: cust_pkg.pm, cust_refund.pm: Initial revision
+
+1998-09-25 01:03 ivan
+
+ * site_perl/: dbdef_table.pm, dbdef_column.pm: Initial revision
+
+1998-09-25 00:53 ivan
+
+ * site_perl/: dbdef_index.pm, dbdef_unique.pm: Initial revision
+
+1998-09-25 00:47 ivan
+
+ * site_perl/: dbdef_colgroup.pm, dbdef.pm: Initial revision
+
+1998-09-24 03:18 ivan
+
+ * site_perl/UID.pm: Initial revision
+
+1998-09-24 02:27 ivan
+
+ * site_perl/type_pkgs.pm: Initial revision
+
+1998-09-24 01:59 ivan
+
+ * site_perl/svc_domain.pm: Initial revision
+
+1998-09-24 01:54 ivan
+
+ * site_perl/svc_acct.pm: Initial revision
+
+1998-09-24 01:18 ivan
+
+ * site_perl/svc_acct_sm.pm: Initial revision
+
+1998-09-23 23:20 ivan
+
+ * site_perl/svc_acct_pop.pm: Initial revision
+
+1998-09-23 22:15 ivan
+
+ * site_perl/part_svc.pm: Initial revision
+
+1998-09-23 00:27 ivan
+
+ * site_perl/pkg_svc.pm: Initial revision
+
+1998-09-23 00:23 ivan
+
+ * site_perl/: agent_type.pm, cust_credit.pm, cust_main_county.pm,
+ cust_pay.pm, cust_svc.pm, part_pkg.pm, part_referral.pm: Initial
+ revision
+
+1998-09-21 23:08 ivan
+
+ * site_perl/cust_main.pm: Initial revision
+
+1998-09-21 20:40 ivan
+
+ * site_perl/cust_bill_pkg.pm: Initial revision
+
+1998-09-21 19:56 ivan
+
+ * site_perl/: cust_bill.pm, agent.pm: Initial revision
+
+1998-09-21 16:58 ivan
+
+ * site_perl/SSH.pm: Initial revision
+
+1998-09-21 16:49 ivan
+
+ * site_perl/CGI.pm: Initial revision
+
+1998-09-21 16:01 ivan
+
+ * htdocs/docs/config.html: Initial revision
+
+1998-09-20 12:53 ivan
+
+ * site_perl/Bill.pm: Initial revision
+
+1998-09-18 15:14 ivan
+
+ * htdocs/docs/schema.html: Initial revision
+
+1998-09-17 22:43 ivan
+
+ * bin/svc_acct.export: Initial revision
+
+1998-09-17 19:07 ivan
+
+ * htdocs/docs/install.html: Initial revision
+
+1998-09-12 14:33 ivan
+
+ * htdocs/docs/trouble.html: Initial revision
+
+1998-09-02 21:50 ivan
+
+ * CREDITS: Initial revision
+
+1998-09-02 21:09 ivan
+
+ * htdocs/docs/billing.html: Initial revision
+
+1998-09-02 18:57 ivan
+
+ * htdocs/edit/process/: cust_main_county-expand.cgi,
+ cust_main_county.cgi, part_pkg.cgi, part_referral.cgi,
+ part_svc.cgi, svc_acct_pop.cgi: Initial revision
+
+1998-09-02 18:53 ivan
+
+ * htdocs/edit/process/agent_type.cgi: Initial revision
+
+1998-09-02 18:49 ivan
+
+ * htdocs/edit/process/agent.cgi: Initial revision
+
+1998-09-02 18:42 ivan
+
+ * htdocs/: edit/part_referral.cgi, edit/svc_acct_pop.cgi,
+ view/cust_main.cgi: Initial revision
+
+1998-09-02 18:37 ivan
+
+ * htdocs/: browse/svc_acct_pop.cgi,
+ edit/cust_main_county-expand.cgi, edit/cust_main_county.cgi:
+ Initial revision
+
+1998-09-02 18:33 ivan
+
+ * htdocs/browse/: part_referral.cgi, part_svc.cgi: Initial revision
+
+1998-09-02 18:28 ivan
+
+ * htdocs/browse/: cust_main_county.cgi, part_pkg.cgi: Initial
+ revision
+
+1998-09-02 18:24 ivan
+
+ * htdocs/browse/: agent.cgi, agent_type.cgi: Initial revision
+
+1998-08-25 14:51 ivan
+
+ * htdocs/docs/export.html: Initial revision
+
+1998-08-23 20:28 ivan
+
+ * htdocs/docs/passwd.html: Initial revision
+
+1998-08-23 20:12 ivan
+
+ * fs_passwd/fs_passwd_server: Initial revision
+
+1998-08-23 20:04 ivan
+
+ * fs_passwd/fs_passwd: Initial revision
+
+1998-08-23 19:01 ivan
+
+ * bin/bill: Initial revision
+
+1998-08-23 16:39 ivan
+
+ * htdocs/docs/legacy.html: Initial revision
+
+1998-08-23 16:19 ivan
+
+ * htdocs/docs/admin.html: Initial revision
+
+1998-08-19 21:42 ivan
+
+ * eg/TEMPLATE_cust_main.import: Initial revision
+
+1998-08-16 14:41 ivan
+
+ * htdocs/search/svc_acct.cgi: Initial revision
+
+1998-08-16 14:02 ivan
+
+ * bin/svc_acct.import: Initial revision
+
+1998-08-14 15:11 ivan
+
+ * bin/svc_acct_sm.export: Initial revision
+
+1998-08-12 21:15 ivan
+
+ * htdocs/docs/upgrade.html: Initial revision
+
+1998-08-12 20:55 ivan
+
+ * Artistic: Initial revision
+
+1998-08-12 18:04 ivan
+
+ * htdocs/docs/CGI-modules-2.76-patch.txt: Initial revision
+
+1998-07-26 14:32 ivan
+
+ * htdocs/search/svc_acct_sm.cgi: Initial revision
+
+1998-07-26 14:24 ivan
+
+ * htdocs/: view/svc_acct_sm.cgi, edit/svc_acct_sm.cgi: Initial
+ revision
+
+1998-07-18 17:37 ivan
+
+ * htdocs/edit/process/svc_acct_sm.cgi: Initial revision
+
+1998-07-18 17:13 ivan
+
+ * htdocs/search/cust_main.cgi: Initial revision
+
+1998-07-18 16:39 ivan
+
+ * htdocs/misc/cancel_pkg.cgi: Initial revision
+
+1998-07-18 00:24 ivan
+
+ * htdocs/edit/svc_domain.cgi: Initial revision
+
+1998-07-18 00:11 ivan
+
+ * etc/domain-template.txt: Initial revision
+
+1998-07-17 22:42 ivan
+
+ * htdocs/search/svc_domain.cgi: Initial revision
+
+1998-07-17 01:52 ivan
+
+ * htdocs/search/cust_pkg.cgi: Initial revision
+
+1998-07-17 00:43 ivan
+
+ * bin/svc_acct_sm.import: Initial revision
+
+1998-07-13 12:32 ivan
+
+ * htdocs/edit/svc_acct.cgi: Initial revision
+
+1998-07-13 10:52 ivan
+
+ * htdocs/edit/cust_main.cgi: Initial revision
+
+1998-07-12 13:29 ivan
+
+ * htdocs/edit/agent.cgi: Initial revision
+
+1998-07-12 13:25 ivan
+
+ * htdocs/edit/agent_type.cgi: Initial revision
+
+1998-07-12 13:18 ivan
+
+ * htdocs/edit/part_pkg.cgi: Initial revision
+
+1998-07-12 12:51 ivan
+
+ * htdocs/edit/part_svc.cgi: Initial revision
+
+1998-07-10 20:49 ivan
+
+ * htdocs/view/cust_bill.cgi: Initial revision
+
+1998-07-02 02:31 ivan
+
+ * htdocs/edit/cust_pkg.cgi: Initial revision
+
+1998-06-24 00:27 ivan
+
+ * htdocs/misc/link.cgi: Initial revision
+
+1998-06-23 23:59 ivan
+
+ * htdocs/misc/process/link.cgi: Initial revision
+
+1998-06-16 19:03 ivan
+
+ * htdocs/misc/print-invoice.cgi: Initial revision
+
+1998-06-03 00:22 ivan
+
+ * bin/dbdef-create: Initial revision
+
+1998-04-16 22:37 ivan
+
+ * htdocs/: edit/process/cust_credit.cgi,
+ edit/process/cust_main.cgi, edit/process/cust_pay.cgi,
+ edit/process/cust_pkg.cgi, edit/process/svc_acct.cgi,
+ misc/bill.cgi, misc/cancel-unaudited.cgi, misc/expire_pkg.cgi,
+ misc/susp_pkg.cgi, misc/unsusp_pkg.cgi, search/cust_bill.cgi,
+ view/cust_pkg.cgi, view/svc_domain.cgi: Initial revision
+
+1998-04-16 13:34 ivan
+
+ * fs_radlog/fs_radlogd: Initial revision
+
+1998-03-23 00:20 ivan
+
+ * fs_passwd/fs_passwdd: Initial revision
+
+1998-03-22 23:46 ivan
+
+ * GPL, INSTALL, etc/acp_logfile-parse, etc/countries.txt,
+ etc/example-direct-cardin, htdocs/edit/cust_credit.cgi,
+ htdocs/edit/cust_pay.cgi, htdocs/images/sisd.jpg,
+ htdocs/search/cust_bill.html,
+ htdocs/search/cust_main-payinfo.html,
+ htdocs/search/cust_main.html, htdocs/search/svc_acct.html,
+ htdocs/search/svc_acct_sm.html, htdocs/search/svc_domain.html,
+ site_perl/table_template-svc.pm,
+ site_perl/table_template-unique.pm, site_perl/table_template.pm:
+ Initial revision
+
diff --git a/FS/FS.pm b/FS/FS.pm
index c4be977..7ce9741 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -102,6 +102,8 @@ L<FS::cust_main_county> - Locale (tax rate) class
L<FS::cust_tax_exempt> - Tax exemption record class
+L<FS::cust_tax_adjustment> - Tax adjustment record class
+
L<FS::cust_tax_exempt_pkg> - Line-item specific tax exemption record class
L<FS::svc_Common> - Service base class
@@ -136,6 +138,10 @@ L<FS::part_virtual_field> - Broadband virtual field class
L<FS::svc_phone> - Phone service class
+L<FS::phone_device> - Phone device class
+
+L<FS::part_device> - Device definition class
+
L<FS::phone_avail> - Phone number availability cache
L<FS::cdr> - Call Detail Record class
@@ -144,8 +150,6 @@ L<FS::cdr_calltype> - CDR calltype class
L<FS::cdr_carrier> - CDR carrier class
-L<FS::cdr_upstream_rate> - CDR upstream rate class
-
L<FS::cdr_type> - CDR type class
L<FS::svc_external> - Externally tracked service class.
@@ -165,7 +169,7 @@ L<FS::part_export> - External provisioning export class
L<FS::part_export_option> - Export option class
-L<FS::pkg_category> - Package category class
+L<FS::pkg_category> - Package category class (invoice oriented)
L<FS::pkg_class> - Package class class
@@ -177,6 +181,8 @@ L<FS::part_pkg_taxclass> - Tax class class
L<FS::part_pkg_option> - Package definition option class
+L<FS::part_pkg_report_option> - Package reporting classification class
+
L<FS::pkg_svc> - Class linking package definitions (see L<FS::part_pkg>) with
service definitions (see L<FS::part_svc>)
@@ -228,12 +234,16 @@ L<FS::cust_main_Mixin> - Mixin class for records that contain fields from cust_m
L<FS::cust_main_invoice> - Invoice destination class
+L<FS::cust_main_exemption> - Customer tax exemption class
+
L<FS::cust_main_note> - Customer note class
L<FS::banned_pay> - Banned payment information class
L<FS::cust_bill> - Invoice class
+L<FS::cust_statement> - Informational statement class
+
L<FS::cust_bill_pkg> - Invoice line item class
L<FS::cust_bill_pkg_detail> - Invoice line item detail class
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 93660e2..a54d270 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -94,11 +94,10 @@ tie my %rights, 'Tie::IxHash',
'View customer',
#'View Customer | View tickets',
'Edit customer',
+ 'View customer history',
'Cancel customer',
'Complimentary customer', #aka users-allow_comp
{ rightname=>'Delete customer', desc=>"Enable customer deletions. Be very careful! Deleting a customer will remove all traces that this customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customer's packages if they cancel service." }, #aka. deletecustomers
- 'Add customer note', #NEW
- 'Edit customer note', #NEW
'Bill customer now', #NEW
'Bulk send customer notices', #NEW
],
@@ -140,6 +139,7 @@ tie my %rights, 'Tie::IxHash',
'Edit www config', #NEW
'Edit domain catchall', #NEW
'Edit domain nameservice', #NEW
+ 'Manage domain registration',
{ rightname=>'View/link unlinked services', global=>1 }, #not agent-virtualizable without more work
],
@@ -150,7 +150,9 @@ tie my %rights, 'Tie::IxHash',
'Customer invoice / financial info rights' => [
'View invoices',
'Resend invoices', #NEWNEW
+ 'Delete invoices', #new, but no need to phase in
'View customer tax exemptions', #yow
+ 'Add customer tax adjustment', #new, but no need to phase in
'View customer batched payments', #NEW
'View customer pending payments', #NEW
'Edit customer pending payments', #NEW
@@ -197,6 +199,21 @@ tie my %rights, 'Tie::IxHash',
],
+
+ ###
+ # note/attachment rights...
+ ###
+ 'Customer note and attachment rights' => [
+ 'Add customer note', #NEW
+ 'Edit customer note', #NEW
+ 'Download attachment', #NEW
+ 'Add attachment', #NEW
+ 'Edit attachment', #NEW
+ 'Delete attachment', #NEW
+ 'View deleted attachments', #NEW
+ 'Undelete attachment', #NEW
+ 'Purge attachment', #NEW
+ ],
###
# report/listing rights...
@@ -210,6 +227,7 @@ tie my %rights, 'Tie::IxHash',
{ rightname=> 'List rating data', desc=>'Usage reports', global=>1 },
'Billing event reports',
+ 'Receivables report',
'Financial reports',
],
@@ -221,6 +239,7 @@ tie my %rights, 'Tie::IxHash',
{ rightname=>'Time queue', global=>1 },
{ rightname=>'Process batches', global=>1 },
{ rightname=>'Reprocess batches', global=>1 },
+ { rightname=>'Redownload resolved batches', global=>1 },
{ rightname=>'Import', global=>1 }, #some of these are ag-virt'ed now? give em their own ACLs
{ rightname=>'Export', global=>1 },
{ rightname=> 'Edit rating data', desc=>'Delete CDRs', global=>1 },
@@ -267,14 +286,38 @@ tie my %rights, 'Tie::IxHash',
=item rights
-Returns a list of right names.
+Returns the full list of right names.
=cut
- sub rights {
+sub rights {
#my $class = shift;
map { ref($_) ? $_->{'rightname'} : $_ } map @{ $rights{$_} }, keys %rights;
- }
+}
+
+=item default_superuser_rights
+
+Most (but not all) right names.
+
+=cut
+
+sub default_superuser_rights {
+ my $class = shift;
+ my %omit = map { $_=>1 } (
+ 'Delete customer',
+ 'Delete invoices',
+ 'Delete payment',
+ 'Delete credit', #?
+ 'Delete refund', #?
+ 'Time queue',
+ 'Redownload resolved batches',
+ 'Raw SQL',
+ 'Configuration download',
+ );
+
+ no warnings 'uninitialized';
+ grep { ! $omit{$_} } $class->rights;
+}
=item rights_info
diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm
index 7ad1dc2..f33a718 100644
--- a/FS/FS/CGI.pm
+++ b/FS/FS/CGI.pm
@@ -241,7 +241,7 @@ sub rooturl {
(browse|config|docs|edit|graph|misc|search|view|pref|rt|elements)
/
(process/)?
- ([\w\-\.\/]+)
+ ([\w\-\.\/]*)
$
}
{}x;
diff --git a/FS/FS/ClientAPI/Bulk.pm b/FS/FS/ClientAPI/Bulk.pm
new file mode 100644
index 0000000..ec617df
--- /dev/null
+++ b/FS/FS/ClientAPI/Bulk.pm
@@ -0,0 +1,384 @@
+package FS::ClientAPI::Bulk;
+
+use strict;
+
+use vars qw( $DEBUG $cache );
+use Date::Parse;
+use FS::Record qw( qsearchs );
+use FS::Conf;
+use FS::ClientAPI_SessionCache;
+use FS::cust_main;
+use FS::cust_pkg;
+use FS::cust_svc;
+use FS::svc_acct;
+use FS::svc_external;
+use FS::cust_recon;
+use Data::Dumper;
+
+$DEBUG = 1;
+
+sub _cache {
+ $cache ||= new FS::ClientAPI_SessionCache ( {
+ 'namespace' => 'FS::ClientAPI::Agent', #yes, share session_ids
+ } );
+}
+
+sub _izoom_ftp_row_fixup {
+ my $hash = shift;
+
+ my @addr_fields = qw( address1 address2 city state zip );
+ my @fields = ( qw( agent_custid username _password first last ),
+ @addr_fields,
+ map { "ship_$_" } @addr_fields );
+
+ $hash->{$_} =~ s/[&\/\*'"]/_/g foreach @fields;
+
+ #$hash->{action} = '' if $hash->{action} eq 'R'; #unsupported for ftp
+
+ $hash->{refnum} = 1; #ahem
+ $hash->{country} = 'US';
+ $hash->{ship_country} = 'US';
+ $hash->{payby} = 'LECB';
+ $hash->{payinfo} = $hash->{daytime};
+ $hash->{ship_fax} = '' if ( !$hash->{sms} || $hash->{sms} eq 'F' );
+
+ my $has_ship =
+ grep { $hash->{"ship_$_"} &&
+ (! $hash->{$_} || $hash->{"ship_$_"} ne $hash->{$_} )
+ }
+ ( @addr_fields, 'fax' );
+
+ if ( $has_ship ) {
+ foreach ( @addr_fields, qw( first last ) ) {
+ $hash->{"ship_$_"} = $hash->{$_} unless $hash->{"ship_$_"};
+ }
+ }
+
+ delete $hash->{sms};
+
+ '';
+
+};
+
+sub _izoom_ftp_result {
+ my ($hash, $error) = @_;
+ my $cust_main =
+ qsearchs( 'cust_main', { 'agent_custid' => $hash->{agent_custid},
+ 'agentnum' => $hash->{agentnum}
+ }
+ );
+
+ my $custnum = $cust_main ? $cust_main->custnum : '';
+ my @response = ( $hash->{action}, $hash->{agent_custid}, $custnum );
+
+ if ( $error ) {
+ push @response, ( 'ERROR', $error );
+ } else {
+ push @response, ( 'OK', 'OK' );
+ }
+
+ join( ',', @response );
+
+}
+
+sub _izoom_ftp_badaction {
+ "Invalid action: $_[0] record: @_ ";
+}
+
+sub _izoom_soap_row_fixup { _izoom_ftp_row_fixup(@_) };
+
+sub _izoom_soap_result {
+ my ($hash, $error) = @_;
+
+ if ( $hash->{action} eq 'R' ) {
+ if ( $error ) {
+ return "Please check errors:\n $error"; # odd extra space
+ } else {
+ return join(' ', "Everything ok.", $hash->{pkg}, $hash->{adjourn} );
+ }
+ }
+
+ my $pkg = $hash->{pkg} || $hash->{saved_pkg} || '';
+ if ( $error ) {
+ return join(' ', $hash->{agent_custid}, $error );
+ } else {
+ return join(' ', $hash->{agent_custid}, $pkg, $hash->{adjourn} );
+ }
+
+}
+
+sub _izoom_soap_badaction {
+ "Unknown action '$_[13]' ";
+}
+
+my %format = (
+ 'izoom-ftp' => {
+ 'fields' => [ qw ( action agent_custid username _password
+ daytime ship_fax sms first last
+ address1 address2 city state zip
+ pkg adjourn ship_address1 ship_address2
+ ship_city ship_state ship_zip ) ],
+ 'fixup' => sub { _izoom_ftp_row_fixup(@_) },
+ 'result' => sub { _izoom_ftp_result(@_) },
+ 'action' => sub { _izoom_ftp_badaction(@_) },
+ },
+ 'izoom-soap' => {
+ 'fields' => [ qw ( agent_custid username _password
+ daytime first last address1 address2
+ city state zip pkg action adjourn
+ ship_fax sms ship_address1 ship_address2
+ ship_city ship_state ship_zip ) ],
+ 'fixup' => sub { _izoom_soap_row_fixup(@_) },
+ 'result' => sub { _izoom_soap_result(@_) },
+ 'action' => sub { _izoom_soap_badaction(@_) },
+ },
+);
+
+sub processrow {
+ my $p = shift;
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $conf = new FS::Conf;
+ my $format = $conf->config('selfservice-bulk_format', $session->{agentnum})
+ || 'izoom-soap';
+ my ( @row ) = @{ $p->{row} };
+
+ warn "processrow called with '". join("' '", @row). "'\n" if $DEBUG;
+
+ return { 'error' => "unknown format: $format" }
+ unless exists $format{$format};
+
+ return { 'error' => "Invalid record record length: ". scalar(@row).
+ "record: @row " #sic
+ }
+ unless scalar(@row) == scalar(@{$format{$format}{fields}});
+
+ my %hash = ( 'agentnum' => $session->{agentnum} );
+ my $error;
+
+ foreach my $field ( @{ $format{ $format }{ fields } } ) {
+ $hash{$field} = shift @row;
+ }
+
+ $error ||= &{ $format{ $format }{ fixup } }( \%hash );
+
+ # put in the fixup routine?
+ if ( 'R' eq $hash{action} ) {
+ warn "processing reconciliation\n" if $DEBUG;
+ $error ||= process_recon($hash{agentnum}, $hash{agent_custid});
+ } elsif ( 'P' eq $hash{action} ) {
+ # do nothing
+ } elsif( 'D' eq $hash{action} ) {
+ $hash{promo_pkg} = 'disk-1-'. $session->{agent};
+ } elsif ( 'S' eq $hash{action} ) {
+ $hash{promo_pkg} = 'disk-2-'. $session->{agent};
+ $hash{saved_pkg} = $hash{pkg};
+ $hash{pkg} = '';
+ } else {
+ $error ||= &{ $format{ $format }{ action } }( @row );
+ }
+
+ warn "processing provision\n" if ($DEBUG && !$error && $hash{action} ne 'R');
+ $error ||= provision( %hash ) unless $hash{action} eq 'R';
+
+ my $result = &{ $format{ $format }{ result } }( \%hash, $error );
+
+ warn "processrow returning '". join("' '", $result, $error). "'\n"
+ if $DEBUG;
+
+ return { 'error' => $error, 'message' => $result };
+
+}
+
+sub provision {
+ my %args = ( @_ );
+
+ delete $args{action};
+
+ my $cust_main =
+ qsearchs( 'cust_main',
+ { map { $_ => $args{$_} } qw ( agent_custid agentnum ) },
+ );
+
+ unless ( $cust_main ) {
+ $cust_main = new FS::cust_main { %args };
+ my $error = $cust_main->insert;
+ return $error if $error;
+ }
+
+ my @pkgs = grep { $_->part_pkg->freq } $cust_main->ncancelled_pkgs;
+ if ( scalar(@pkgs) > 1 ) {
+ return "Invalid account, should not be more then one active package ". #sic
+ "but found: ". scalar(@pkgs). " packages.";
+ }
+
+ my $part_pkg = qsearchs( 'part_pkg', { 'pkg' => $args{pkg} } )
+ or return "Unknown pkgpart: $args{pkg}"
+ if $args{pkg};
+
+
+ my $create_package = $args{pkg};
+ if ( scalar(@pkgs) && $create_package ) {
+ my $pkg = pop(@pkgs);
+
+ if ( $part_pkg->pkgpart != $pkg->pkgpart ) {
+ my @cust_bill_pkg = $pkg->cust_bill_pkg();
+ if ( 1 == scalar(@cust_bill_pkg) ) {
+ my $cbp= pop(@cust_bill_pkg);
+ my $cust_bill = $cbp->cust_bill;
+ $cust_bill->delete(); #really? wouldn't a credit be better?
+ }
+ $pkg->cancel();
+ } else {
+ $create_package = '';
+ $pkg->setfield('adjourn', str2time($args{adjourn}));
+ my $error = $pkg->replace();
+ return $error if $error;
+ }
+ }
+
+ if ( $create_package ) {
+ my $cust_pkg = new FS::cust_pkg ( {
+ 'pkgpart' => $part_pkg->pkgpart,
+ 'adjourn' => str2time( $args{adjourn} ),
+ } );
+
+ my $svcpart = $part_pkg->svcpart('svc_acct');
+
+ my $svc_acct = new FS::svc_acct ( {
+ 'svcpart' => $svcpart,
+ 'username' => $args{username},
+ '_password' => $args{_password},
+ } );
+
+ my $error = $cust_main->order_pkg( cust_pkg => $cust_pkg,
+ svcs => [ $svc_acct ],
+ );
+ return $error if $error;
+ }
+
+ if ( $args{promo_pkg} ) {
+ my $part_pkg =
+ qsearchs( 'part_pkg', { 'promo_code' => $args{promo_pkg} } )
+ or return "unknown pkgpart: $args{promo_pkg}";
+
+ my $svcpart = $part_pkg->svcpart('svc_external')
+ or return "unknown svcpart: svc_external";
+
+ my $cust_pkg = new FS::cust_pkg ( {
+ 'svcpart' => $svcpart,
+ 'pkgpart' => $part_pkg->pkgpart,
+ } );
+
+ my $svc_ext = new FS::svc_external ( { 'svcpart' => $svcpart } );
+
+ my $ticket_subject = 'Send setup disk to customer '. $cust_main->custnum;
+ my $error = $cust_main->order_pkg ( cust_pkg => $cust_pkg,
+ svcs => [ $svc_ext ],
+ noexport => 1,
+ ticket_subject => $ticket_subject,
+ ticket_queue => "disk-$args{agentnum}",
+ );
+ return $error if $error;
+ }
+
+ my $error = $cust_main->bill();
+ return $error if $error;
+}
+
+sub process_recon {
+ my ( $agentnum, $id ) = @_;
+ my @recs = split /;/, $id;
+ my $err = '';
+ foreach my $rec ( @recs ) {
+ my @record = split /,/, $rec;
+ my $result = process_recon_record(@record, $agentnum);
+ $err .= "$result\n" if $result;
+ }
+ return $err;
+}
+
+sub process_recon_record {
+ my ( $agent_custid, $username, $_password, $daytime, $first, $last, $address1, $address2, $city, $state, $zip, $pkg, $adjourn, $agentnum) = @_;
+
+ warn "process_recon_record called with '". join("','", @_). "'\n" if $DEBUG;
+
+ my ($cust_pkg, $package);
+
+ my $cust_main =
+ qsearchs( 'cust_main',
+ { 'agent_custid' => $agent_custid, 'agentnum' => $agentnum },
+ );
+
+ my $comments = '';
+ if ( $cust_main ) {
+ my @cust_pkg = grep { $_->part_pkg->freq } $cust_main->ncancelled_pkgs;
+ if ( scalar(@cust_pkg) == 1) {
+ $cust_pkg = pop(@cust_pkg);
+ $package = $cust_pkg->part_pkg->pkg;
+ $comments = "$agent_custid wrong package, expected: $pkg found: $package"
+ if ( $pkg ne $package );
+ } else {
+ $comments = "invalid account, should be one active package but found: ".
+ scalar(@cust_pkg). " packages.";
+ }
+ } else {
+ $comments =
+ "Customer not found agent_custid=$agent_custid, agentnum=$agentnum";
+ }
+
+ my $cust_recon = new FS::cust_recon( {
+ 'recondate' => time,
+ 'agentnum' => $agentnum,
+ 'first' => $first,
+ 'last' => $last,
+ 'address1' => $address1,
+ 'address2' => $address2,
+ 'city' => $city,
+ 'state' => $state,
+ 'zip' => $zip,
+ 'custnum' => $cust_main ? $cust_main->custnum : '', #really?
+ 'status' => $cust_main ? $cust_main->status : '',
+ 'pkg' => $package,
+ 'adjourn' => $cust_pkg ? $cust_pkg->adjourn : '',
+ 'agent_custid' => $agent_custid, # redundant?
+ 'agent_pkg' => $pkg,
+ 'agent_adjourn' => str2time($adjourn),
+ 'comments' => $comments,
+ } );
+
+ warn Dumper($cust_recon) if $DEBUG;
+ my $error = $cust_recon->insert;
+ return $error if $error;
+
+ warn "process_recon_record returning $comments\n" if $DEBUG;
+
+ $comments;
+
+}
+
+sub check_username {
+ my $p = shift;
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $svc_domain = qsearchs( 'svc_domain', { 'domain' => $p->{domain} } )
+ or return { 'error' => 'Unknown domain '. $p->{domain} };
+
+ my $svc_acct = qsearchs( 'svc_acct', { 'username' => $p->{user},
+ 'domsvc' => $svc_domain->svcnum,
+ },
+ );
+
+ return { 'error' => $p->{user}. '@'. $p->{domain}. " alerady in use" } # sic
+ if $svc_acct;
+
+ return { 'error' => '',
+ 'message' => $p->{user}. '@'. $p->{domain}. " is free"
+ };
+}
+
+1;
diff --git a/FS/FS/ClientAPI/MasonComponent.pm b/FS/FS/ClientAPI/MasonComponent.pm
index 78ea9bd..88baf07 100644
--- a/FS/FS/ClientAPI/MasonComponent.pm
+++ b/FS/FS/ClientAPI/MasonComponent.pm
@@ -1,9 +1,14 @@
package FS::ClientAPI::MasonComponent;
use strict;
-use vars qw($DEBUG $me);
+use vars qw( $cache $DEBUG $me );
+use subs qw( _cache );
use FS::Mason qw( mason_interps );
use FS::Conf;
+use FS::ClientAPI_SessionCache;
+use FS::Record qw( qsearch qsearchs );
+use FS::cust_main;
+use FS::part_pkg;
$DEBUG = 0;
$me = '[FS::ClientAPI::MasonComponent]';
@@ -13,6 +18,54 @@ my %allowed_comps = map { $_=>1 } qw(
/misc/areacodes.cgi
/misc/exchanges.cgi
/misc/phonenums.cgi
+ /misc/states.cgi
+ /misc/counties.cgi
+ /misc/svc_acct-domains.cgi
+ /misc/part_svc-columns.cgi
+);
+
+my %session_comps = map { $_=>1 } qw(
+ /elements/location.html
+ /edit/cust_main/first_pkg/select-part_pkg.html
+);
+
+my %session_callbacks = (
+
+ '/elements/location.html' => sub {
+ my( $custnum, $argsref ) = @_;
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return "unknown custnum $custnum";
+ my %args = @$argsref;
+ $args{object} = $cust_main;
+ @$argsref = ( %args );
+ return ''; #no error
+ },
+
+ '/edit/cust_main/first_pkg/select-part_pkg.html' => sub {
+ my( $custnum, $argsref ) = @_;
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return "unknown custnum $custnum";
+
+ my $pkgpart = $cust_main->agent->pkgpart_hashref;
+
+ #false laziness w/ edit/cust_main/first_pkg.html
+ my @first_svc = ( 'svc_acct', 'svc_phone' );
+
+ my @part_pkg =
+ grep { $_->svcpart(\@first_svc)
+ && ( $pkgpart->{ $_->pkgpart }
+ || ( $_->agentnum && $_->agentnum == $cust_main->agentnum )
+ )
+ }
+ qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
+
+ my %args = @$argsref;
+ $args{part_pkg} = \@part_pkg;
+ @$argsref = ( %args );
+ return ''; #no error
+
+ },
+
);
my $outbuf;
@@ -24,12 +77,23 @@ sub mason_comp {
warn "$me mason_comp called on $packet\n" if $DEBUG;
my $comp = $packet->{'comp'};
- unless ( $allowed_comps{$comp} ) {
+ unless ( $allowed_comps{$comp} || $session_comps{$comp} ) {
return { 'error' => 'Illegal component' };
}
my @args = $packet->{'args'} ? @{ $packet->{'args'} } : ();
+ if ( $session_comps{$comp} ) {
+
+ my $session = _cache->get($packet->{'session_id'})
+ or return ( 'error' => "Can't resume session" ); #better error message
+ my $custnum = $session->{'custnum'};
+
+ my $error = &{ $session_callbacks{$comp} }( $custnum, \@args );
+ return { 'error' => $error } if $error;
+
+ }
+
my $conf = new FS::Conf;
$FS::Mason::Request::FSURL = $conf->config('selfservice_server-base_url');
$FS::Mason::Request::QUERY_STRING = $packet->{'query_string'} || '';
@@ -43,4 +107,11 @@ sub mason_comp {
}
+#hmm
+sub _cache {
+ $cache ||= new FS::ClientAPI_SessionCache( {
+ 'namespace' => 'FS::ClientAPI::MyAccount',
+ } );
+}
+
1;
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index c0586af..26cd76f 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -10,7 +10,7 @@ use Business::CreditCard;
use Time::Duration;
use FS::UI::Web::small_custview qw(small_custview); #less doh
use FS::UI::Web;
-use FS::UI::bytecount;
+use FS::UI::bytecount qw( display_bytecount );
use FS::Conf;
use FS::Record qw(qsearch qsearchs);
use FS::Msgcat qw(gettext);
@@ -55,12 +55,35 @@ sub _cache {
} );
}
+sub skin_info {
+ #my $p = shift;
+
+ my $conf = new FS::Conf;
+
+ use vars qw($skin_info); #cache for performance.
+ #agentnum eventually...? but if they're not logged in yet.. ?
+
+ $skin_info ||= {
+ 'head' => join("\n", $conf->config('selfservice-head') ),
+ 'body_header' => join("\n", $conf->config('selfservice-body_header') ),
+ 'body_footer' => join("\n", $conf->config('selfservice-body_footer') ),
+ 'body_bgcolor' => scalar( $conf->config('selfservice-body_bgcolor') ),
+ 'box_bgcolor' => scalar( $conf->config('selfservice-box_bgcolor') ),
+
+ 'company_name' => scalar($conf->config('company_name')),
+ };
+
+ $skin_info;
+
+}
+
sub login_info {
my $p = shift;
my $conf = new FS::Conf;
my %info = (
+ %{ skin_info() },
'phone_login' => $conf->exists('selfservice_server-phone_login'),
'single_domain'=> scalar($conf->config('selfservice_server-single_domain')),
);
@@ -103,16 +126,6 @@ sub login {
);
return { error => 'User not found.' } unless $svc_acct;
- #my $pkg_svc = $svc_acct->cust_svc->pkg_svc;
- #return { error => 'Only primary user may log in.' }
- # if $conf->exists('selfservice_server-primary_only')
- # && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' );
- my $cust_svc = $svc_acct->cust_svc;
- my $part_pkg = $cust_svc->cust_pkg->part_pkg;
- return { error => 'Only primary user may log in.' }
- if $conf->exists('selfservice_server-primary_only')
- && $cust_svc->svcpart != $part_pkg->svcpart('svc_acct');
-
return { error => 'Incorrect password.' }
unless $svc_acct->check_password($p->{'password'});
@@ -124,12 +137,28 @@ sub login {
'svcnum' => $svc_x->svcnum,
};
- my $cust_pkg = $svc_x->cust_svc->cust_pkg;
+ my $cust_svc = $svc_x->cust_svc;
+ my $cust_pkg = $cust_svc->cust_pkg;
if ( $cust_pkg ) {
my $cust_main = $cust_pkg->cust_main;
$session->{'custnum'} = $cust_main->custnum;
+ if ( $conf->exists('pkg-balances') ) {
+ my @cust_pkg = grep { $_->part_pkg->freq !~ /^(0|$)/ }
+ $cust_main->ncancelled_pkgs;
+ $session->{'pkgnum'} = $cust_pkg->pkgnum
+ if scalar(@cust_pkg) > 1;
+ }
}
+ #my $pkg_svc = $svc_acct->cust_svc->pkg_svc;
+ #return { error => 'Only primary user may log in.' }
+ # if $conf->exists('selfservice_server-primary_only')
+ # && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' );
+ my $part_pkg = $cust_pkg->part_pkg;
+ return { error => 'Only primary user may log in.' }
+ if $conf->exists('selfservice_server-primary_only')
+ && $cust_svc->svcpart != $part_pkg->svcpart([qw( svc_acct svc_phone )]);
+
my $session_id;
do {
$session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
@@ -147,12 +176,59 @@ sub logout {
my $p = shift;
if ( $p->{'session_id'} ) {
_cache->remove($p->{'session_id'});
- return { 'error' => '' };
+ return { %{ skin_info() }, 'error' => '' };
} else {
- return { 'error' => "Can't resume session" }; #better error message
+ return { %{ skin_info() }, 'error' => "Can't resume session" }; #better error message
}
}
+sub access_info {
+ my $p = shift;
+
+ my $conf = new FS::Conf;
+
+ my $info = skin_info($p);
+
+ use vars qw( $cust_paybys ); #cache for performance
+ unless ( $cust_paybys ) {
+
+ my %cust_paybys = map { $_ => 1 }
+ map { FS::payby->payby2payment($_) }
+ $conf->config('signup_server-payby');
+
+ $cust_paybys = [ keys %cust_paybys ];
+
+ }
+ $info->{'cust_paybys'} = $cust_paybys;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ $info->{hide_payment_fields} =
+ [
+ map { my $pg = '';
+ if ( FS::payby->realtime($_) ) {
+ $pg = $cust_main->agent->payment_gateway(
+ 'method' => FS::payby->payby2bop($_),
+ 'nofatal' => 1,
+ );
+ }
+ $pg && $pg->gateway_namespace eq 'Business::OnlineThirdPartyPayment';
+ }
+ @{ $info->{cust_paybys} }
+ ];
+
+ return { %$info,
+ 'custnum' => $custnum,
+ 'pkgnum' => $session->{'pkgnum'},
+ 'svcnum' => $session->{'svcnum'},
+ 'nonprimary' => $session->{'nonprimary'},
+ };
+}
+
sub customer_info {
my $p = shift;
@@ -175,21 +251,32 @@ sub customer_info {
my $cust_main = qsearchs('cust_main', $search )
or return { 'error' => "unknown custnum $custnum" };
- $return{balance} = $cust_main->balance;
+ if ( $session->{'pkgnum'} ) {
+ $return{balance} = $cust_main->balance_pkgnum( $session->{'pkgnum'} );
+ } else {
+ $return{balance} = $cust_main->balance;
+ }
$return{tickets} = [ ($cust_main->tickets) ];
- my @open = map {
- {
- invnum => $_->invnum,
- date => time2str("%b %o, %Y", $_->_date),
- owed => $_->owed,
- };
- } $cust_main->open_cust_bill;
- $return{open_invoices} = \@open;
+ unless ( $session->{'pkgnum'} ) {
+ my @open = map {
+ {
+ invnum => $_->invnum,
+ date => time2str("%b %o, %Y", $_->_date),
+ owed => $_->owed,
+ };
+ } $cust_main->open_cust_bill;
+ $return{open_invoices} = \@open;
+ }
$return{small_custview} =
- small_custview( $cust_main, $conf->config('countrydefault') );
+ small_custview( $cust_main,
+ scalar($conf->config('countrydefault')),
+ ( $session->{'pkgnum'} ? 1 : 0 ), #nobalance
+ );
+
+ warn $return{small_custview};
$return{name} = $cust_main->first. ' '. $cust_main->get('last');
@@ -281,7 +368,8 @@ sub edit_info {
$new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' );
- }elsif ( $payby =~ /^(CHEK|DCHK)$/ ) {
+ } elsif ( $payby =~ /^(CHEK|DCHK)$/ ) {
+
my $payinfo;
$p->{'payinfo1'} =~ /^([\dx]+)$/
or return { 'error' => "illegal account number ". $p->{'payinfo1'} };
@@ -291,15 +379,15 @@ sub edit_info {
my $payinfo2 = $1;
$payinfo = $payinfo1. '@'. $payinfo2;
- if ( $payinfo eq $cust_main->paymask ) {
- $new->payinfo($cust_main->payinfo);
- } else {
- $new->payinfo($payinfo);
- }
+ $new->payinfo( ($payinfo eq $cust_main->paymask)
+ ? $cust_main->payinfo
+ : $payinfo
+ );
$new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' );
- }elsif ( $payby =~ /^(BILL)$/ ) {
+ } elsif ( $payby =~ /^(BILL)$/ ) {
+ #no-op
} elsif ( $payby ) { #notyet ready
return { 'error' => "unknown payby $payby" };
}
@@ -338,6 +426,12 @@ sub payment_info {
'country' => $conf->config('countrydefault') || 'US'
} );
+ my %cust_paybys = map { $_ => 1 }
+ map { FS::payby->payby2payment($_) }
+ $conf->config('signup_server-payby');
+
+ my @cust_paybys = keys %cust_paybys;
+
$payment_info = {
#list all counties/states/countries
@@ -353,6 +447,7 @@ sub payment_info {
'paytypes' => [ @FS::cust_main::paytypes ],
'paybys' => [ $conf->config('signup_server-payby') ],
+ 'cust_paybys' => \@cust_paybys,
'stateid_label' => FS::Msgcat::_gettext('stateid'),
'stateid_state_label' => FS::Msgcat::_gettext('stateid_state'),
@@ -375,7 +470,21 @@ sub payment_info {
my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
or return { 'error' => "unknown custnum $custnum" };
- $return{balance} = $cust_main->balance;
+ $return{hide_payment_fields} =
+ [
+ map { my $pg = '';
+ if ( FS::payby->realtime($_) ) {
+ $pg = $cust_main->agent->payment_gateway(
+ 'method' => FS::payby->payby2bop($_),
+ 'nofatal' => 1,
+ );
+ }
+ $pg && $pg->gateway_namespace eq 'Business::OnlineThirdPartyPayment';
+ }
+ @{ $return{cust_paybys} }
+ ];
+
+ $return{balance} = $cust_main->balance; #XXX pkg-balances?
$return{payname} = $cust_main->payname
|| ( $cust_main->first. ' '. $cust_main->get('last') );
@@ -436,6 +545,7 @@ sub process_payment {
or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} };
my $paybatch = $1;
+ $p->{'payby'} ||= 'CARD';
$p->{'payby'} =~ /^([A-Z]{4})$/
or return { 'error' => "illegal_payby " . $p->{'payby'} };
my $payby = $1;
@@ -460,6 +570,8 @@ sub process_payment {
$payinfo = $p->{'payinfo'};
+ #more intelligent mathing will be needed here if you change
+ #card_masking_method and don't remove existing paymasks
$payinfo = $cust_main->payinfo
if $cust_main->paymask eq $payinfo;
@@ -490,7 +602,8 @@ sub process_payment {
}
my %payby2fields = (
- 'CARD' => [ qw( paystart_month paystart_year payissue address1 address2 city state zip payip ) ],
+ 'CARD' => [ qw( paystart_month paystart_year payissue payip
+ address1 address2 city state zip country ) ],
'CHEK' => [ qw( ss paytype paystate stateid stateid_state payip ) ],
);
@@ -501,6 +614,7 @@ sub process_payment {
'payname' => $payname,
'paybatch' => $paybatch, #this doesn't actually do anything
'paycvv' => $paycvv,
+ 'pkgnum' => $session->{'pkgnum'},
map { $_ => $p->{$_} } @{ $payby2fields{$payby} }
);
return { 'error' => $error } if $error;
@@ -512,15 +626,15 @@ sub process_payment {
if ($payby eq 'CARD' || $payby eq 'DCRD') {
$new->set( $_ => $p->{$_} )
foreach qw( payname paystart_month paystart_year payissue payip
- address1 address2 city state zip payinfo );
+ address1 address2 city state zip country );
$new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' );
} elsif ($payby eq 'CHEK' || $payby eq 'DCHK') {
$new->set( $_ => $p->{$_} )
foreach qw( payname payip paytype paystate
stateid stateid_state );
- $new->set( 'payinfo' => $payinfo );
$new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' );
}
+ $new->set( 'payinfo' => $payinfo );
$new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' );
my $error = $new->replace($cust_main);
return { 'error' => $error } if $error;
@@ -531,6 +645,32 @@ sub process_payment {
}
+sub realtime_collect {
+
+ my $p = shift;
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ my $error = $cust_main->realtime_collect(
+ 'method' => $p->{'method'},
+ 'pkgnum' => $session->{'pkgnum'},
+ 'session_id' => $p->{'session_id'},
+ );
+ return { 'error' => $error } unless ref( $error );
+
+ my $amount = $session->{'pkgnum'}
+ ? $cust_main->balance_pkgnum( $session->{'pkgnum'} )
+ : $cust_main->balance;
+
+ return { 'error' => '', amount => $amount, %$error };
+}
+
sub process_payment_order_pkg {
my $p = shift;
@@ -617,7 +757,14 @@ sub invoice_logo {
#sessioning for this? how do we get the session id to the backend invoice
# template so it can add it to the link, blah
- my $templatename = $p->{'templatename'};
+ my $agentnum = '';
+ if ( $p->{'invnum'} ) {
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $p->{'invnum'} } )
+ or return { 'error' => 'unknown invnum' };
+ $agentnum = $cust_bill->cust_main->agentnum;
+ }
+
+ my $templatename = $p->{'template'} || $p->{'templatename'};
#false laziness-ish w/view/cust_bill-logo.cgi
@@ -631,7 +778,7 @@ sub invoice_logo {
my $filename = "logo$templatename.png";
return { 'error' => '',
- 'logo' => $conf->config_binary($filename),
+ 'logo' => $conf->config_binary($filename, $agentnum),
'content_type' => 'image/png', #should allow gif, jpg too
};
}
@@ -734,10 +881,17 @@ sub list_svcs {
foreach my $cust_pkg ( $p->{'ncancelled'}
? $cust_main->ncancelled_pkgs
: $cust_main->unsuspended_pkgs ) {
+ next if $session->{'pkgnum'} && $cust_pkg->pkgnum != $session->{'pkgnum'};
push @cust_svc, @{[ $cust_pkg->cust_svc ]}; #@{[ ]} to force array context
}
- @cust_svc = grep { $_->part_svc->svcdb eq $p->{'svcdb'} } @cust_svc
- if $p->{'svcdb'};
+ if ( $p->{'svcdb'} ) {
+ my $svcdb = ref($p->{'svcdb'}) eq 'HASH'
+ ? $p->{'svcdb'}
+ : ref($p->{'svcdb'}) eq 'ARRAY'
+ ? { map { $_=>1 } @{ $p->{'svcdb'} } }
+ : { $p->{'svcdb'} => 1 };
+ @cust_svc = grep $svcdb->{ $_->part_svc->svcdb }, @cust_svc
+ }
#@svc_x = sort { $a->domain cmp $b->domain || $a->username cmp $b->username }
# @svc_x;
@@ -745,30 +899,51 @@ sub list_svcs {
{
#no#'svcnum' => $session->{'svcnum'},
'custnum' => $custnum,
- 'svcs' => [ map {
- my $svc_x = $_->svc_x;
- my($label, $value) = $_->label;
- my $part_pkg = $svc_x->cust_svc->cust_pkg->part_pkg;
-
- { 'svcnum' => $_->svcnum,
- 'label' => $label,
- 'value' => $value,
- 'username' => $svc_x->username,
- 'email' => $svc_x->email,
- 'seconds' => $svc_x->seconds,
- 'upbytes' => FS::UI::bytecount::display_bytecount($svc_x->upbytes),
- 'downbytes' => FS::UI::bytecount::display_bytecount($svc_x->downbytes),
- 'totalbytes'=> FS::UI::bytecount::display_bytecount($svc_x->totalbytes),
- 'recharge_amount' => $part_pkg->option('recharge_amount', 1),
- 'recharge_seconds' => $part_pkg->option('recharge_seconds', 1),
- 'recharge_upbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_upbytes', 1)),
- 'recharge_downbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_downbytes', 1)),
- 'recharge_totalbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_totalbytes', 1)),
- # more...
- };
- }
- @cust_svc
- ],
+ 'svcs' => [
+ map {
+ my $svc_x = $_->svc_x;
+ my($label, $value) = $_->label;
+ my $svcdb = $_->part_svc->svcdb;
+ my $part_pkg = $_->cust_pkg->part_pkg;
+
+ my %hash = (
+ 'svcnum' => $_->svcnum,
+ 'svcdb' => $svcdb,
+ 'label' => $label,
+ 'value' => $value,
+ );
+
+ if ( $svcdb eq 'svc_acct' ) {
+ %hash = (
+ %hash,
+ 'username' => $svc_x->username,
+ 'email' => $svc_x->email,
+ 'seconds' => $svc_x->seconds,
+ 'upbytes' => display_bytecount($svc_x->upbytes),
+ 'downbytes' => display_bytecount($svc_x->downbytes),
+ 'totalbytes' => display_bytecount($svc_x->totalbytes),
+
+ 'recharge_amount' => $part_pkg->option('recharge_amount',1),
+ 'recharge_seconds' => $part_pkg->option('recharge_seconds',1),
+ 'recharge_upbytes' =>
+ display_bytecount($part_pkg->option('recharge_upbytes',1)),
+ 'recharge_downbytes' =>
+ display_bytecount($part_pkg->option('recharge_downbytes',1)),
+ 'recharge_totalbytes' =>
+ display_bytecount($part_pkg->option('recharge_totalbytes',1)),
+ # more...
+ );
+
+ } elsif ( $svcdb eq 'svc_phone' ) {
+ %hash = (
+ %hash,
+ );
+ }
+
+ \%hash;
+ }
+ @cust_svc
+ ],
};
}
@@ -778,9 +953,8 @@ sub _list_svc_usage {
my @usage = ();
foreach my $part_export (
map { qsearch ( 'part_export', { 'exporttype' => $_ } ) }
- qw (sqlradius sqlradius_withdomain')
+ qw( sqlradius sqlradius_withdomain )
) {
-
push @usage, @ { $part_export->usage_sessions($begin, $end, $svc_acct) };
}
(@usage);
@@ -813,29 +987,50 @@ sub list_support_usage {
_usage_details(\&_list_support_usage, @_);
}
+sub _list_cdr_usage {
+ my($svc_phone, $begin, $end) = @_;
+ map [ $_->downstream_csv('format' => 'default') ], #XXX config for format
+ $svc_phone->cust_svc->get_cdrs( 'begin'=>$begin, 'end'=>$end, );
+}
+
+sub list_cdr_usage {
+ my $p = shift;
+ _usage_details( \&_list_cdr_usage, $p,
+ 'svcdb' => 'svc_phone',
+ );
+}
+
sub _usage_details {
- my ($callback, $p) = (shift,shift);
+ my($callback, $p, %opt) = @_;
my($context, $session, $custnum) = _custoragent_session_custnum($p);
return { 'error' => $session } if $context eq 'error';
my $search = { 'svcnum' => $p->{'svcnum'} };
$search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
- my $svc_acct = qsearchs ( 'svc_acct', $search );
+
+ my $svcdb = $opt{'svcdb'} || 'svc_acct';
+
+ my $svc_x = qsearchs( $svcdb, $search );
return { 'error' => 'No service selected in list_svc_usage' }
- unless $svc_acct;
+ unless $svc_x;
- my $freq = $svc_acct->cust_svc->cust_pkg->part_pkg->freq;
- my $start = $svc_acct->cust_svc->cust_pkg->setup;
- #my $end = $svc_acct->cust_svc->cust_pkg->bill; # or time?
- my $end = time;
+ my $header = $svcdb eq 'svc_phone'
+ ? [ split(',', FS::cdr::invoice_header('default') ) ] #XXX
+ : [];
- unless($p->{beginning}){
- $p->{beginning} = $svc_acct->cust_svc->cust_pkg->last_bill;
- $p->{ending} = $end;
+ my $cust_pkg = $svc_x->cust_svc->cust_pkg;
+ my $freq = $cust_pkg->part_pkg->freq;
+ my $start = $cust_pkg->setup;
+ #my $end = $cust_pkg->bill; # or time?
+ my $end = time;
+
+ unless ( $p->{beginning} ) {
+ $p->{beginning} = $cust_pkg->last_bill;
+ $p->{ending} = $end;
}
- my (@usage) = &$callback($svc_acct,$p->{beginning},$p->{ending});
+ my (@usage) = &$callback($svc_x, $p->{beginning}, $p->{ending});
#kinda false laziness with FS::cust_main::bill, but perhaps
#we should really change this bit to DateTime and DateTime::Duration
@@ -878,6 +1073,7 @@ sub _usage_details {
'ending' => $p->{ending},
'previous' => ($previous > $start) ? $previous : $start,
'next' => ($next < $end) ? $next : $end,
+ 'header' => $header,
'usage' => \@usage,
};
}
@@ -921,7 +1117,7 @@ sub order_pkg {
my %fields = (
'svc_acct' => [ qw( username domsvc _password sec_phrase popnum ) ],
'svc_domain' => [ qw( domain ) ],
- 'svc_phone' => [ qw( phonenum pin sip_password ) ],
+ 'svc_phone' => [ qw( phonenum pin sip_password phone_name ) ],
'svc_external' => [ qw( id title ) ],
);
@@ -1124,14 +1320,18 @@ sub renew_info {
my $total = $cust_main->balance;
my @array = map {
- $total += $_->part_pkg->base_recur;
+ my $bill = $_->bill;
+ $total += $_->part_pkg->base_recur($_, \$bill);
my $renew_date = $_->part_pkg->add_freq($_->bill);
{
- 'bill_date' => $_->bill,
- 'bill_date_pretty' => time2str('%x', $_->bill),
- 'renew_date' => $renew_date,
- 'renew_date_pretty' => time2str('%x', $renew_date),
- 'amount' => sprintf('%.2f', $total),
+ 'pkgnum' => $_->pkgnum,
+ 'amount' => sprintf('%.2f', $total),
+ 'bill_date' => $_->bill,
+ 'bill_date_pretty' => time2str('%x', $_->bill),
+ 'renew_date' => $renew_date,
+ 'renew_date_pretty' => time2str('%x', $renew_date),
+ 'expire_date' => $_->expire,
+ 'expire_date_pretty' => time2str('%x', $_->expire),
};
}
@cust_pkg;
@@ -1140,6 +1340,15 @@ sub renew_info {
}
+sub payment_info_renew_info {
+ my $p = shift;
+ my $renew_info = renew_info($p);
+ my $payment_info = payment_info($p);
+ return { %$renew_info,
+ %$payment_info,
+ };
+}
+
sub order_renew {
my $p = shift;
diff --git a/FS/FS/ClientAPI/SGNG.pm b/FS/FS/ClientAPI/SGNG.pm
new file mode 100644
index 0000000..7f784dc
--- /dev/null
+++ b/FS/FS/ClientAPI/SGNG.pm
@@ -0,0 +1,277 @@
+#this stuff is SG-specific (i.e. multi-customer company username hack)
+
+package FS::ClientAPI::SGNG;
+
+use strict;
+use vars qw( $cache $DEBUG );
+use Time::Local qw(timelocal timelocal_nocheck);
+use Business::CreditCard;
+use FS::Record qw( qsearch qsearchs );
+use FS::Conf;
+use FS::cust_main;
+use FS::cust_pkg;
+use FS::ClientAPI::MyAccount; #qw( payment_info process_payment )
+
+$DEBUG = 0;
+
+sub _cache {
+ $cache ||= new FS::ClientAPI_SessionCache( {
+ 'namespace' => 'FS::ClientAPI::MyAccount', #yes, share session_ids
+ } );
+}
+
+sub ping {
+ #my $p = shift;
+
+ return { 'pong' => '1' };
+
+}
+
+#this might almost be general-purpose
+sub decompify_pkgs {
+ my $p = shift;
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ return { 'error' => 'Not a complimentary customer' }
+ unless $cust_main->payby eq 'COMP';
+
+ my $paydate =
+ $cust_main->paydate =~ /^\S+$/ ? $cust_main->paydate : '2037-12-31';
+
+ my ($payyear,$paymonth,$payday) = split (/-/,$paydate);
+
+ my $date = timelocal(0,0,0,$payday,--$paymonth,$payyear);
+
+ foreach my $cust_pkg (
+ qsearch({ 'table' => 'cust_pkg',
+ 'hashref' => { 'custnum' => $custnum,
+ 'bill' => '',
+ },
+ 'extra_sql' => ' AND '. FS::cust_pkg->active_sql,
+ })
+ ) {
+ $cust_pkg->set('bill', $date);
+ my $error = $cust_pkg->replace;
+ return { 'error' => $error } if $error;
+ }
+
+ return { 'error' => '' };
+
+}
+
+#find old payment info
+# (should work just like MyAccount::payment_info, except returns previous info
+# too)
+# definitly sg-specific, no one else stores past customer records like this
+sub previous_payment_info {
+ my $p = shift;
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $payment_info = FS::ClientAPI::MyAccount::payment_info($p);
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ #?
+ return $payment_info if $cust_main->payby =~ /^(CARD|DCRD|CHEK|DCHK)$/;
+
+ foreach my $prev_cust_main (
+ reverse _previous_cust_main( 'custnum' => $custnum,
+ 'username' => $cust_main->company,
+ 'with_payments' => 1,
+ )
+ ) {
+
+ next unless $prev_cust_main->payby =~ /^(CARD|DCRD|CHEK|DCHK)$/;
+
+ if ( $prev_cust_main->payby =~ /^(CARD|DCRD)$/ ) {
+
+ #card expired?
+ my ($payyear,$paymonth,$payday) = split (/-/, $cust_main->paydate);
+
+ my $expdate = timelocal_nocheck(0,0,0,1,$paymonth,$payyear);
+
+ next if $expdate < time;
+
+ } elsif ( $prev_cust_main->payby =~ /^(CHEK|DCHK)$/ ) {
+
+ #any check? or just skip these in favor of cards?
+
+ }
+
+ return { %$payment_info,
+ #$prev_cust_main->payment_info
+ _cust_main_payment_info( $prev_cust_main ),
+ 'previous_custnum' => $prev_cust_main->custnum,
+ };
+
+ }
+
+ #still nothing? return an error?
+ return $payment_info;
+
+}
+
+#this is really FS::cust_main::payment_info, but here for now
+sub _cust_main_payment_info {
+ my $self = shift;
+
+ my %return = ();
+
+ $return{balance} = $self->balance;
+
+ $return{payname} = $self->payname
+ || ( $self->first. ' '. $self->get('last') );
+
+ $return{$_} = $self->get($_) for qw(address1 address2 city state zip);
+
+ $return{payby} = $self->payby;
+ $return{stateid_state} = $self->stateid_state;
+
+ if ( $self->payby =~ /^(CARD|DCRD)$/ ) {
+ $return{card_type} = cardtype($self->payinfo);
+ $return{payinfo} = $self->paymask;
+
+ @return{'month', 'year'} = $self->paydate_monthyear;
+
+ }
+
+ if ( $self->payby =~ /^(CHEK|DCHK)$/ ) {
+ my ($payinfo1, $payinfo2) = split '@', $self->paymask;
+ $return{payinfo1} = $payinfo1;
+ $return{payinfo2} = $payinfo2;
+ $return{paytype} = $self->paytype;
+ $return{paystate} = $self->paystate;
+
+ }
+
+ #doubleclick protection
+ my $_date = time;
+ $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32;
+
+ %return;
+
+}
+
+#find old cust_main records (with payments)
+sub _previous_cust_main {
+
+ #safety check! return nothing unless we're enabled explicitly
+ return () unless FS::Conf->new->exists('sg-multicustomer_hack');
+
+ my %opt = @_;
+ my $custnum = $opt{'custnum'};
+ my $username = $opt{'username'};
+
+ my %search = ();
+ if ( $opt{'with_payments'} ) {
+ $search{'extra_sql'} =
+ ' AND 0 < ( SELECT COUNT(*) FROM cust_pay
+ WHERE cust_pay.custnum = cust_main.custnum
+ )
+ ';
+ }
+
+ qsearch( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'company' => { op => 'ILIKE', value => $opt{'username'} },
+ 'custnum' => { op => '!=', value => $opt{'custnum'} },
+ },
+ 'order_by' => 'ORDER BY custnum',
+ %search,
+ } );
+
+}
+
+#since we could be passing masked old CC data, need to look that up and
+#replace it (like regular process_payment does) w/info from old customer record
+sub previous_process_payment {
+ my $p = shift;
+
+ return FS::ClientAPI::MyAccount::process_payment($p)
+ unless $p->{'previous_custnum'}
+ && ( ( $p->{'payby'} =~ /^(CARD|DCRD)$/ && $p->{'payinfo'} =~ /x/i )
+ || ( $p->{'payby'} =~ /^(CHEK|DCHK)$/ && $p->{'payinfo1'} =~ /x/i )
+ );
+
+ my $session = _cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ #make sure this is really a previous custnum of this customer
+ my @previous_cust_main =
+ grep { $_->custnum == $p->{'previous_custnum'} }
+ _previous_cust_main( 'custnum' => $custnum,
+ 'username' => $cust_main->company,
+ 'with_payments' => 1,
+ );
+
+ my $previous_cust_main = $previous_cust_main[0];
+
+ #causes problems with old data w/old masking method
+ #if $previous_cust_main->paymask eq $payinfo;
+
+ if ( $p->{'payby'} =~ /^(CHEK|DCHK)$/ && $p->{'payinfo1'} =~ /x/i ) {
+ ( $p->{'payinfo1'}, $p->{'payinfo2'} ) =
+ split('@', $previous_cust_main->payinfo);
+ } elsif ( $p->{'payby'} =~ /^(CARD|DCRD)$/ && $p->{'payinfo'} =~ /x/i ) {
+ $p->{'payinfo'} = $previous_cust_main->payinfo;
+ }
+
+ FS::ClientAPI::MyAccount::process_payment($p);
+
+}
+
+sub previous_payment_info_renew_info {
+ my $p = shift;
+ my $renew_info = renew_info($p);
+ my $payment_info = previous_payment_info($p);
+ return { %$renew_info,
+ %$payment_info,
+ };
+}
+
+sub previous_process_payment_order_pkg {
+ my $p = shift;
+
+ my $hr = previous_process_payment($p);
+ return $hr if $hr->{'error'};
+
+ order_pkg($p);
+}
+
+sub previous_process_payment_change_pkg {
+ my $p = shift;
+
+ my $hr = previous_process_payment($p);
+ return $hr if $hr->{'error'};
+
+ change_pkg($p);
+}
+
+sub previous_process_payment_order_renew {
+ my $p = shift;
+
+ my $hr = previous_process_payment($p);
+ return $hr if $hr->{'error'};
+
+ order_renew($p);
+}
+
+1;
+
diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
index 5569dfb..c376476 100644
--- a/FS/FS/ClientAPI/Signup.pm
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -6,6 +6,7 @@ use Data::Dumper;
use Tie::RefHash;
use FS::Conf;
use FS::Record qw(qsearch qsearchs dbdef);
+use FS::CGI qw(popurl);
use FS::Msgcat qw(gettext);
use FS::Misc qw(card_types);
use FS::ClientAPI_SessionCache;
@@ -20,6 +21,7 @@ use FS::svc_phone;
use FS::acct_snarf;
use FS::queue;
use FS::reg_code;
+use FS::payby;
$DEBUG = 0;
$me = '[FS::ClientAPI::Signup]';
@@ -59,7 +61,9 @@ sub signup_info {
} }
grep { $_->svcpart($svc_x)
&& ( $href->{ $_->pkgpart }
- || $_->agentnum == $agent->agentnum
+ || ( $_->agentnum
+ && $_->agentnum == $agent->agentnum
+ )
)
}
qsearch( 'part_pkg', { 'disabled' => '' } )
@@ -103,6 +107,8 @@ sub signup_info {
'security_phrase' => $conf->exists('security_phrase'),
+ 'nomadix' => $conf->exists('signup_server-nomadix'),
+
'payby' => [ $conf->config('signup_server-payby') ],
'card_types' => card_types(),
@@ -276,6 +282,32 @@ sub signup_info {
if ( $agentnum ) {
+ warn "$me setting agent-specific payment flag\n" if $DEBUG > 1;
+ my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ warn "$me has agent $agent\n" if $DEBUG > 1;
+ if ( $agent ) { #else complain loudly?
+ $signup_info->{'hide_payment_fields'} = [];
+ foreach my $payby (@{$signup_info->{payby}}) {
+ warn "$me checking $payby payment fields\n" if $DEBUG > 1;
+ my $hide = 0;
+ if ( FS::payby->realtime($payby) ) {
+ my $payment_gateway =
+ $agent->payment_gateway( 'method' => FS::payby->payby2bop($payby),
+ 'nofatal' => 1,
+ );
+ if ( $payment_gateway
+ && $payment_gateway->gateway_namespace
+ eq 'Business::OnlineThirdPartyPayment'
+ ) {
+ warn "$me hiding $payby payment fields\n" if $DEBUG > 1;
+ $hide = 1;
+ }
+ }
+ push @{$signup_info->{'hide_payment_fields'}}, $hide;
+ }
+ }
+ warn "$me done setting agent-specific payment flag\n" if $DEBUG > 1;
+
warn "$me setting agent-specific package list\n" if $DEBUG > 1;
$signup_info->{'part_pkg'} = $signup_info->{'agentnum2part_pkg'}{$agentnum}
unless @{ $signup_info->{'part_pkg'} };
@@ -295,8 +327,6 @@ sub signup_info {
];
warn "$me done setting agent-specific adv. source list\n" if $DEBUG > 1;
- my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
-
$signup_info->{'agent_name'} = $agent->agent;
$signup_info->{'company_name'} = $conf->config('company_name', $agentnum);
@@ -436,6 +466,21 @@ sub new_customer {
unless grep { $_ eq $packet->{'payby'} }
$conf->config('signup_server-payby');
+ if (FS::payby->realtime($packet->{payby})) {
+ my $payby = $packet->{payby};
+
+ my $agent = qsearchs('agent', { 'agentnum' => $agentnum });
+ return { 'error' => "Unknown reseller" }
+ unless $agent;
+
+ my $gw = $agent->payment_gateway( 'method' => FS::payby->payby2bop($payby),
+ 'nofatal' => 1,
+ );
+
+ $cust_main->payby('BILL') # MCRD better?
+ if $gw && $gw->gateway_namespace eq 'Business::OnlineThirdPartyPayment';
+ }
+
$cust_main->payinfo($cust_main->daytime)
if $cust_main->payby eq 'LECB' && ! $cust_main->payinfo;
@@ -469,14 +514,14 @@ sub new_customer {
#return { 'error' => $error } if $error;
#should be all auto-magic and shit
- my $svc;
+ my @svc = ();
if ( $svc_x eq 'svc_acct' ) {
- $svc = new FS::svc_acct ( {
+ my $svc = new FS::svc_acct {
'svcpart' => $svcpart,
map { $_ => $packet->{$_} }
qw( username _password sec_phrase popnum ),
- } );
+ };
my @acct_snarf;
my $snarfnum = 1;
@@ -493,21 +538,48 @@ sub new_customer {
}
$svc->child_objects( \@acct_snarf );
+ push @svc, $svc;
+
} elsif ( $svc_x eq 'svc_phone' ) {
- $svc = new FS::svc_phone ( {
+ my $svc = new FS::svc_phone ( {
'svcpart' => $svcpart,
map { $_ => $packet->{$_} }
qw( countrycode phonenum sip_password pin ),
} );
+ push @svc, $svc;
+
} else {
die "unknown signup service $svc_x";
}
-
- my $y = $svc->setdefault; # arguably should be in new method
+ my $y = $svc[0]->setdefault; # arguably should be in new method
return { 'error' => $y } if $y && !ref($y);
+ if ($packet->{'mac_addr'} && $conf->exists('signup_server-mac_addr_svcparts'))
+ {
+
+ my %mac_addr_svcparts = map { $_ => 1 }
+ $conf->config('signup_server-mac_addr_svcparts');
+ my @pkg_svc = grep { $_->quantity && $mac_addr_svcparts{$_->svcpart} }
+ $cust_pkg->part_pkg->pkg_svc;
+
+ return { 'error' => 'No service defined to assign mac address' }
+ unless @pkg_svc;
+
+ my $svc = new FS::svc_acct {
+ 'svcpart' => $pkg_svc[0]->svcpart, #multiple matches? alas..
+ 'username' => $packet->{'mac_addr'},
+ '_password' => '', #blank as requested (set passwordmin to 0)
+ };
+
+ my $y = $svc->setdefault; # arguably should be in new method
+ return { 'error' => $y } if $y && !ref($y);
+
+ push @svc, $svc;
+
+ }
+
#$error = $svc->check;
#return { 'error' => $error } if $error;
@@ -521,7 +593,7 @@ sub new_customer {
use Tie::RefHash;
tie my %hash, 'Tie::RefHash';
- %hash = ( $cust_pkg => [ $svc ] );
+ %hash = ( $cust_pkg => \@svc );
#msgcat
$error = $cust_main->insert(
\%hash,
@@ -547,10 +619,26 @@ sub new_customer {
# " new customer: $bill_error"
# if $bill_error;
- $bill_error = $cust_main->collect('realtime' => 1);
+ if ($cust_main->_new_bop_required()) {
+ $bill_error = $cust_main->realtime_collect(
+ method => FS::payby->payby2bop( $packet->{payby} ),
+ depend_jobnum => $placeholder->jobnum,
+ );
+ } else {
+ $bill_error = $cust_main->collect('realtime' => 1);
+ }
#warn "[fs_signup_server] error collecting from new customer: $bill_error"
# if $bill_error;
+ if ($bill_error && ref($bill_error) eq 'HASH') {
+ return { 'error' => '_collect',
+ ( map { $_ => $bill_error->{$_} }
+ qw(popup_url reference collectitems)
+ ),
+ amount => $cust_main->balance,
+ };
+ }
+
if ( $cust_main->balance > 0 ) {
#this makes sense. credit is "un-doing" the invoice
@@ -589,9 +677,9 @@ sub new_customer {
);
if ( $svc_x eq 'svc_acct' ) {
- $return{$_} = $svc->$_() for qw( username _password );
+ $return{$_} = $svc[0]->$_() for qw( username _password );
} elsif ( $svc_x eq 'svc_phone' ) {
- $return{$_} = $svc->$_() for qw( countrycode phonenum sip_password pin );
+ $return{$_} = $svc[0]->$_() for qw( countrycode phonenum sip_password pin );
} else {
die "unknown signup service $svc_x";
}
@@ -600,4 +688,83 @@ sub new_customer {
}
+sub capture_payment {
+ my $packet = shift;
+
+ warn "$me capture_payment called on $packet\n" if $DEBUG;
+
+ ###
+ # identify processor/gateway from called back URL
+ ###
+
+ my $conf = new FS::Conf;
+
+ my $url = $packet->{url};
+ my $payment_gateway =
+ qsearchs('payment_gateway', { 'gateway_callback_url' => popurl(0, $url) } );
+
+ unless ($payment_gateway) {
+
+ my ( $processor, $login, $password, $action, @bop_options ) =
+ $conf->config('business-onlinepayment');
+ $action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+ die "No real-time processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n"
+ unless $processor;
+
+ $payment_gateway = new FS::payment_gateway( {
+ gateway_namespace => $conf->config('business-onlinepayment-namespace'),
+ gateway_module => $processor,
+ gateway_username => $login,
+ gateway_password => $password,
+ gateway_action => $action,
+ options => [ ( @bop_options ) ],
+ });
+
+ }
+
+ die "No real-time third party processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n*"
+ unless $payment_gateway->gateway_namespace eq 'Business::OnlineThirdPartyPayment';
+
+ ###
+ # locate pending transaction
+ ###
+
+ eval "use Business::OnlineThirdPartyPayment";
+ die $@ if $@;
+
+ my $transaction =
+ new Business::OnlineThirdPartyPayment( $payment_gateway->gateway_module,
+ @{ [ $payment_gateway->options ] },
+ );
+
+ my $paypendingnum = $transaction->reference($packet->{data});
+
+ my $cust_pay_pending =
+ qsearchs('cust_pay_pending', { paypendingnum => $paypendingnum } );
+
+ unless ($cust_pay_pending) {
+ my $bill_error = "No payment is being processed with id $paypendingnum".
+ "; Transaction aborted.";
+ return { error => '_decline', bill_error => $bill_error };
+ }
+
+ if ($cust_pay_pending->status ne 'pending') {
+ my $bill_error = "Payment with id $paypendingnum is not pending, but ".
+ $cust_pay_pending->status. "; Transaction aborted.";
+ return { error => '_decline', bill_error => $bill_error };
+ }
+
+ my $cust_main = $cust_pay_pending->cust_main;
+ my $bill_error =
+ $cust_main->realtime_botpp_capture( $cust_pay_pending, %{$packet->{data}} );
+
+ return { 'error' => ( $bill_error->{bill_error} ? '_decline' : '' ),
+ %$bill_error,
+ };
+
+}
+
1;
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index b869302..13bec18 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -8,6 +8,7 @@ use MIME::Base64;
use FS::ConfItem;
use FS::ConfDefaults;
use FS::Conf_compat17;
+use FS::payby;
use FS::conf;
use FS::Record qw(qsearch qsearchs);
use FS::UID qw(dbh datasrc use_confcompat);
@@ -75,11 +76,23 @@ sub base_dir {
$1;
}
-=item config KEY [ AGENTNUM ]
+=item conf KEY [ AGENTNUM [ NODEFAULT ] ]
+
+Returns the L<FS::conf> record for the key and agent.
+
+=cut
+
+sub conf {
+ my $self = shift;
+ $self->_config(@_);
+}
+
+=item config KEY [ AGENTNUM [ NODEFAULT ] ]
Returns the configuration value or values (depending on context) for key.
The optional agent number selects an agent specific value instead of the
-global default if one is present.
+global default if one is present. If NODEFAULT is true only the agent
+specific value(s) is returned.
=cut
@@ -92,12 +105,12 @@ sub _usecompat {
}
sub _config {
- my($self,$name,$agentnum)=@_;
+ my($self,$name,$agentnum,$agentonly)=@_;
my $hashref = { 'name' => $name };
$hashref->{agentnum} = $agentnum;
local $FS::Record::conf = undef; # XXX evil hack prevents recursion
my $cv = FS::Record::qsearchs('conf', $hashref);
- if (!$cv && defined($agentnum) && $agentnum) {
+ if (!$agentonly && !$cv && defined($agentnum) && $agentnum) {
$hashref->{agentnum} = '';
$cv = FS::Record::qsearchs('conf', $hashref);
}
@@ -108,12 +121,10 @@ sub config {
my $self = shift;
return $self->_usecompat('config', @_) if use_confcompat;
- my($name, $agentnum)=@_;
-
- carp "FS::Conf->config($name, $agentnum) called"
+ carp "FS::Conf->config(". join(', ', @_). ") called"
if $DEBUG > 1;
- my $cv = $self->_config($name, $agentnum) or return;
+ my $cv = $self->_config(@_) or return;
if ( wantarray ) {
my $v = $cv->value;
@@ -124,7 +135,7 @@ sub config {
}
}
-=item config_binary KEY [ AGENTNUM ]
+=item config_binary KEY [ AGENTNUM [ NODEFAULT ] ]
Returns the exact scalar value for key.
@@ -134,12 +145,11 @@ sub config_binary {
my $self = shift;
return $self->_usecompat('config_binary', @_) if use_confcompat;
- my($name,$agentnum)=@_;
- my $cv = $self->_config($name, $agentnum) or return;
+ my $cv = $self->_config(@_) or return;
decode_base64($cv->value);
}
-=item exists KEY [ AGENTNUM ]
+=item exists KEY [ AGENTNUM [ NODEFAULT ] ]
Returns true if the specified key exists, even if the corresponding value
is undefined.
@@ -152,10 +162,10 @@ sub exists {
my($name, $agentnum)=@_;
- carp "FS::Conf->exists($name, $agentnum) called"
+ carp "FS::Conf->exists(". join(', ', @_). ") called"
if $DEBUG > 1;
- defined($self->_config($name, $agentnum));
+ defined($self->_config(@_));
}
=item config_orbase KEY SUFFIX
@@ -450,11 +460,12 @@ sub _orbase_items {
die "don't know about $base items" unless $proto->key eq $base;
map { new FS::ConfItem {
- 'key' => $_,
- 'section' => $proto->section,
- 'description' => 'Alternate ' . $proto->description . ' See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Invoice_templates">billing documentation</a> for details.',
- 'type' => $proto->type,
- };
+ 'key' => $_,
+ 'base_key' => $proto->key,
+ 'section' => $proto->section,
+ 'description' => 'Alternate ' . $proto->description . ' See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Invoice_templates">billing documentation</a> for details.',
+ 'type' => $proto->type,
+ };
} &$listmaker($base);
} @base_items,
);
@@ -563,17 +574,28 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'alert_expiration',
+ 'section' => 'billing',
+ 'description' => 'Enable alerts about billing method expiration.',
+ 'type' => 'checkbox',
+ 'per_agent' => 1,
+ },
+
+ {
'key' => 'alerter_template',
'section' => 'billing',
'description' => 'Template file for billing method expiration alerts. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Credit_cards_and_Electronic_checks">billing documentation</a> for details.',
'type' => 'textarea',
- 'per-agent' => 1,
+ 'per_agent' => 1,
},
{
'key' => 'apacheip',
- 'section' => 'deprecated',
- 'description' => '<b>DEPRECATED</b>, add an <i>apache</i> <a href="../browse/part_export.cgi">export</a> instead. Used to be the current IP address to assign to new virtual hosts',
+ #not actually deprecated yet
+ #'section' => 'deprecated',
+ #'description' => '<b>DEPRECATED</b>, add an <i>apache</i> <a href="../browse/part_export.cgi">export</a> instead. Used to be the current IP address to assign to new virtual hosts',
+ 'section' => '',
+ 'description' => 'IP address to assign to new virtual hosts',
'type' => 'text',
},
@@ -606,6 +628,40 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'billco-url',
+ 'section' => 'billing',
+ 'description' => 'The url to use for performing uploads to the invoice mailing service.',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ },
+
+ {
+ 'key' => 'billco-username',
+ 'section' => 'billing',
+ 'description' => 'The login name to use for uploads to the invoice mailing service.',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ 'agentonly' => 1,
+ },
+
+ {
+ 'key' => 'billco-password',
+ 'section' => 'billing',
+ 'description' => 'The password to use for uploads to the invoice mailing service.',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ 'agentonly' => 1,
+ },
+
+ {
+ 'key' => 'billco-clicode',
+ 'section' => 'billing',
+ 'description' => 'The clicode to use for uploads to the invoice mailing service.',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ },
+
+ {
'key' => 'business-onlinepayment',
'section' => 'billing',
'description' => '<a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> support, at least three lines: processor, login, and password. An optional fourth line specifies the action or actions (multiple actions are separated with `,\': for example: `Authorization Only, Post Authorization\'). Optional additional lines are passed to Business::OnlinePayment as %processor_options.',
@@ -620,6 +676,17 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'business-onlinepayment-namespace',
+ 'section' => 'billing',
+ 'description' => 'Specifies which perl module namespace (which group of collection routines) is used by default.',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'Business::OnlinePayment' => 'Direct API (Business::OnlinePayment)',
+ 'Business::OnlineThirdPartyPayment' => 'Web API (Business::ThirdPartyPayment)',
+ ],
+ },
+
+ {
'key' => 'business-onlinepayment-description',
'section' => 'billing',
'description' => 'String passed as the description field to <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a>. Evaluated as a double-quoted perl string, with the following variables available: <code>$agent</code> (the agent name), and <code>$pkgs</code> (a comma-separated list of packages for which these charges apply)',
@@ -661,7 +728,14 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'deletecustomers',
'section' => 'UI',
- 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that this customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that the customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'deleteinvoices',
+ 'section' => 'UI',
+ 'description' => 'Enable invoices deletions. Be very careful! Deleting an invoice will remove all traces that the invoice ever existed! Normally, you would apply a credit against the invoice instead.', #invoice voiding?
'type' => 'checkbox',
},
@@ -674,8 +748,11 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'deletecredits',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable deletion of unclosed credits. Be very careful! Only delete credits that were data-entry errors, not adjustments. Optionally specify one or more comma-separated email addresses to be notified when a credit is deleted.',
+ #not actually deprecated yet
+ #'section' => 'deprecated',
+ #'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable deletion of unclosed credits. Be very careful! Only delete credits that were data-entry errors, not adjustments. Optionally specify one or more comma-separated email addresses to be notified when a credit is deleted.',
+ 'section' => '',
+ 'description' => 'One or more comma-separated email addresses to be notified when a credit is deleted.',
'type' => [qw( checkbox text )],
},
@@ -687,6 +764,20 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'unapplypayments',
+ 'section' => 'deprecated',
+ 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable "unapplication" of unclosed payments.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'unapplycredits',
+ 'section' => 'deprecated',
+ 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to nable "unapplication" of unclosed credits.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'dirhash',
'section' => 'shell',
'description' => 'Optional numeric value to control directory hashing. If positive, hashes directories for the specified number of levels from the front of the username. If negative, hashes directories for the specified number of levels from the end of the username. Some examples: <ul><li>1: user -> <a href="#home">/home</a>/u/user<li>2: user -> <a href="#home">/home</a>/u/s/user<li>-1: user -> <a href="#home">/home</a>/r/user<li>-2: user -> <a href="#home">home</a>/r/e/user</ul>',
@@ -694,6 +785,20 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'disable_cust_attachment',
+ 'section' => '',
+ 'description' => 'Disable customer file attachments',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'max_attachment_size',
+ 'section' => '',
+ 'description' => 'Maximum size for customer file attachments (leave blank for unlimited)',
+ 'type' => 'text',
+ },
+
+ {
'key' => 'disable_customer_referrals',
'section' => 'UI',
'description' => 'Disable new customer-to-customer referrals in the web interface',
@@ -787,6 +892,13 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'invoice_usesummary',
+ 'section' => 'billing',
+ 'description' => 'Indicates that html and latex invoices should be in summary style and make use of invoice_latexsummary.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'invoice_template',
'section' => 'billing',
'description' => 'Text template file for invoices. Used if no invoice_html template is defined, and also seen by users using non-HTML capable mail clients. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Plaintext_invoice_templates">billing documentation</a> for details.',
@@ -806,6 +918,7 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Notes section for HTML invoices. Defaults to the same data in invoice_latexnotes if not specified.',
'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -813,6 +926,15 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Footer for HTML invoices. Defaults to the same data in invoice_latexfooter if not specified.',
'type' => 'textarea',
+ 'per_agent' => 1,
+ },
+
+ {
+ 'key' => 'invoice_htmlsummary',
+ 'section' => 'billing',
+ 'description' => 'Summary initial page for HTML invoices.',
+ 'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -834,6 +956,7 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Notes section for LaTeX typeset PostScript invoices.',
'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -841,6 +964,15 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Footer for LaTeX typeset PostScript invoices.',
'type' => 'textarea',
+ 'per_agent' => 1,
+ },
+
+ {
+ 'key' => 'invoice_latexsummary',
+ 'section' => 'billing',
+ 'description' => 'Summary initial page for LaTeX typeset PostScript invoices.',
+ 'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -848,6 +980,7 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Remittance coupon for LaTeX typeset PostScript invoices.',
'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -862,6 +995,7 @@ worry that config_items is freeside-specific and icky.
'section' => 'billing',
'description' => 'Optional small footer for multi-page LaTeX typeset PostScript invoices.',
'type' => 'textarea',
+ 'per_agent' => 1,
},
{
@@ -890,10 +1024,29 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'invoice_sections',
'section' => 'billing',
- 'description' => 'Split invoice into sections and label according to package class when enabled.',
+ 'description' => 'Split invoice into sections and label according to package category when enabled.',
'type' => 'checkbox',
},
+ {
+ 'key' => 'finance_pkgclass',
+ 'section' => 'billing',
+ 'description' => 'The package class for finance charges',
+ 'type' => 'select-sub',
+ 'options_sub' => sub { require FS::Record;
+ require FS::pkg_class;
+ map { $_->classnum => $_->classname }
+ FS::Record::qsearch('pkg_class', {} );
+ },
+ 'option_sub' => sub { require FS::Record;
+ require FS::pkg_class;
+ my $pkg_class = FS::Record::qsearchs(
+ 'pkg_class', { 'classnum'=>shift }
+ );
+ $pkg_class ? $pkg_class->classname : '';
+ },
+ },
+
{
'key' => 'separate_usage',
'section' => 'billing',
@@ -902,13 +1055,31 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'invoice_send_receipts',
+ 'section' => 'deprecated',
+ 'description' => '<b>DEPRECATED</b>, this used to send an invoice copy on payments and credits. See the payment_receipt_email and XXXX instead.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'payment_receipt_email',
'section' => 'billing',
- 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance</ul>',
+ 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance<li><code>$pkg</code> - Package (requires payment_receipt-trigger set to "when payment is applied".)</ul>',
'type' => [qw( checkbox textarea )],
},
{
+ 'key' => 'payment_receipt-trigger',
+ 'section' => 'billing',
+ 'description' => 'When payment receipts are triggered. Defaults to when payment is made.',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'cust_pay' => 'When payment is made.',
+ 'cust_bill_pay_pkg' => 'When payment is applied.',
+ ],
+ },
+
+ {
'key' => 'lpr',
'section' => 'required',
'description' => 'Print command for paper invoices, for example `lpr -h\'',
@@ -990,6 +1161,13 @@ worry that config_items is freeside-specific and icky.
# },
{
+ 'key' => 'report_template',
+ 'section' => 'deprecated',
+ 'description' => 'Deprecated template file for reports.',
+ 'type' => 'textarea',
+ },
+
+ {
'key' => 'maxsearchrecordsperpage',
'section' => 'UI',
'description' => 'If set, number of search records to return per page.',
@@ -1127,6 +1305,7 @@ worry that config_items is freeside-specific and icky.
'section' => 'username',
'description' => 'Usernames must contain at least one letter',
'type' => 'checkbox',
+ 'per_agent' => 1,
},
{
@@ -1171,6 +1350,13 @@ worry that config_items is freeside-specific and icky.
'type' => 'checkbox',
},
+ {
+ 'key' => 'username-colon',
+ 'section' => 'username',
+ 'description' => 'Allow the colon character (:) in usernames.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'safe-part_bill_event',
'section' => 'UI',
@@ -1293,44 +1479,29 @@ worry that config_items is freeside-specific and icky.
'key' => 'signup_server-default_pkgpart',
'section' => '',
'description' => 'Default package for the signup server',
- 'type' => 'select-sub',
- 'options_sub' => sub { require FS::Record;
- require FS::part_pkg;
- map { $_->pkgpart => $_->pkg.' - '.$_->comment }
- FS::Record::qsearch( 'part_pkg',
- { 'disabled' => ''}
- );
- },
- 'option_sub' => sub { require FS::Record;
- require FS::part_pkg;
- my $part_pkg = FS::Record::qsearchs(
- 'part_pkg', { 'pkgpart'=>shift }
- );
- $part_pkg
- ? $part_pkg->pkg.' - '.$part_pkg->comment
- : '';
- },
+ 'type' => 'select-part_pkg',
},
{
'key' => 'signup_server-default_svcpart',
'section' => '',
- 'description' => 'Default svcpart for the signup server - only necessary for services that trigger special provisioning widgets (such as DID provisioning).',
- 'type' => 'select-sub',
- 'options_sub' => sub { require FS::Record;
- require FS::part_svc;
- map { $_->svcpart => $_->svc }
- FS::Record::qsearch( 'part_svc',
- { 'disabled' => ''}
- );
- },
- 'option_sub' => sub { require FS::Record;
- require FS::part_svc;
- my $part_svc = FS::Record::qsearchs(
- 'part_svc', { 'svcpart'=>shift }
- );
- $part_svc ? $part_svc->svc : '';
- },
+ 'description' => 'Default service definition for the signup server - only necessary for services that trigger special provisioning widgets (such as DID provisioning).',
+ 'type' => 'select-part_svc',
+ },
+
+ {
+ 'key' => 'signup_server-mac_addr_svcparts',
+ 'section' => '',
+ 'description' => 'Service definitions which can receive mac addresses (current mapped to username for svc_acct).',
+ 'type' => 'select-part_svc',
+ 'multiple' => 1,
+ },
+
+ {
+ 'key' => 'signup_server-nomadix',
+ 'section' => '',
+ 'description' => 'Signup page Nomadix integration',
+ 'type' => 'checkbox',
},
{
@@ -1347,7 +1518,7 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'selfservice_server-base_url',
'section' => '',
- 'description' => 'Base URL for the self-service web interface - necessary for special provisioning widgets to find their way.',
+ 'description' => 'Base URL for the self-service web interface - necessary for some widgets to find their way, including retrieval of non-US state information and phone number provisioning.',
'type' => 'text',
},
@@ -1452,6 +1623,13 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'bill_usage_on_cancel',
+ 'section' => 'billing',
+ 'description' => 'Enable automatic generation of an invoice for usage when a package is cancelled. Not all packages can do this. Usage data must already be available.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'require_cardname',
'section' => 'billing',
'description' => 'Require an "Exact name on card" to be entered explicitly; don\'t default to using the first and last name.',
@@ -1475,7 +1653,14 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'enable_taxproducts',
'section' => 'billing',
- 'description' => 'Enable per-package mapping to new style tax classes',
+ 'description' => 'Enable per-package mapping to vendor tax data from CCH or elsewhere.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'taxdatadirectdownload',
+ 'section' => 'billing', #well
+ 'description' => 'Enable downloading tax data directly from the vendor site',
'type' => 'checkbox',
},
@@ -1608,6 +1793,14 @@ worry that config_items is freeside-specific and icky.
'select_enum' => [ 'Framed-IP-Address', 'Framed-Address' ],
},
+ #http://dev.coova.org/svn/coova-chilli/doc/dictionary.chillispot
+ {
+ 'key' => 'radius-chillispot-max',
+ 'section' => '',
+ 'description' => 'Enable ChilliSpot (and CoovaChilli) Max attributes, specifically ChilliSpot-Max-{Input,Output,Total}-{Octets,Gigawords}.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'svc_acct-alldomains',
'section' => '',
@@ -1630,6 +1823,31 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'users-allow_comp',
+ 'section' => 'deprecated',
+ 'description' => '<b>DEPRECATED</b>, enable the <i>Complimentary customer</i> access right instead. Was: Usernames (Freeside users, created with <a href="../docs/man/bin/freeside-adduser.html">freeside-adduser</a>) which can create complimentary customers, one per line. If no usernames are entered, all users can create complimentary accounts.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'credit_card-recurring_billing_flag',
+ 'section' => 'billing',
+ 'description' => 'This controls when the system passes the "recurring_billing" flag on credit card transactions. If supported by your processor (and the Business::OnlinePayment processor module), passing the flag indicates this is a recurring transaction and may turn off the CVV requirement. ',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'actual_oncard' => 'Default/classic behavior: set the flag if a customer has actual previous charges on the card.',
+ 'transaction_is_recur' => 'Set the flag if the transaction itself is recurring, irregardless of previous charges on the card.',
+ ],
+ },
+
+ {
+ 'key' => 'credit_card-recurring_billing_acct_code',
+ 'section' => 'billing',
+ 'description' => 'When the "recurring billing" flag is set, also set the "acct_code" to "rebill". Useful for reporting purposes with supported gateways (PlugNPay, others?)',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'cvv-save',
'section' => 'billing',
'description' => 'Save CVV2 information after the initial transaction for the selected credit card types. Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option for any credit card types.',
@@ -1638,6 +1856,31 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'manual_process-pkgpart',
+ 'section' => 'billing',
+ 'description' => 'Package to add to each manual credit card and ACH payments entered from the backend. Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option.',
+ 'type' => 'select-part_pkg',
+ },
+
+ {
+ 'key' => 'manual_process-display',
+ 'section' => 'billing',
+ 'description' => 'When using manual_process-pkgpart, add the fee to the amount entered (default), or subtract the fee from the amount entered.',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'add' => 'Add fee to amount entered',
+ 'subtract' => 'Subtract fee from amount entered',
+ ],
+ },
+
+ {
+ 'key' => 'manual_process-skip_first',
+ 'section' => 'billing',
+ 'description' => "When using manual_process-pkgpart, omit the fee if it is the customer's first payment.",
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'allow_negative_charges',
'section' => 'billing',
'description' => 'Allow negative charges. Normally not used unless importing data from a legacy system that requires this.',
@@ -1682,7 +1925,8 @@ worry that config_items is freeside-specific and icky.
'key' => 'svc_www-usersvc_svcpart',
'section' => '',
'description' => 'Allowable service definition svcparts for virtual hosts, one per line.',
- 'type' => 'textarea',
+ 'type' => 'select-part_svc',
+ 'multiple' => 1,
},
{
@@ -1847,6 +2091,27 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'echeck-void',
+ 'section' => 'deprecated',
+ 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable local-only voiding of echeck payments in addition to refunds against the payment gateway',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cc-void',
+ 'section' => 'deprecated',
+ 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable local-only voiding of credit card payments in addition to refunds against the payment gateway',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'unvoid',
+ 'section' => 'deprecated',
+ 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable unvoiding of voided payments',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'address2-search',
'section' => 'UI',
'description' => 'Enable a "Unit" search box which searches the second address field. Useful for multi-tenant applications. See also: cust_main-require_address2',
@@ -1955,7 +2220,7 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'svc_acct-usage_threshold',
'section' => 'billing',
- 'description' => 'The threshold (expressed as percentage) of acct.seconds or acct.up|down|totalbytes at which a warning message is sent to a service holder. Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd. Defaults to 80.',
+ 'description' => 'The threshold (expressed as percentage) of acct.seconds or acct.up|down|totalbytes at which a warning message is sent to a service holder. Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
'type' => 'text',
},
@@ -2024,6 +2289,20 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'voip-cdr_email',
+ 'section' => '',
+ 'description' => 'Include the call details on emailed invoices even if the customer is configured for not printing them on the invoices.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'voip-cust_email_csv_cdr',
+ 'section' => '',
+ 'description' => 'Enable the per-customer option for including CDR information as a CSV attachment on emailed invoices.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'svc_forward-arbitrary_dst',
'section' => '',
'description' => "Allow forwards to point to arbitrary strings that don't necessarily look like email addresses. Only used when using forwards for weird, non-email things.",
@@ -2040,21 +2319,35 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'tax-pkg_address',
'section' => 'billing',
- 'description' => 'By default, tax calculations are done based on the billing address. Enable this switch to calculate tax based on the package address instead (when present).',
+ 'description' => 'By default, tax calculations are done based on the billing address. Enable this switch to calculate tax based on the package address instead (when present). Note that this option is currently incompatible with vendor data taxation enabled by enable_taxproducts.',
'type' => 'checkbox',
},
{
'key' => 'invoice-ship_address',
'section' => 'billing',
- 'description' => 'Enable this switch to include the ship address on the invoice.',
+ 'description' => 'Include the shipping address on invoices.',
'type' => 'checkbox',
},
{
'key' => 'invoice-unitprice',
'section' => 'billing',
- 'description' => 'This switch enables unit pricing on the invoice.',
+ 'description' => 'Enable unit pricing on invoices.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'invoice-smallernotes',
+ 'section' => 'billing',
+ 'description' => 'Display the notes section in a smaller font on invoices.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'invoice-smallerfooter',
+ 'section' => 'billing',
+ 'description' => 'Display footers in a smaller font on invoices.',
'type' => 'checkbox',
},
@@ -2062,19 +2355,7 @@ worry that config_items is freeside-specific and icky.
'key' => 'postal_invoice-fee_pkgpart',
'section' => 'billing',
'description' => 'This allows selection of a package to insert on invoices for customers with postal invoices selected.',
- 'type' => 'select-sub',
- 'options_sub' => sub { require FS::Record;
- require FS::part_pkg;
- map { $_->pkgpart => $_->pkg }
- FS::Record::qsearch('part_pkg', { disabled=>'' } );
- },
- 'option_sub' => sub { require FS::Record;
- require FS::part_pkg;
- my $part_pkg = FS::Record::qsearchs(
- 'part_pkg', { 'pkgpart'=>shift }
- );
- $part_pkg ? $part_pkg->pkg : '';
- },
+ 'type' => 'select-part_pkg',
},
{
@@ -2167,6 +2448,13 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'batchconfig-paymentech',
+ 'section' => 'billing',
+ 'description' => 'Configuration for Chase Paymentech batching, four lines: 1. BIN, 2. Terminal ID, 3. Merchant ID, 4. Username',
+ 'type' => 'textarea',
+ },
+
+ {
'key' => 'payment_history-years',
'section' => 'UI',
'description' => 'Number of years of payment history to show by default. Currently defaults to 2.',
@@ -2174,6 +2462,20 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'change_history-years',
+ 'section' => 'UI',
+ 'description' => 'Number of years of change history to show by default. Currently defaults to 0.5.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_main-packages-years',
+ 'section' => 'UI',
+ 'description' => 'Number of years to show old (cancelled and one-time charge) packages by default. Currently defaults to 2.',
+ 'type' => 'text',
+ },
+
+ {
'key' => 'cust_main-use_comments',
'section' => 'UI',
'description' => 'Display free form comments on the customer edit screen. Useful as a scratch pad.',
@@ -2265,6 +2567,14 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'dashboard-install_welcome',
+ 'section' => 'UI',
+ 'description' => 'New install welcome screen.',
+ 'type' => 'select',
+ 'select_enum' => [ '', 'ITSP_fsinc_hosted', ],
+ },
+
+ {
'key' => 'dashboard-toplist',
'section' => 'UI',
'description' => 'List of items to display on the top of the front page',
@@ -2292,7 +2602,7 @@ worry that config_items is freeside-specific and icky.
'key' => 'logo.eps',
'section' => 'billing', #?
'description' => 'Company logo for printed and PDF invoices, in EPS format.',
- 'type' => 'binary',
+ 'type' => 'image',
'per_agent' => 1, #XXX as above, kinda
},
@@ -2357,7 +2667,8 @@ worry that config_items is freeside-specific and icky.
'key' => 'support_packages',
'section' => '',
'description' => 'A list of packages eligible for RT ticket time transfer, one pkgpart per line.', #this should really be a select multiple, or specified in the packages themselves...
- 'type' => 'textarea',
+ 'type' => 'select-part_pkg',
+ 'multiple' => 1,
},
{
@@ -2474,6 +2785,13 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'previous_balance-summary_only',
+ 'section' => 'billing',
+ 'description' => 'Only show a single line summarizing the total previous balance rather than one line per invoice.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'usps_webtools-userid',
'section' => 'UI',
'description' => 'Production UserID for USPS web tools. Enables USPS address standardization. See the <a href="http://www.usps.com/webtools/">USPS website</a>, register and agree not to use the tools for batch purposes.',
@@ -2495,6 +2813,35 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'cust_main-require_censustract',
+ 'section' => 'UI',
+ 'description' => 'Customer is required to have a census tract. Useful for FCC form 477 reports. See also: cust_main-auto_standardize_address',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'census_year',
+ 'section' => 'UI',
+ 'description' => 'The year to use in census tract lookups',
+ 'type' => 'select',
+ 'select_enum' => [ qw( 2009 2008 2007 2006 ) ],
+ },
+
+ {
+ 'key' => 'company_latitude',
+ 'section' => 'UI',
+ 'description' => 'Your company latitude (-90 through 90)',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'company_longitude',
+ 'section' => 'UI',
+ 'description' => 'Your company longitude (-180 thru 180)',
+ 'type' => 'text',
+ },
+
+ {
'key' => 'disable_acl_changes',
'section' => '',
'description' => 'Disable all ACL changes, for demos.',
@@ -2511,7 +2858,14 @@ worry that config_items is freeside-specific and icky.
{
'key' => 'cust_main-default_agent_custid',
'section' => 'UI',
- 'description' => 'Display the agent_custid field instead of the custnum field.',
+ 'description' => 'Display the agent_custid field when available instead of the custnum field.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_bill-default_agent_invid',
+ 'section' => 'UI',
+ 'description' => 'Display the agent_invid field when available instead of the invnum field.',
'type' => 'checkbox',
},
@@ -2536,7 +2890,7 @@ worry that config_items is freeside-specific and icky.
'key' => 'mcp_svcpart',
'section' => '',
'description' => 'Master Control Program svcpart. Leave this blank.',
- 'type' => 'text',
+ 'type' => 'text', #select-part_svc
},
{
@@ -2598,6 +2952,23 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'selfservice-bulk_format',
+ 'section' => '',
+ 'description' => 'Parameter arrangement for selfservice bulk features',
+ 'type' => 'select',
+ 'select_enum' => [ '', 'izoom-soap', 'izoom-ftp' ],
+ 'per_agent' => 1,
+ },
+
+ {
+ 'key' => 'selfservice-bulk_ftp_dir',
+ 'section' => '',
+ 'description' => 'Enable bulk ftp provisioning in this folder',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ },
+
+ {
'key' => 'signup-no_company',
'section' => '',
'description' => "Don't display a field for company name on signup.",
@@ -2647,9 +3018,30 @@ worry that config_items is freeside-specific and icky.
},
{
+ 'key' => 'cdr-charged_party-accountcode-trim_leading_0s',
+ 'section' => '',
+ 'description' => 'When setting the charged_party field of CDRs to the accountcode, trim any leading zeros.',
+ 'type' => 'checkbox',
+ },
+
+# {
+# 'key' => 'cdr-charged_party-truncate_prefix',
+# 'section' => '',
+# 'description' => 'If the charged_party field has this prefix, truncate it to the length in cdr-charged_party-truncate_length.',
+# 'type' => 'text',
+# },
+#
+# {
+# 'key' => 'cdr-charged_party-truncate_length',
+# 'section' => '',
+# 'description' => 'If the charged_party field has the prefix in cdr-charged_party-truncate_prefix, truncate it to this length.',
+# 'type' => 'text',
+# },
+
+ {
'key' => 'cdr-charged_party_rewrite',
'section' => '',
- 'description' => 'Do charged party rewriting in the freeside-cdrrewrited daemon; useful if CDRs are being dropped off directly in the database and require special charged_party processing such as cdr-charged_party-accountcode.',
+ 'description' => 'Do charged party rewriting in the freeside-cdrrewrited daemon; useful if CDRs are being dropped off directly in the database and require special charged_party processing such as cdr-charged_party-accountcode or cdr-charged_party-truncate*.',
'type' => 'checkbox',
},
@@ -2674,6 +3066,186 @@ worry that config_items is freeside-specific and icky.
'type' => 'checkbox',
},
+ {
+ 'key' => 'sg-multicustomer_hack',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'sg-ping_username',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sg-ping_password',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sg-login_username',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'disable-cust-pkg_class',
+ 'section' => 'UI',
+ 'description' => 'Disable the two-step dropdown for selecting package class and package, and return to the classic single dropdown.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'queued-max_kids',
+ 'section' => '',
+ 'description' => 'Maximum number of queued processes. Defaults to 10.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cancelled_cust-noevents',
+ 'section' => 'billing',
+ 'description' => "Don't run events for cancelled customers",
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'agent-invoice_template',
+ 'section' => 'billing',
+ 'description' => 'Enable display/edit of old-style per-agent invoice template selection',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'svc_broadband-manage_link',
+ 'section' => 'UI',
+ 'description' => 'URL for svc_broadband "Manage Device" link. The following substitutions are available: $ip_addr.',
+ 'type' => 'text',
+ },
+
+ #more fine-grained, service def-level control could be useful eventually?
+ {
+ 'key' => 'svc_broadband-allow_null_ip_addr',
+ 'section' => '',
+ 'description' => '',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'tax-report_groups',
+ 'section' => '',
+ 'description' => 'List of grouping possibilities for tax names on reports, one per line, "label op value" (op can be = or !=).',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'tax-cust_exempt-groups',
+ 'section' => '',
+ 'description' => 'List of grouping possibilities for tax names, for per-customer exemption purposes, one tax name per line. For example, "GST" would indicate the ability to exempt customers individually from taxes named "GST" (but not other taxes).',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'cust_main-default_view',
+ 'section' => 'UI',
+ 'description' => 'Default customer view, for users who have not selected a default view in their preferences.',
+ 'type' => 'select',
+ 'select_hash' => [
+ #false laziness w/view/cust_main.cgi and pref/pref.html
+ 'basics' => 'Basics',
+ 'notes' => 'Notes',
+ 'tickets' => 'Tickets',
+ 'packages' => 'Packages',
+ 'payment_history' => 'Payment History',
+ 'change_history' => 'Change History',
+ 'jumbo' => 'Jumbo',
+ ],
+ },
+
+ {
+ 'key' => 'enable_tax_adjustments',
+ 'section' => 'billing',
+ 'description' => 'Enable the ability to add manual tax adjustments.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'rt-crontool',
+ 'section' => '',
+ 'description' => 'Enable the RT CronTool extension.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'pkg-balances',
+ 'section' => 'billing',
+ 'description' => 'Enable experimental package balances. Not recommended for general use.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-edit_signupdate',
+ 'section' => 'UI',
+ 'descritpion' => 'Enable manual editing of the signup date.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'svc_acct-disable_access_number',
+ 'section' => 'UI',
+ 'descritpion' => 'Disable access number selection.',
+ 'type' => 'checkbox',
+ },
+
+ { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "apachemachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "apachemachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "bindprimary", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "bindsecondaries", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "bsdshellmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "cyrus", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "cp_app", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "erpcdmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "icradiusmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "icradius_mysqldest", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "icradius_mysqlsource", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "icradius_secrets", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "maildisablecatchall", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "mxmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "nsmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "arecords", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "cnamerecords", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "nismachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "qmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "radiusmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "sendmailconfigpath", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "sendmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "sendmailrestart", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "shellmachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "shellmachine-useradd", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "shellmachine-userdel", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "shellmachine-usermod", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "shellmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "radiusprepend", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "textradiusprepend", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "username_policy", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "vpopmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "vpopmailrestart", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "safe-part_pkg", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "selfservice_server-quiet", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "signup_server-quiet", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "signup_server-email", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "vonage-username", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "vonage-password", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ { key => "vonage-fromnumber", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+
);
1;
+
diff --git a/FS/FS/Conf_compat17.pm b/FS/FS/Conf_compat17.pm
index 0f2e193..15d4738 100644
--- a/FS/FS/Conf_compat17.pm
+++ b/FS/FS/Conf_compat17.pm
@@ -443,10 +443,10 @@ httemplate/docs/config.html
},
{
- 'key' => 'business-onlinepayment-email_customer',
- 'section' => 'billing',
- 'description' => 'Controls the "email_customer" flag used by some Business::OnlinePayment processors to enable customer receipts.',
- 'type' => 'checkbox',
+ 'key' => 'business-onlinepayment-email_customer',
+ 'section' => 'billing',
+ 'description' => 'Controls the "email_customer" flag used by some Business::OnlinePayment processors to enable customer receipts.',
+ 'type' => 'checkbox',
},
{
@@ -484,7 +484,14 @@ httemplate/docs/config.html
{
'key' => 'deletecustomers',
'section' => 'UI',
- 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that this customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that the customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'deleteinvoices',
+ 'section' => 'UI',
+ 'description' => 'Enable invoices deletions. Be very careful! Deleting an invoice will remove all traces that the invoice ever existed! Normally, you would apply a credit against the invoice instead.', #invoice voiding?
'type' => 'checkbox',
},
@@ -643,6 +650,13 @@ httemplate/docs/config.html
},
{
+ 'key' => 'invoice_subject',
+ 'section' => 'billing',
+ 'description' => 'Subject: header on email invoices. Defaults to "Invoice". The following substitutions are available: $name, $name_short, $invoice_number, and $invoice_date.',
+ 'type' => 'text',
+ },
+
+ {
'key' => 'invoice_template',
'section' => 'required',
'description' => 'Required template file for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
@@ -1185,6 +1199,13 @@ httemplate/docs/config.html
'type' => 'checkbox',
},
+ {
+ 'key' => 'username-colon',
+ 'section' => 'username',
+ 'description' => 'Allow the colon character (:) in usernames.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'safe-part_bill_event',
'section' => 'UI',
@@ -1558,8 +1579,8 @@ httemplate/docs/config.html
{
'key' => 'paymentforcedtobatch',
- 'section' => 'UI',
- 'description' => 'Causes per customer payment entry to be forced to a batch processor rather than performed realtime.',
+ 'section' => 'deprecated',
+ 'description' => 'See batch-enable_payby and realtime-disable_payby. Used to (for CHEK): Cause per customer payment entry to be forced to a batch processor rather than performed realtime.',
'type' => 'checkbox',
},
@@ -1586,6 +1607,14 @@ httemplate/docs/config.html
'select_enum' => [ 'Framed-IP-Address', 'Framed-Address' ],
},
+ #http://dev.coova.org/svn/coova-chilli/doc/dictionary.chillispot
+ {
+ 'key' => 'radius-chillispot-max',
+ 'section' => '',
+ 'description' => 'Enable ChilliSpot (and CoovaChilli) Max attributes, specifically ChilliSpot-Max-{Input,Output,Total}-{Octets,Gigawords}.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'svc_acct-alldomains',
'section' => '',
@@ -1615,6 +1644,24 @@ httemplate/docs/config.html
},
{
+ 'key' => 'credit_card-recurring_billing_flag',
+ 'section' => 'billing',
+ 'description' => 'This controls when the system passes the "recurring_billing" flag on credit card transactions. If supported by your processor (and the Business::OnlinePayment processor module), passing the flag indicates this is a recurring transaction and may turn off the CVV requirement. ',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'actual_oncard' => 'Default/classic behavior: set the flag if a customer has actual previous charges on the card.',
+ 'transaction_is_recur' => 'Set the flag if the transaction itself is recurring, irregardless of previous charges on the card.',
+ ],
+ },
+
+ {
+ 'key' => 'credit_card-recurring_billing_acct_code',
+ 'section' => 'billing',
+ 'description' => 'When the "recurring billing" flag is set, also set the "acct_code" to "rebill". Useful for reporting purposes with supported gateways (PlugNPay, others?)',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'cvv-save',
'section' => 'billing',
'description' => 'Save CVV2 information after the initial transaction for the selected credit card types. Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option for any credit card types.',
@@ -1818,13 +1865,13 @@ httemplate/docs/config.html
'key' => 'address2-search',
'section' => 'UI',
'description' => 'Enable a "Unit" search box which searches the second address field',
- 'type' => 'checkbox',
+ 'type' => 'checkbox',
},
{
- 'key' => 'cust_main-require_address2',
- 'section' => 'UI',
- 'description' => 'Second address field is required (on service address only, if billing and service addresses differ). Also enables "Unit" labeling of address2 on customer view and edit pages. Useful for multi-tenant applications. See also: address2-search',
+ 'key' => 'cust_main-require_address2',
+ 'section' => 'UI',
+ 'description' => 'Second address field is required (on service address only, if billing and service addresses differ). Also enables "Unit" labeling of address2 on customer view and edit pages. Useful for multi-tenant applications. See also: address2-search',
'type' => 'checkbox',
},
@@ -2025,21 +2072,29 @@ httemplate/docs/config.html
'type' => 'select-sub',
'options_sub' => sub { require FS::Record;
require FS::part_pkg;
- map { $_->pkgpart => $_->pkg }
+ map { $_->pkgpart => $_->pkg }
FS::Record::qsearch('part_pkg', { disabled=>'' } );
- },
+ },
'option_sub' => sub { require FS::Record;
require FS::part_pkg;
- my $part_pkg = FS::Record::qsearchs(
- 'part_pkg', { 'pkgpart'=>shift }
- );
+ my $part_pkg = FS::Record::qsearchs(
+ 'part_pkg', { 'pkgpart'=>shift }
+ );
$part_pkg ? $part_pkg->pkg : '';
- },
+ },
},
{
- 'key' => 'batch-enable',
+ 'key' => 'postal_invoice-recurring_only',
'section' => 'billing',
+ 'description' => 'The postal invoice fee is omitted on invoices without recurring charges when this is set',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'batch-enable',
+ 'section' => 'deprecated', #make sure batch-enable_payby is set for
+ #everyone before removing
'description' => 'Enable credit card and/or ACH batching - leave disabled for real-time installations.',
'type' => 'checkbox',
},
@@ -2228,20 +2283,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'cust_main-require_phone',
- 'section' => '',
- 'description' => 'Require daytime or night for all customer records.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'cust_main-require_invoicing_list_email',
- 'section' => '',
- 'description' => 'Email address field is required: require at least one invoicing email address for all customer records.',
- 'type' => 'checkbox',
- },
-
- {
'key' => 'password-generated-allcaps',
'section' => 'password',
'description' => 'Causes passwords automatically generated to consist entirely of capital letters',
@@ -2277,6 +2318,20 @@ httemplate/docs/config.html
},
{
+ 'key' => 'cust_main-require_phone',
+ 'section' => '',
+ 'description' => 'Require daytime or night for all customer records.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-require_invoicing_list_email',
+ 'section' => '',
+ 'description' => 'Email address field is required: require at least one invoicing email address for all customer records.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'cancel_credit_type',
'section' => 'billing',
'description' => 'The group to use for new, automatically generated credit reasons resulting from cancellation.',
@@ -2388,7 +2443,7 @@ httemplate/docs/config.html
'description' => 'Default area code for customers.',
'type' => 'text',
},
-
+
{
'key' => 'cust_bill-max_same_services',
'section' => 'billing',
@@ -2396,6 +2451,69 @@ httemplate/docs/config.html
'type' => 'text',
},
+ {
+ 'key' => 'suspend_email_admin',
+ 'section' => '',
+ 'description' => 'Destination admin email address to enable suspension notices',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'email_report-subject',
+ 'section' => '',
+ 'description' => 'Subject for reports emailed by freeside-fetch. Defaults to "Freeside report".',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sg-multicustomer_hack',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'sg-ping_username',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sg-ping_password',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sg-login_username',
+ 'section' => '',
+ 'description' => "Don't use this.",
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'queued-max_kids',
+ 'section' => '',
+ 'description' => 'Maximum number of queued processes. Defaults to 10.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cancelled_cust-noevents',
+ 'section' => 'billing',
+ 'description' => "Don't run events for cancelled customers",
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'svc_broadband-manage_link',
+ 'section' => 'UI',
+ 'description' => 'URL for svc_broadband "Manage Device" link. The following substitutions are available: $ip_addr.',
+ 'type' => 'text',
+ },
+
);
1;
diff --git a/FS/FS/Cron/alert_expiration.pm b/FS/FS/Cron/alert_expiration.pm
new file mode 100644
index 0000000..a9b9da9
--- /dev/null
+++ b/FS/FS/Cron/alert_expiration.pm
@@ -0,0 +1,177 @@
+package FS::Cron::alert_expiration;
+
+use vars qw( @ISA @EXPORT_OK);
+use Exporter;
+use FS::Record qw(qsearch);
+use FS::Conf;
+use FS::cust_main;
+use FS::Misc;
+use Time::Local;
+use Date::Parse qw(str2time);
+
+
+@ISA = qw( Exporter );
+@EXPORT_OK = qw( alert_expiration );
+
+my $warning_time = 30 * 24 * 60 * 60;
+my $urgent_time = 15 * 24 * 60 * 60;
+my $panic_time = 5 * 24 * 60 * 60;
+my $window_time = 24 * 60 * 60;
+
+sub alert_expiration {
+ my $conf = new FS::Conf;
+ my $smtpmachine = $conf->config('smtpmachine');
+
+ my %opt = @_;
+ my ($_date) = $opt{'d'} ? str2time($opt{'d'}) : $^T;
+ $_date += $opt{'y'} * 86400 if $opt{'y'};
+ my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($_date)) [0..5];
+ $mon++;
+
+ my $debug = 0;
+ $debug = 1 if $opt{'v'};
+ $debug = $opt{'l'} if $opt{'l'};
+
+ $FS::cust_main::DEBUG = $debug;
+
+ # Get a list of customers.
+
+ my %limit;
+ $limit{'agentnum'} = $opt{'a'} if $opt{'a'};
+ $limit{'payby'} = $opt{'p'} if $opt{'p'};
+
+ my @customers;
+
+ if(my @custnums = @ARGV) {
+ # We're given an explicit list of custnums, so select those. Then check against
+ # -a and -p to avoid doing anything unexpected.
+ foreach (@custnums) {
+ my $customer = FS::cust_main->by_key($_);
+ if($customer and (!$opt{'a'} or $customer->agentnum == $opt{'a'})
+ and (!$opt{'p'} or $customer->payby eq $opt{'p'}) ) {
+ push @customers, $customer;
+ }
+ }
+ }
+ else { # no @ARGV
+ @customers = qsearch('cust_main', \%limit);
+ }
+ return if(!@customers);
+ foreach my $customer (@customers) {
+ my $paydate = $customer->paydate;
+ next if $paydate =~ /^\s*$/; # skip empty expiration dates
+
+ my $custnum = $customer->custnum;
+ my $first = $customer->first;
+ my $last = $customer->last;
+ my $company = $customer->company;
+ my $payby = $customer->payby;
+ my $payinfo = $customer->payinfo;
+ my $daytime = $customer->daytime;
+ my $night = $customer->night;
+
+ my ($paymonth, $payyear) = $customer->paydate_monthyear;
+ $paymonth--; # localtime() convention
+ $payday = 1; # This is enforced by FS::cust_main::check.
+ my $expire_time;
+ if($payby eq 'CARD' || $payby eq 'DCRD') {
+ # Credit cards expire at the end of the month/year.
+ if($paymonth == 11) {
+ $payyear++;
+ $paymonth = 0;
+ } else {
+ $paymonth++;
+ }
+ $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear) - 1;
+ }
+ else {
+ $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear);
+ }
+
+ if (grep { $expire_time < $_date + $_ &&
+ $expire_time > $_date + $_ - $window_time }
+ ($warning_time, $urgent_time, $panic_time) ) {
+ my $agentnum = $customer->agentnum;
+ $mail_sender = $conf->config('invoice_from', $agentnum);
+ $failure_recipient = $conf->config('invoice_from', $agentnum)
+ || 'postmaster';
+
+ my @alerter_template = $conf->config('alerter_template', $agentnum)
+ or die 'cannot load config file alerter_template';
+
+ my $alerter = new Text::Template(TYPE => 'ARRAY',
+ SOURCE => [
+ map "$_\n", @alerter_template
+ ])
+ or die "can't create Text::Template object: $Text::Template::ERROR";
+
+ $alerter->compile()
+ or die "can't compile template: $Text::Template::ERROR";
+
+ my @packages = $customer->ncancelled_pkgs;
+ if(@packages) {
+ my @invoicing_list = $customer->invoicing_list;
+ my @to_addrs = grep { $_ ne 'POST' } @invoicing_list;
+ if(@to_addrs) {
+ # Set up template fields.
+ my %fill_in;
+ $fill_in{$_} = $customer->getfield($_)
+ foreach(qw(first last company));
+ $fill_in{'expdate'} = $expire_time;
+ $fill_in{'company_name'} = $conf->config('company_name', $agentnum);
+ $fill_in{'company_address'} =
+ join("\n",$conf->config('company_address',$agentnum))."\n";
+ if($payby eq 'CARD' || $payby eq 'DCRD') {
+ $fill_in{'payby'} = "credit card (".
+ substr($customer->payinfo, 0, 2) . "xxxxxxxxxx" .
+ substr($payinfo, -4) . ")";
+ }
+ elsif($payby eq 'COMP') {
+ $fill_in{'payby'} = 'complimentary account';
+ }
+ else {
+ $fill_in{'payby'} = 'current method';
+ }
+ # Send it already!
+ my $error = FS::Misc::send_email (
+ from => $mail_sender,
+ to => [ @to_addrs ],
+ subject => 'Billing Arrangement Expiration',
+ body => [ $alerter->fill_in( HASH => \%fill_in ) ],
+ );
+ die "can't send expiration alert: $error"
+ if $error;
+ }
+ else { # if(@to_addrs)
+ push @{$agent_failure_body{$customer->agentnum}},
+ sprintf(qq{%5d %-32.32s %4s %10s %12s %12s},
+ $custnum,
+ $first . " " . $last . " " . $company,
+ $payby,
+ $paydate,
+ $daytime,
+ $night );
+ }
+ } # if(@packages)
+ } # if(expired)
+ } # foreach(@customers)
+
+ # Failure notification
+ foreach my $agentnum (keys %agent_failure_body) {
+ $mail_sender = $conf->config('invoice_from', $agentnum)
+ if($conf->exists('invoice_from', $agentnum));
+ $failure_recipient = $conf->config('invoice_from', $agentnum)
+ if($conf->exists('invoice_from', $agentnum));
+ my $error = FS::Misc::send_email (
+ from => $mail_sender,
+ to => $failure_recipient,
+ subject => 'Unnotified Billing Arrangement Expirations',
+ body => [ @{$agent_failure_body{$agentnum}} ],
+ );
+ die "can't send alerter failure email to $failure_recipient: $error"
+ if $error;
+ }
+
+}
+
+1;
diff --git a/FS/FS/Cron/bill.pm b/FS/FS/Cron/bill.pm
index ad6498c..dbb6c66 100644
--- a/FS/FS/Cron/bill.pm
+++ b/FS/FS/Cron/bill.pm
@@ -4,17 +4,26 @@ use strict;
use vars qw( @ISA @EXPORT_OK );
use Exporter;
use Date::Parse;
+use DBI 1.33; #The "clone" method was added in DBI 1.33.
use FS::UID qw(dbh);
-use FS::Record qw(qsearchs);
+use FS::Record qw( qsearch qsearchs );
+use FS::queue;
use FS::cust_main;
use FS::part_event;
use FS::part_event_condition;
@ISA = qw( Exporter );
-@EXPORT_OK = qw ( bill );
+@EXPORT_OK = qw ( bill bill_where );
-sub bill {
+#freeside-daily %opt:
+# -s: re-charge setup fees
+# -v: enable debugging
+# -l: debugging level
+# -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+# -r: Multi-process mode dry run option
+# -g: Don't bill these pkgparts
+sub bill {
my %opt = @_;
my $check_freq = $opt{'check_freq'} || '1d';
@@ -22,17 +31,135 @@ sub bill {
my $debug = 0;
$debug = 1 if $opt{'v'};
$debug = $opt{'l'} if $opt{'l'};
-
$FS::cust_main::DEBUG = $debug;
#$FS::cust_event::DEBUG = $opt{'l'} if $opt{'l'};
+ #we're at now now (and later).
+ $opt{'time'} = $opt{'d'} ? str2time($opt{'d'}) : $^T;
+ $opt{'time'} += $opt{'y'} * 86400 if $opt{'y'};
+
+ $opt{'invoice_time'} = $opt{'n'} ? $^T : $opt{'time'};
+
+ #hashref here doesn't work with -m
+ #my $not_pkgpart = $opt{g} ? { map { $_=>1 } split(/,\s*/, $opt{g}) }
+ # : {};
+
+ ###
+ # get a list of custnums
+ ###
+
+ my $cursor_dbh = dbh->clone;
+
+ $cursor_dbh->do(
+ "DECLARE cron_bill_cursor CURSOR FOR ".
+ " SELECT custnum FROM cust_main WHERE ". bill_where( %opt )
+ ) or die $cursor_dbh->errstr;
+
+ while ( 1 ) {
+
+ my $sth = $cursor_dbh->prepare('FETCH 100 FROM cron_bill_cursor'); #mysql?
+
+ $sth->execute or die $sth->errstr;
+
+ my @custnums = map { $_->[0] } @{ $sth->fetchall_arrayref };
+
+ last unless scalar(@custnums);
+
+ ###
+ # for each custnum, queue or make one customer object and bill
+ # (one at a time, to reduce memory footprint with large #s of customers)
+ ###
+
+ foreach my $custnum ( @custnums ) {
+
+ my %args = (
+ 'time' => $opt{'time'},
+ 'invoice_time' => $opt{'invoice_time'},
+ 'actual_time' => $^T, #when freeside-bill was started
+ #(not, when using -m, freeside-queued)
+ 'check_freq' => $check_freq,
+ 'resetup' => ( $opt{'s'} ? $opt{'s'} : 0 ),
+ 'not_pkgpart' => $opt{'g'}, #$not_pkgpart,
+ );
+
+ if ( $opt{'m'} ) {
+
+ if ( $opt{'r'} ) {
+ warn "DRY RUN: would add custnum $custnum for queued_bill\n";
+ } else {
+
+ #avoid queuing another job if there's one still waiting to run
+ next if qsearch( 'queue', { 'job' => 'FS::cust_main::queued_bill',
+ 'custnum' => $custnum,
+ 'status' => 'new',
+ }
+ );
+
+ #add job to queue that calls bill_and_collect with options
+ my $queue = new FS::queue {
+ 'job' => 'FS::cust_main::queued_bill',
+ 'secure' => 'Y',
+ 'priority' => 99, #don't get in the way of provisioning jobs
+ };
+ my $error = $queue->insert( 'custnum'=>$custnum, %args );
+
+ }
+
+ } else {
+
+ my $cust_main = qsearchs( 'cust_main', { 'custnum' => $custnum } );
+ $cust_main->bill_and_collect( %args, 'debug' => $debug );
+
+ }
+
+ }
+
+ }
+
+ $cursor_dbh->commit or die $cursor_dbh->errstr;
+
+}
+
+# freeside-daily %opt:
+# -d: Pretend it's 'date'. Date is in any format Date::Parse is happy with,
+# but be careful.
+#
+# -y: In addition to -d, which specifies an absolute date, the -y switch
+# specifies an offset, in days. For example, "-y 15" would increment the
+# "pretend date" 15 days from whatever was specified by the -d switch
+# (or now, if no -d switch was given).
+#
+# -n: When used with "-d" and/or "-y", specifies that invoices should be dated
+# with today's date, irregardless of the pretend date used to pre-generate
+# the invoices.
+#
+# -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
+#
+# -a: Only process customers with the specified agentnum
+#
+# -v: enable debugging
+#
+# -l: debugging level
+
+sub bill_where {
+ my( %opt ) = @_;
+
+ my $time = $opt{'time'};
+ my $invoice_time = $opt{'invoice_time'};
+
+ my $check_freq = $opt{'check_freq'} || '1d';
+
my @search = ();
+ push @search, "( cust_main.archived != 'Y' OR archived IS NULL )"; #disable?
+
push @search, "cust_main.payby = '". $opt{'p'}. "'"
if $opt{'p'};
push @search, "cust_main.agentnum = ". $opt{'a'}
if $opt{'a'};
+ #it would be useful if i recognized $opt{g} / $not_pkgpart...
+
if ( @ARGV ) {
push @search, "( ".
join(' OR ', map "cust_main.custnum = $_", @ARGV ).
@@ -43,23 +170,22 @@ sub bill {
# generate where_pkg/where_event search clause
###
- #we're at now now (and later).
- my($time)= $opt{'d'} ? str2time($opt{'d'}) : $^T;
- $time += $opt{'y'} * 86400 if $opt{'y'};
-
- my $invoice_time = $opt{'n'} ? $^T : $time;
-
# select * from cust_main where
my $where_pkg = <<"END";
- 0 < ( select count(*) from cust_pkg
- where cust_main.custnum = cust_pkg.custnum
- and ( cancel is null or cancel = 0 )
- and ( setup is null or setup = 0
- or bill is null or bill <= $time
- or ( expire is not null and expire <= $^T )
- or ( adjourn is not null and adjourn <= $^T )
- )
- )
+ EXISTS(
+ SELECT 1 FROM cust_pkg
+ WHERE cust_main.custnum = cust_pkg.custnum
+ AND ( cancel IS NULL OR cancel = 0 )
+ AND ( ( ( setup IS NULL OR setup = 0 )
+ AND ( start_date IS NULL OR start_date = 0
+ OR ( start_date IS NOT NULL AND start_date <= $^T )
+ )
+ )
+ OR bill IS NULL OR bill <= $time
+ OR ( expire IS NOT NULL AND expire <= $^T )
+ OR ( adjourn IS NOT NULL AND adjourn <= $^T )
+ )
+ )
END
my $where_event = join(' OR ', map {
@@ -69,23 +195,24 @@ END
my $where = FS::part_event_condition->where_conditions_sql( $eventtable,
'time'=>$time,
);
+ $where = $where ? "AND $where" : '';
my $are_part_event =
- "0 < ( SELECT COUNT(*) FROM part_event $join
- WHERE check_freq = '$check_freq'
- AND eventtable = '$eventtable'
- AND ( disabled = '' OR disabled IS NULL )
- AND $where
- )
+ "EXISTS ( SELECT 1 FROM part_event $join
+ WHERE check_freq = '$check_freq'
+ AND eventtable = '$eventtable'
+ AND ( disabled = '' OR disabled IS NULL )
+ $where
+ )
";
if ( $eventtable eq 'cust_main' ) {
$are_part_event;
} else {
- "0 < ( SELECT COUNT(*) FROM $eventtable
- WHERE cust_main.custnum = $eventtable.custnum
- AND $are_part_event
- )
+ "EXISTS ( SELECT 1 FROM $eventtable
+ WHERE cust_main.custnum = $eventtable.custnum
+ AND $are_part_event
+ )
";
}
@@ -93,54 +220,11 @@ END
push @search, "( $where_pkg OR $where_event )";
- ###
- # get a list of custnums
- ###
-
warn "searching for customers:\n". join("\n", @search). "\n"
if $opt{'v'} || $opt{'l'};
- my $sth = dbh->prepare(
- "SELECT custnum FROM cust_main".
- " WHERE ". join(' AND ', @search)
- ) or die dbh->errstr;
-
- $sth->execute or die $sth->errstr;
-
- my @custnums = map { $_->[0] } @{ $sth->fetchall_arrayref };
-
- ###
- # for each custnum, queue or make one customer object and bill
- # (one at a time, to reduce memory footprint with large #s of customers)
- ###
-
- foreach my $custnum ( @custnums ) {
-
- my %args = (
- 'time' => $time,
- 'invoice_time' => $invoice_time,
- 'actual_time' => $^T, #when freeside-bill was started
- #(not, when using -m, freeside-queued)
- 'check_freq' => $check_freq,
- 'resetup' => ( $opt{'s'} ? $opt{'s'} : 0 ),
- );
-
- if ( $opt{'m'} ) {
-
- #add job to queue that calls bill_and_collect with options
- my $queue = new FS::queue {
- 'job' => 'FS::cust_main::queued_bill',
- 'secure' => 'Y',
- };
- my $error = $queue->insert( 'custnum'=>$custnum, %args );
-
- } else {
-
- my $cust_main = qsearchs( 'cust_main', { 'custnum' => $custnum } );
- $cust_main->bill_and_collect( %args, 'debug' => $debug );
-
- }
-
- }
+ join(' AND ', @search);
}
+
+1;
diff --git a/FS/FS/Cron/check.pm b/FS/FS/Cron/check.pm
new file mode 100644
index 0000000..9d3ffbd
--- /dev/null
+++ b/FS/FS/Cron/check.pm
@@ -0,0 +1,200 @@
+package FS::Cron::check;
+
+use strict;
+use vars qw( @ISA @EXPORT_OK $DEBUG $FS_RUN $error_msg
+ $SELFSERVICE_USER $SELFSERVICE_MACHINES @SELFSERVICE_MACHINES
+ );
+use Exporter;
+use LWP::UserAgent;
+use HTTP::Request;
+use URI::Escape;
+use Email::Send;
+use FS::Conf;
+use FS::Record qw(qsearch);
+use FS::cust_pay_pending;
+
+@ISA = qw( Exporter );
+@EXPORT_OK = qw(
+ check_queued check_selfservice check_apache check_bop_failures
+ check_sg check_sg_login check_sgng
+ alert error_msg
+);
+
+$DEBUG = 0;
+
+$FS_RUN = '/var/run';
+
+sub check_queued {
+ _check_fsproc('queued');
+}
+
+$SELFSERVICE_USER = '%%%SELFSERVICE_USER%%%';
+
+$SELFSERVICE_MACHINES = '%%%SELFSERVICE_MACHINES%%%'; #substituted by Makefile
+$SELFSERVICE_MACHINES =~ s/^\s+//;
+$SELFSERVICE_MACHINES =~ s/\s+$//;
+@SELFSERVICE_MACHINES = split(/\s+/, $SELFSERVICE_MACHINES);
+@SELFSERVICE_MACHINES = ()
+ if scalar(@SELFSERVICE_MACHINES) == 1
+ && $SELFSERVICE_MACHINES[0] eq '%%%'.'SELFSERVICE_MACHINES'.'%%%';
+
+sub check_selfservice {
+ foreach my $machine ( @SELFSERVICE_MACHINES ) {
+ unless ( _check_fsproc("selfservice-server.$SELFSERVICE_USER.$machine") ) {
+ $error_msg = "Self-service daemon not running for $machine";
+ return 0;
+ }
+ }
+ return 1;
+}
+
+sub check_sg {
+ my $conf = new FS::Conf;
+ #different trigger if they ever stop using multicustomer_hack ?
+ return 1 unless $conf->exists('sg-multicustomer_hack');
+
+ my $ua = new LWP::UserAgent;
+ $ua->agent("FreesideCronCheck/0.1 " . $ua->agent);
+
+ my $USER = $conf->config('sg-ping_username');
+ my $PASS = $conf->config('sg-ping_password');
+ my $req = new HTTP::Request GET=>"https://$USER:$PASS\@localhost/sg/ping.cgi";
+ my $res = $ua->request($req);
+
+ return 1 if $res->is_success
+ && $res->content =~ /OK/
+ && $res->content !~ /error/i; #doh, the error message includes "OK"
+
+ $error_msg = $res->is_success ? $res->content : $res->status_line;
+ return 0;
+}
+
+sub check_sg_login {
+ my $conf = new FS::Conf;
+ #different trigger if they ever stop using multicustomer_hack ?
+ return 1 unless $conf->exists('sg-multicustomer_hack');
+
+ my $ua = new LWP::UserAgent;
+ $ua->agent("FreesideCronCheck/0.1 " . $ua->agent);
+
+ my $USER = $conf->config('sg-ping_username');
+ my $PASS = $conf->config('sg-ping_password');
+ my $USERNAME = $conf->config('sg-login_username');
+ my $req = new HTTP::Request
+ GET=>"https://$USER:$PASS\@localhost/sg/start.cgi?".
+ 'username='. uri_escape($USERNAME);
+ my $res = $ua->request($req);
+
+ return 1 if $res->is_success
+ && $res->content =~ /[\da-f]{32}/i #session_id
+ && $res->content !~ /error/i;
+
+ $error_msg = $res->is_success ? $res->content : $res->status_line;
+ return 0;
+}
+
+sub check_sgng {
+ my $conf = new FS::Conf;
+ #different trigger if they ever stop using multicustomer_hack ?
+ return 1 unless $conf->exists('sg-multicustomer_hack');
+
+ eval 'use RPC::XML; use RPC::XML::Client;';
+ if ($@) { $error_msg = $@; return 0; };
+
+ my $cli = RPC::XML::Client->new('https://localhost/selfservice/xmlrpc.cgi');
+ my $resp = $cli->send_request('FS.SelfService.XMLRPC.ping');
+
+ return 1 if ref($resp)
+ && ! $resp->is_fault
+ && ref($resp->value)
+ && $resp->value->{'pong'} == 1;
+
+ #hua
+ $error_msg = ref($resp)
+ ? ( $resp->is_fault
+ ? $resp->string
+ : ( ref($resp->value) ? $resp->value->{'error'}
+ : $resp->value
+ )
+ )
+ : $resp;
+ return 0;
+}
+
+sub _check_fsproc {
+ my $arg = shift;
+ _check_pidfile( "freeside-$arg.pid" );
+}
+
+sub _check_pidfile {
+ my $pidfile = shift;
+ open(PID, "$FS_RUN/$pidfile") or return 0;
+ chomp( my $pid = scalar(<PID>) );
+ close PID; # or return 0;
+
+ $pid && kill 0, $pid;
+}
+
+sub check_apache {
+ my $ua = new LWP::UserAgent;
+ $ua->agent("FreesideCronCheck/0.1 " . $ua->agent);
+
+ my $req = new HTTP::Request GET => 'https://localhost/';
+ my $res = $ua->request($req);
+
+ return 1 if $res->is_success || $res->status_line =~ /^403/;
+ $error_msg = $res->status_line;
+ return 0;
+
+}
+
+#and now for something entirely different...
+my $num_consecutive_bop_failures = 60;
+sub check_bop_failures {
+
+ return 1 if grep { $_->statustext eq 'captured' }
+ qsearch({
+ 'table' => 'cust_pay_pending',
+ 'hashref' => { 'status' => 'done' },
+ 'order_by' => 'ORDER BY paypendingnum DESC'.
+ " LIMIT $num_consecutive_bop_failures",
+ });
+ $error_msg = "Last $num_consecutive_bop_failures real-time payments failed";
+ return 0;
+}
+
+#
+
+sub error_msg {
+ $error_msg;
+}
+
+sub alert {
+ my( $alert, @emails ) = @_;
+
+ my $conf = new FS::Conf;
+ my $smtpmachine = $conf->config('smtpmachine');
+ my $company_name = $conf->config('company_name');
+
+ foreach my $email (@emails) {
+ warn "warning $email about $alert\n" if $DEBUG;
+
+ my $message = <<"__MESSAGE__";
+From: support\@freeside.biz
+To: $email
+Subject: FREESIDE ALERT for $company_name
+
+FREESIDE ALERT: $alert
+
+__MESSAGE__
+
+ my $sender = Email::Send->new({ mailer => 'SMTP' });
+ $sender->mailer_args([ Host => $smtpmachine ]);
+ $sender->send($message);
+
+ }
+
+}
+
+1;
+
diff --git a/FS/FS/Cron/notify.pm b/FS/FS/Cron/notify.pm
index 23cf920..5b0e186 100644
--- a/FS/FS/Cron/notify.pm
+++ b/FS/FS/Cron/notify.pm
@@ -35,7 +35,7 @@ sub notify_flat_delay {
and 0 < ( select count(*) from part_pkg_option
where part_pkg.pkgpart = part_pkg_option.pkgpart
and part_pkg_option.optionname = 'recur_notify'
- and part_pkg_option.optionvalue > 0
+ and CAST( part_pkg_option.optionvalue AS INTEGER ) > 0
and 0 <= ( $time
+ CAST( part_pkg_option.optionvalue AS $integer )
* 86400
@@ -62,7 +62,7 @@ END
0 = ( select count(*) from cust_pkg_option
where cust_pkg.pkgnum = cust_pkg_option.pkgnum
and cust_pkg_option.optionname = 'impending_recur_notification_sent'
- and cust_pkg_option.optionvalue = 1
+ and CAST( cust_pkg_option.optionvalue AS INTEGER ) = 1
)
END
diff --git a/FS/FS/Cron/upload.pm b/FS/FS/Cron/upload.pm
new file mode 100644
index 0000000..fea3d2c
--- /dev/null
+++ b/FS/FS/Cron/upload.pm
@@ -0,0 +1,176 @@
+package FS::Cron::upload;
+
+use strict;
+use vars qw( @ISA @EXPORT_OK $me $DEBUG );
+use Exporter;
+use Date::Format;
+use FS::UID qw(dbh);
+use FS::Record qw( qsearch qsearchs );
+use FS::Conf;
+use FS::queue;
+use FS::agent;
+use LWP::UserAgent;
+use HTTP::Request;
+use HTTP::Request::Common;
+use HTTP::Response;
+
+@ISA = qw( Exporter );
+@EXPORT_OK = qw ( upload );
+$DEBUG = 0;
+$me = '[FS::Cron::upload]';
+
+#freeside-daily %opt:
+# -v: enable debugging
+# -l: debugging level
+# -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+# -r: Multi-process mode dry run option
+# -a: Only process customers with the specified agentnum
+
+
+sub upload {
+ my %opt = @_;
+
+ my $debug = 0;
+ $debug = 1 if $opt{'v'};
+ $debug = $opt{'l'} if $opt{'l'};
+
+ local $DEBUG = $debug if $debug;
+
+ warn "$me upload called\n" if $DEBUG;
+
+ my $conf = new FS::Conf;
+ my @agent = grep { $conf->config( 'billco-username', $_->agentnum, 1 ) }
+ grep { $conf->config( 'billco-password', $_->agentnum, 1 ) }
+ qsearch( 'agent', {} );
+
+ my $date = time2str('%Y%m%d%H%M%S', $^T); # more?
+
+ @agent = grep { $_ == $opt{'a'} } @agent if $opt{'a'};
+
+ foreach my $agent ( @agent ) {
+
+ my $agentnum = $agent->agentnum;
+
+ if ( $opt{'m'} ) {
+
+ if ( $opt{'r'} ) {
+ warn "DRY RUN: would add agent $agentnum for queued upload\n";
+ } else {
+
+ my $queue = new FS::queue {
+ 'job' => 'FS::Cron::upload::billco_upload',
+ };
+ my $error = $queue->insert(
+ 'agentnum' => $agentnum,
+ 'date' => $date,
+ 'l' => $opt{'l'} || '',
+ 'm' => $opt{'m'} || '',
+ 'v' => $opt{'v'} || '',
+ );
+
+ }
+
+ } else {
+
+ eval "&billco_upload( 'agentnum' => $agentnum, 'date' => $date );";
+ warn "billco_upload failed: $@\n"
+ if ( $@ );
+
+ }
+
+ }
+
+}
+
+sub billco_upload {
+ my %opt = @_;
+
+ warn "$me billco_upload called\n" if $DEBUG;
+ my $conf = new FS::Conf;
+ my $dir = '%%%FREESIDE_EXPORT%%%/export.'. $FS::UID::datasrc. '/cust_bill';
+
+ my $agentnum = $opt{agentnum} or die "no agentnum provided\n";
+ my $url = $conf->config( 'billco-url', $agentnum )
+ or die "no url for agent $agentnum\n";
+ my $username = $conf->config( 'billco-username', $agentnum, 1 )
+ or die "no username for agent $agentnum\n";
+ my $password = $conf->config( 'billco-password', $agentnum, 1 )
+ or die "no password for agent $agentnum\n";
+ my $clicode = $conf->config( 'billco-clicode', $agentnum )
+ or die "no clicode for agent $agentnum\n";
+
+ die "no date provided\n" unless $opt{date};
+ my $zipfile = "$dir/agentnum$agentnum-$opt{date}.zip";
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $agent = qsearchs( 'agent', { agentnum => $agentnum } )
+ or die "no such agent: $agentnum";
+ $agent->select_for_update; #mutex
+
+ unless ( -f "$dir/agentnum$agentnum-header.csv" ||
+ -f "$dir/agentnum$agentnum-detail.csv" )
+ {
+ warn "$me neither $dir/agentnum$agentnum-header.csv nor ".
+ "$dir/agentnum$agentnum-detail.csv found\n" if $DEBUG;
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return;
+ }
+
+ # a better way?
+ if ($opt{m}) {
+ my $sql = "SELECT count(*) FROM queue LEFT JOIN cust_main USING(custnum) ".
+ "WHERE queue.job='FS::cust_main::queued_bill' AND cust_main.agentnum = ?";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ while (1) {
+ $sth->execute( $agentnum )
+ or die "Unexpected error executing statement $sql: ". $sth->errstr;
+ last if $sth->fetchow_arrayref->[0];
+ sleep 300;
+ }
+ }
+
+ foreach ( qw ( header detail ) ) {
+ rename "$dir/agentnum$agentnum-$_.csv",
+ "$dir/agentnum$agentnum-$opt{date}-$_.csv";
+ }
+
+ my $command = "cd $dir; zip $zipfile ".
+ "agentnum$agentnum-$opt{date}-header.csv ".
+ "agentnum$agentnum-$opt{date}-detail.csv";
+
+ system($command) and die "$command failed\n";
+
+ unlink "agentnum$agentnum-$opt{date}-header.csv",
+ "agentnum$agentnum-$opt{date}-detail.csv";
+
+ my $ua = new LWP::UserAgent;
+ my $res = $ua->request( POST( $url,
+ 'Content_Type' => 'form-data',
+ 'Content' => [ 'username' => $username,
+ 'pass' => $password,
+ 'custid' => $username,
+ 'clicode' => $clicode,
+ 'file1' => [ $zipfile ],
+ ],
+ )
+ );
+
+ die "upload failed: ". $res->status_line. "\n"
+ unless $res->is_success;
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
+1;
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index ee777a4..6e6072e 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -1,8 +1,9 @@
package FS::Mason;
use strict;
-use vars qw( @ISA @EXPORT_OK );
+use vars qw( @ISA @EXPORT_OK $addl_handler_use );
use Exporter;
+use File::Slurp qw( slurp );
use HTML::Mason 1.27; #http://www.masonhq.com/?ApacheModPerl2Redirect
use HTML::Mason::Interp;
use HTML::Mason::Compiler::ToObject;
@@ -30,6 +31,12 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
=cut
+$addl_handler_use = '';
+my $addl_handler_use_file = '%%%FREESIDE_CONF%%%/addl_handler_use.pl';
+if ( -e $addl_handler_use_file ) {
+ $addl_handler_use = slurp( $addl_handler_use_file );
+}
+
# List of modules that you want to use from components (see Admin
# manual for details)
{
@@ -38,6 +45,13 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use strict;
use vars qw( %session );
use CGI 3.29 qw(-private_tempfiles); #3.29 to fix RT attachment problems
+
+ #breaks quick payment entry
+ #http://rt.cpan.org/Public/Bug/Display.html?id=37365
+ die "CGI.pm v3.38 is broken, use any other version >= 3.29".
+ " (Debian 5.0? aptitude remove libcgi-pm-perl)"
+ if $CGI::VERSION == 3.38;
+
#use CGI::Carp qw(fatalsToBrowser);
use CGI::Cookie;
use List::Util qw( max min );
@@ -45,12 +59,13 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use Date::Format;
use Date::Parse;
use Time::Local;
+ use Time::HiRes;
use Time::Duration;
use DateTime;
use DateTime::Format::Strptime;
use Lingua::EN::Inflect qw(PL);
use Tie::IxHash;
- use URI::URL;
+ use URI;
use URI::Escape;
use HTML::Entities;
use HTML::TreeBuilder;
@@ -70,6 +85,19 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use Spreadsheet::WriteExcel;
use Business::CreditCard 0.30; #for mask-aware cardtype()
use NetAddr::IP;
+ use Net::Ping;
+ use Net::Ping::External;
+ #if CPAN #7815 ever gets fixed# if ( $Net::Ping::External::VERSION <= 0.12 )
+ {
+ no warnings 'redefine';
+ eval 'sub Net::Ping::External::_ping_linux {
+ my %args = @_;
+ my $command = "ping -s $args{size} -c $args{count} -w $args{timeout} $args{host}";
+ return Net::Ping::External::_ping_system($command, 0);
+ }
+ ';
+ die $@ if $@;
+ }
use String::Approx qw(amatch);
use Chart::LinesPoints;
use Chart::Mountain;
@@ -91,6 +119,7 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use FS::UI::bytecount;
use FS::Msgcat qw(gettext geterror);
use FS::Misc qw( send_email send_fax states_hash counties state_label );
+ use FS::Misc::eps2png qw( eps2png );
use FS::Report::Table::Monthly;
use FS::TicketSystem;
use FS::Tron qw( tron_lint );
@@ -166,6 +195,8 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use FS::access_right;
use FS::AccessRight;
use FS::svc_phone;
+ use FS::phone_device;
+ use FS::part_device;
use FS::reason_type;
use FS::reason;
use FS::cust_main_note;
@@ -175,6 +206,25 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
use FS::part_pkg_taxoverride;
use FS::part_pkg_taxrate;
use FS::tax_rate;
+ use FS::part_pkg_report_option;
+ use FS::cust_attachment;
+ use FS::h_cust_pkg;
+ use FS::h_svc_acct;
+ use FS::h_svc_broadband;
+ use FS::h_svc_domain;
+ #use FS::h_domain_record;
+ use FS::h_svc_external;
+ use FS::h_svc_forward;
+ use FS::h_svc_phone;
+ #use FS::h_phone_device;
+ use FS::h_svc_www;
+ use FS::cust_statement;
+ # Sammath Naur
+
+ if ( $FS::Mason::addl_handler_use ) {
+ eval $FS::Mason::addl_handler_use;
+ die $@ if $@;
+ }
if ( %%%RT_ENABLED%%% ) {
eval '
@@ -211,7 +261,7 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc.
#slow, unreliable, segfaults and is optional
#see rt/html/Ticket/Elements/ShowTransactionAttachments
- #use Text::Quoted;
+ use Text::Quoted;
#?#use File::Path qw( rmtree );
#?#use File::Glob qw( bsd_glob );
@@ -351,6 +401,21 @@ sub mason_interps {
RT::LoadConfig();
}
+ # A hook supporting strange legacy ways people have added stuff on
+
+ my @addl_comp_root = ();
+ my $addl_comp_root_file = '%%%FREESIDE_CONF%%%/addl_comp_root.pl';
+ if ( -e $addl_comp_root_file ) {
+ warn "reading $addl_comp_root_file\n";
+ my $text = slurp( $addl_comp_root_file );
+ my @addl = eval $text;
+ if ( @addl && ! $@ ) {
+ @addl_comp_root = @addl;
+ } elsif ($@) {
+ warn "error parsing $addl_comp_root_file: $@\n";
+ }
+ }
+
my %interp = (
request_class => $request_class,
data_dir => '%%%MASONDATA%%%',
@@ -360,6 +425,7 @@ sub mason_interps {
comp_root => [
[ 'freeside'=>'%%%FREESIDE_DOCUMENT_ROOT%%%' ],
[ 'rt' =>'%%%FREESIDE_DOCUMENT_ROOT%%%/rt' ],
+ @addl_comp_root,
],
);
@@ -374,6 +440,9 @@ sub mason_interps {
${$_[0]} = "'". ${$_[0]}. "'";
}
},
+ compiler => HTML::Mason::Compiler::ToObject->new(
+ allow_globals => [qw(%session)],
+ ),
);
my $rt_interp = new HTML::Mason::Interp (
diff --git a/FS/FS/Misc/eps2png.pm b/FS/FS/Misc/eps2png.pm
new file mode 100644
index 0000000..aa8e572
--- /dev/null
+++ b/FS/FS/Misc/eps2png.pm
@@ -0,0 +1,278 @@
+package FS::Misc::eps2png;
+
+#based on eps2png by Johan Vromans
+#Copyright 1994,2008 by Johan Vromans.
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of the Perl Artistic License or the
+#GNU General Public License as published by the Free Software
+#Foundation; either version 2 of the License, or (at your option) any
+#later version.
+
+use strict;
+use vars qw( @ISA @EXPORT_OK );
+use Exporter;
+use File::Temp;
+use File::Slurp qw( slurp );
+#use FS::UID;
+
+@ISA = qw( Exporter );
+@EXPORT_OK = qw( eps2png );
+
+################ Program parameters ################
+
+# Some GhostScript programs can produce GIF directly.
+# If not, we need the PBM package for the conversion.
+# NOTE: This will be changed upon install.
+my $use_pbm = 0;
+
+my $res = 82; # default resolution
+my $scale = 1; # default scaling
+my $mono = 0; # produce BW images if non-zero
+my $format; # output format
+my $gs_format; # GS output type
+my $output; # output, defaults to STDOUT
+my $antialias = 4; # antialiasing
+my $DEF_width; # desired widht
+my $DEF_height; # desired height
+#my $DEF_width = 90; # desired widht
+#my $DEF_height = 36; # desired height
+
+my ($verbose,$trace,$test,$debug) = (0,0,0,0);
+#handle_options ();
+set_out_type ('png'); # unless defined $format;
+warn "Producing $format ($gs_format) image.\n" if $verbose;
+
+$trace |= $test | $debug;
+$verbose |= $trace;
+
+################ Presets ################
+
+################ The Process ################
+
+my $err = 0;
+
+sub eps2png {
+ my( $eps, %options ) = @_; #well, no options yet
+
+ my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
+ my $eps_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
+ DIR => $dir,
+ SUFFIX => '.eps',
+ #UNLINK => 0,
+ ) or die "can't open temp file: $!\n";
+ print $eps_file $eps;
+ close $eps_file;
+
+ my @eps = split(/\r?\n/, $eps);
+
+ warn "converting eps (". length($eps). " bytes, ". scalar(@eps). " lines)\n"
+ if $verbose;
+
+ my $line = shift @eps; #<EPS>;
+ unless ( $eps =~ /^%!PS-Adobe.*EPSF-/ ) {
+ warn "not EPS file (no %!PS-Adobe header)\n";
+ return; #empty png file?
+ }
+
+ my $ps = ""; # PostScript input data
+ my $xscale;
+ my $yscale;
+ my $gotbb;
+
+ # Prevent derived values from propagating.
+ my $width = $DEF_width;
+ my $height = $DEF_height;
+
+ while ( @eps ) {
+
+ $line = shift(@eps)."\n";
+
+ # Search for BoundingBox.
+ if ( $line =~ /^%%BoundingBox:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/i ) {
+ $gotbb++;
+ warn "$eps_file: x0=$1, y0=$2, w=", $3-$1, ", h=", $4-$2
+ if $verbose;
+
+ if ( defined $width ) {
+ $res = 72;
+ $xscale = $width / ($3 - $1);
+ if ( defined $height ) {
+ $yscale = $height / ($4 - $2);
+ }
+ else {
+ $yscale = $xscale;
+ $height = ($4 - $2) * $yscale;
+ }
+ }
+ elsif ( defined $height ) {
+ $res = 72;
+ $yscale = $height / ($4 - $2);
+ if ( defined $width ) {
+ $xscale = $width / ($3 - $1);
+ }
+ else {
+ $xscale = $yscale;
+ $width = ($3 - $1) * $xscale;
+ }
+ }
+ unless ( defined $xscale ) {
+ $xscale = $yscale = $scale;
+ # Calculate actual width.
+ $width = $3 - $1;
+ $height = $4 - $2;
+ # Normal PostScript resolution is 72.
+ $width *= $res/72 * $xscale;
+ $height *= $res/72 * $yscale;
+ # Round up.
+ $width = int ($width + 0.5) + 1;
+ $height = int ($height + 0.5) + 1;
+ }
+ warn ", width=$width, height=$height\n" if $verbose;
+
+ # Scale.
+ $ps .= "$xscale $yscale scale\n"
+ if $xscale != 1 || $yscale != 1;
+
+ # Create PostScript code to translate coordinates.
+ $ps .= (0-$1) . " " . (0-$2) . " translate\n"
+ unless $1 == 0 && $2 == 0;
+
+ # Include the image, show and quit.
+ $ps .= "($eps_file) run\n".
+ "showpage\n".
+ "quit\n";
+
+ last;
+ }
+ elsif ( $line =~ /^%%EndComments/i ) {
+ last;
+ }
+ }
+
+ unless ( $gotbb ) {
+ warn "No bounding box in $eps_file\n";
+ return;
+ }
+
+ #it would be better to ask gs to spit out files on stdout, but c'est la vie
+
+ #my $out_file; # output file
+ #my $pbm_file; # temporary file for PBM conversion
+
+ my $out_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
+ DIR => $dir,
+ SUFFIX => '.png',
+ #UNLINK => 0,
+ ) or die "can't open temp file: $!\n";
+
+ my $pbm_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
+ DIR => $dir,
+ SUFFIX => '.pbm',
+ #UNLINK => 0,
+ ) or die "can't open temp file: $!\n";
+
+ # Note the temporary PBM file is created where the output file is
+ # located, since that will guarantee accessibility (and a valid
+ # filename).
+ warn "Creating $out_file\n" if $verbose;
+
+ my $gs0 = "gs -q -dNOPAUSE -r$res -g${width}x$height";
+ my $gs1 = "-";
+ $gs0 .= " -dTextAlphaBits=$antialias -dGraphicsAlphaBits=$antialias"
+ if $antialias;
+ if ( $format eq 'png' ) {
+ mysystem ("$gs0 -sDEVICE=". ($mono ? "pngmono" : $gs_format).
+ " -sOutputFile=$out_file $gs1", $ps);
+ }
+ elsif ( $format eq 'jpg' ) {
+ mysystem ("$gs0 -sDEVICE=". ($mono ? "jpeggray" : $gs_format).
+ " -sOutputFile=$out_file $gs1", $ps);
+ }
+ elsif ( $format eq 'gif' ) {
+ if ( $use_pbm ) {
+ # Convert to PPM and use some of the PBM converters.
+ mysystem ("$gs0 -sDEVICE=". ($mono ? "pbm" : "ppm").
+ " -sOutputFile=$pbm_file $gs1", $ps);
+ # mysystem ("pnmcrop $pbm_file | ppmtogif > $out_file");
+ mysystem ("ppmtogif $pbm_file > $out_file");
+ unlink ($pbm_file);
+ }
+ else {
+ # GhostScript has GIF drivers built-in.
+ mysystem ("$gs0 -sDEVICE=". ($mono ? "gifmono" : "gif8").
+ " -sOutputFile=$out_file $gs1", $ps);
+ }
+ }
+ else {
+ warn "ASSERT ERROR: Unhandled output type: $format\n";
+ exit (1);
+ }
+
+# unless ( -s $out_file ) {
+# warn "Problem creating $out_file for $eps_file\n";
+# $err++;
+# }
+
+ slurp($out_file);
+
+}
+
+exit 1 if $err;
+
+################ Subroutines ################
+
+sub mysystem {
+ my ($cmd, $data) = @_;
+ warn "+ $cmd\n" if $trace;
+ if ( $data ) {
+ if ( $trace ) {
+ my $dp = ">> " . $data;
+ $dp =~ s/\n(.)/\n>> $1/g;
+ warn "$dp";
+ }
+ open (CMD, "|$cmd") or die ("$cmd: $!\n");
+ print CMD $data;
+ close CMD or die ("$cmd close: $!\n");
+ }
+ else {
+ system ($cmd);
+ }
+}
+
+sub set_out_type {
+ my ($opt) = lc (shift (@_));
+ if ( $opt =~ /^png(mono|gray|16|256|16m|alpha)?$/ ) {
+ $format = 'png';
+ $gs_format = $format.(defined $1 ? $1 : '16m');
+ }
+ elsif ( $opt =~ /^gif(mono)?$/ ) {
+ $format = 'gif';
+ $gs_format = $format.(defined $1 ? $1 : '');
+ }
+ elsif ( $opt =~ /^(jpg|jpeg)(gray)?$/ ) {
+ $format = 'jpg';
+ $gs_format = 'jpeg'.(defined $2 ? $2 : '');
+ }
+ else {
+ warn "ASSERT ERROR: Invalid value to set_out_type: $opt\n";
+ exit (1);
+ }
+}
+
+# 'antialias|aa=i' => \$antialias,
+# 'noantialias|noaa' => sub { $antialias = 0 },
+# 'scale=f' => \$scale,
+# 'width=i' => \$width,
+# 'height=i' => \$height,
+# 'resolution=i' => \$res,
+
+# die ("Antialias value must be 0, 1, 2, 4, or 8\n")
+
+# -width XXX desired with
+# -height XXX desired height
+# -resolution XXX resolution (default = $res)
+# -scale XXX scaling factor
+# -antialias XX antialias factor (must be 0, 1, 2, 4 or 8; default: 4)
+# -noantialias no antialiasing (same as -antialias 0)
+
+1;
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 2d0263b..d4d7ca1 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -54,9 +54,14 @@ FS::UID->install_callback( sub {
$conf = FS::Conf->new;
$conf_encryption = $conf->exists('encryption');
$File::CounterFile::DEFAULT_DIR = $conf->base_dir . "/counters.". datasrc;
+ if ( driver_name eq 'Pg' ) {
+ eval "use DBD::Pg ':pg_types'";
+ die $@ if $@;
+ } else {
+ eval "sub PG_BYTEA { die 'guru meditation #9: calling PG_BYTEA when not running Pg?'; }";
+ }
} );
-
=head1 NAME
FS::Record - Database record objects
@@ -215,29 +220,33 @@ objects.
The preferred usage is to pass a hash reference of named parameters:
- my @records = qsearch( {
- 'table' => 'table_name',
- 'hashref' => { 'field' => 'value'
- 'field' => { 'op' => '<',
- 'value' => '420',
- },
- },
-
- #these are optional...
- 'select' => '*',
- 'extra_sql' => 'AND field ',
- 'order_by' => 'ORDER BY something',
- #'cache_obj' => '', #optional
- 'addl_from' => 'LEFT JOIN othtable USING ( field )',
- 'debug' => 1,
- }
- );
+ @records = qsearch( {
+ 'table' => 'table_name',
+ 'hashref' => { 'field' => 'value'
+ 'field' => { 'op' => '<',
+ 'value' => '420',
+ },
+ },
+
+ #these are optional...
+ 'select' => '*',
+ 'extra_sql' => 'AND field = ? AND intfield = ?',
+ 'extra_param' => [ 'value', [ 5, 'int' ] ],
+ 'order_by' => 'ORDER BY something',
+ #'cache_obj' => '', #optional
+ 'addl_from' => 'LEFT JOIN othtable USING ( field )',
+ 'debug' => 1,
+ }
+ );
Much code still uses old-style positional parameters, this is also probably
fine in the common case where there are only two parameters:
my @records = qsearch( 'table', { 'field' => 'value' } );
+Also possible is an experimental LISTREF of PARAMS_HASHREFs for a UNION of
+the individual PARAMS_HASHREF queries
+
###oops, argh, FS::Record::new only lets us create database fields.
#Normal behaviour if SELECT is not specified is `*', as in
#C<SELECT * FROM table WHERE ...>. However, there is an experimental new
@@ -251,8 +260,40 @@ fine in the common case where there are only two parameters:
my %TYPE = (); #for debugging
+sub _bind_type {
+ my($type, $value) = @_;
+
+ my $bind_type = { TYPE => SQL_VARCHAR };
+
+ if ( $type =~ /(big)?(int|serial)/i && $value =~ /^\d+(\.\d+)?$/ ) {
+
+ $bind_type = { TYPE => SQL_INTEGER };
+
+ } elsif ( $type =~ /^bytea$/i || $type =~ /(blob|varbinary)/i ) {
+
+ if ( driver_name eq 'Pg' ) {
+ no strict 'subs';
+ $bind_type = { pg_type => PG_BYTEA };
+ #} else {
+ # $bind_type = ? #SQL_VARCHAR could be fine?
+ }
+
+ #DBD::Pg 1.49: Cannot bind ... unknown sql_type 6 with SQL_FLOAT
+ #fixed by DBD::Pg 2.11.8
+ #can change back to SQL_FLOAT in early-mid 2010, once everyone's upgraded
+ #(make a Tron test first)
+ } elsif ( _is_fs_float( $type, $value ) ) {
+
+ $bind_type = { TYPE => SQL_DECIMAL };
+
+ }
+
+ $bind_type;
+
+}
+
sub _is_fs_float {
- my ($type, $value) = @_;
+ my($type, $value) = @_;
if ( ( $type =~ /(numeric)/i && $value =~ /^[+-]?\d+(\.\d+)?$/ ) ||
( $type =~ /(real|float4)/i && $value =~ /[-+]?\d*\.?\d+([eE][-+]?\d+)?/)
) {
@@ -262,101 +303,147 @@ sub _is_fs_float {
}
sub qsearch {
- my($stable, $record, $select, $extra_sql, $order_by, $cache, $addl_from );
- my $debug = '';
- if ( ref($_[0]) ) { #hashref for now, eventually maybe accept a list too
+ my( @stable, @record, @cache );
+ my( @select, @extra_sql, @extra_param, @order_by, @addl_from );
+ my @debug = ();
+ my %union_options = ();
+ if ( ref($_[0]) eq 'ARRAY' ) {
+ my $optlist = shift;
+ %union_options = @_;
+ foreach my $href ( @$optlist ) {
+ push @stable, ( $href->{'table'} or die "table name is required" );
+ push @record, ( $href->{'hashref'} || {} );
+ push @select, ( $href->{'select'} || '*' );
+ push @extra_sql, ( $href->{'extra_sql'} || '' );
+ push @extra_param, ( $href->{'extra_param'} || [] );
+ push @order_by, ( $href->{'order_by'} || '' );
+ push @cache, ( $href->{'cache_obj'} || '' );
+ push @addl_from, ( $href->{'addl_from'} || '' );
+ push @debug, ( $href->{'debug'} || '' );
+ }
+ die "at least one hashref is required" unless scalar(@stable);
+ } elsif ( ref($_[0]) eq 'HASH' ) {
my $opt = shift;
- $stable = $opt->{'table'} or die "table name is required";
- $record = $opt->{'hashref'} || {};
- $select = $opt->{'select'} || '*';
- $extra_sql = $opt->{'extra_sql'} || '';
- $order_by = $opt->{'order_by'} || '';
- $cache = $opt->{'cache_obj'} || '';
- $addl_from = $opt->{'addl_from'} || '';
- $debug = $opt->{'debug'} || '';
+ $stable[0] = $opt->{'table'} or die "table name is required";
+ $record[0] = $opt->{'hashref'} || {};
+ $select[0] = $opt->{'select'} || '*';
+ $extra_sql[0] = $opt->{'extra_sql'} || '';
+ $extra_param[0] = $opt->{'extra_param'} || [];
+ $order_by[0] = $opt->{'order_by'} || '';
+ $cache[0] = $opt->{'cache_obj'} || '';
+ $addl_from[0] = $opt->{'addl_from'} || '';
+ $debug[0] = $opt->{'debug'} || '';
} else {
- ($stable, $record, $select, $extra_sql, $cache, $addl_from ) = @_;
- $select ||= '*';
+ ( $stable[0],
+ $record[0],
+ $select[0],
+ $extra_sql[0],
+ $cache[0],
+ $addl_from[0]
+ ) = @_;
+ $select[0] ||= '*';
}
+ my $cache = $cache[0];
- #$stable =~ /^([\w\_]+)$/ or die "Illegal table: $table";
- #for jsearch
- $stable =~ /^([\w\s\(\)\.\,\=]+)$/ or die "Illegal table: $stable";
- $stable = $1;
+ my @statement = ();
+ my @value = ();
+ my @bind_type = ();
my $dbh = dbh;
+ foreach my $stable ( @stable ) {
+ my $record = shift @record;
+ my $select = shift @select;
+ my $extra_sql = shift @extra_sql;
+ my $extra_param = shift @extra_param;
+ my $order_by = shift @order_by;
+ my $cache = shift @cache;
+ my $addl_from = shift @addl_from;
+ my $debug = shift @debug;
+
+ #$stable =~ /^([\w\_]+)$/ or die "Illegal table: $table";
+ #for jsearch
+ $stable =~ /^([\w\s\(\)\.\,\=]+)$/ or die "Illegal table: $stable";
+ $stable = $1;
+
+ my $table = $cache ? $cache->table : $stable;
+ my $dbdef_table = dbdef->table($table)
+ or die "No schema for table $table found - ".
+ "do you need to run freeside-upgrade?";
+ my $pkey = $dbdef_table->primary_key;
+
+ my @real_fields = grep exists($record->{$_}), real_fields($table);
+ my @virtual_fields;
+ if ( eval 'scalar(@FS::'. $table. '::ISA);' ) {
+ @virtual_fields = grep exists($record->{$_}), "FS::$table"->virtual_fields;
+ } else {
+ cluck "warning: FS::$table not loaded; virtual fields not searchable"
+ unless $nowarn_classload;
+ @virtual_fields = ();
+ }
- my $table = $cache ? $cache->table : $stable;
- my $dbdef_table = dbdef->table($table)
- or die "No schema for table $table found - ".
- "do you need to run freeside-upgrade?";
- my $pkey = $dbdef_table->primary_key;
+ my $statement .= "SELECT $select FROM $stable";
+ $statement .= " $addl_from" if $addl_from;
+ if ( @real_fields or @virtual_fields ) {
+ $statement .= ' WHERE '. join(' AND ',
+ get_real_fields($table, $record, \@real_fields) ,
+ get_virtual_fields($table, $pkey, $record, \@virtual_fields),
+ );
+ }
- my @real_fields = grep exists($record->{$_}), real_fields($table);
- my @virtual_fields;
- if ( eval 'scalar(@FS::'. $table. '::ISA);' ) {
- @virtual_fields = grep exists($record->{$_}), "FS::$table"->virtual_fields;
- } else {
- cluck "warning: FS::$table not loaded; virtual fields not searchable"
- unless $nowarn_classload;
- @virtual_fields = ();
- }
+ $statement .= " $extra_sql" if defined($extra_sql);
+ $statement .= " $order_by" if defined($order_by);
- my $statement = "SELECT $select FROM $stable";
- $statement .= " $addl_from" if $addl_from;
- if ( @real_fields or @virtual_fields ) {
- $statement .= ' WHERE '. join(' AND ',
- get_real_fields($table, $record, \@real_fields) ,
- get_virtual_fields($table, $pkey, $record, \@virtual_fields),
- );
- }
+ push @statement, $statement;
- $statement .= " $extra_sql" if defined($extra_sql);
- $statement .= " $order_by" if defined($order_by);
+ warn "[debug]$me $statement\n" if $DEBUG > 1 || $debug;
+
- warn "[debug]$me $statement\n" if $DEBUG > 1 || $debug;
- my $sth = $dbh->prepare($statement)
- or croak "$dbh->errstr doing $statement";
+ foreach my $field (
+ grep defined( $record->{$_} ) && $record->{$_} ne '', @real_fields
+ ) {
- my $bind = 1;
+ my $value = $record->{$field};
+ my $op = (ref($value) && $value->{op}) ? $value->{op} : '=';
+ $value = $value->{'value'} if ref($value);
+ my $type = dbdef->table($table)->column($field)->type;
- foreach my $field (
- grep defined( $record->{$_} ) && $record->{$_} ne '', @real_fields
- ) {
+ my $bind_type = _bind_type($type, $value);
- my $value = $record->{$field};
- my $op = (ref($value) && $value->{op}) ? $value->{op} : '=';
- $value = $value->{'value'} if ref($value);
- my $type = dbdef->table($table)->column($field)->type;
+ #if ( $DEBUG > 2 ) {
+ # no strict 'refs';
+ # %TYPE = map { &{"DBI::$_"}() => $_ } @{ $DBI::EXPORT_TAGS{sql_types} }
+ # unless keys %TYPE;
+ # warn " bind_param $bind (for field $field), $value, TYPE $TYPE{$TYPE}\n";
+ #}
- my $TYPE = SQL_VARCHAR;
- if ( $type =~ /(big)?(int|serial)/i && $value =~ /^\d+(\.\d+)?$/ ) {
- $TYPE = SQL_INTEGER;
+ push @value, $value;
+ push @bind_type, $bind_type;
- #DBD::Pg 1.49: Cannot bind ... unknown sql_type 6 with SQL_FLOAT
- #fixed by DBD::Pg 2.11.8
- #can change back to SQL_FLOAT in early-mid 2010, once everyone's upgraded
- } elsif ( _is_fs_float( $type, $value ) ) {
- $TYPE = SQL_DECIMAL;
}
- if ( $DEBUG > 2 ) {
- no strict 'refs';
- %TYPE = map { &{"DBI::$_"}() => $_ } @{ $DBI::EXPORT_TAGS{sql_types} }
- unless keys %TYPE;
- warn " bind_param $bind (for field $field), $value, TYPE $TYPE{$TYPE}\n";
+ foreach my $param ( @$extra_param ) {
+ my $bind_type = { TYPE => SQL_VARCHAR };
+ my $value = $param;
+ if ( ref($param) ) {
+ $value = $param->[0];
+ my $type = $param->[1];
+ $bind_type = _bind_type($type, $value);
+ }
+ push @value, $value;
+ push @bind_type, $bind_type;
}
+ }
- #if this needs to be re-enabled, it needs to use a custom op like
- #"APPROX=" or something (better name?, not '=', to avoid affecting other
- # searches
- #if ($TYPE eq SQL_DECIMAL && $op eq 'APPROX=' ) {
- # # these values are arbitrary; better (faster?) ones welcome
- # $sth->bind_param($bind++, $value*1.00001, { TYPE => $TYPE } );
- # $sth->bind_param($bind++, $value*.99999, { TYPE => $TYPE } );
- #} else {
- $sth->bind_param($bind++, $value, { TYPE => $TYPE } );
- #}
+ my $statement = join( ' ) UNION ( ', @statement );
+ $statement = "( $statement )" if scalar(@statement) > 1;
+ $statement .= " $union_options{order_by}" if $union_options{order_by};
+
+ my $sth = $dbh->prepare($statement)
+ or croak "$dbh->errstr doing $statement";
+ my $bind = 1;
+ foreach my $value ( @value ) {
+ my $bind_type = shift @bind_type;
+ $sth->bind_param($bind++, $value, $bind_type );
}
# $sth->execute( map $record->{$_},
@@ -365,6 +452,13 @@ sub qsearch {
$sth->execute or croak "Error executing \"$statement\": ". $sth->errstr;
+ # virtual fields and blessings are nonsense in a heterogeneous UNION, right?
+ my $table = $stable[0];
+ my $pkey = '';
+ $table = '' if grep { $_ ne $table } @stable;
+ $pkey = dbdef->table($table)->primary_key if $table;
+
+ my @virtual_fields = ();
if ( eval 'scalar(@FS::'. $table. '::ISA);' ) {
@virtual_fields = "FS::$table"->virtual_fields;
} else {
@@ -1165,7 +1259,10 @@ sub replace {
# Encrypt for replace
my $saved = {};
- if ($conf->exists('encryption') && defined(eval '@FS::'. $new->table . '::encrypted_fields')) {
+ if ( $conf->exists('encryption')
+ && defined(eval '@FS::'. $new->table . '::encrypted_fields')
+ && scalar( eval '@FS::'. $new->table . '::encrypted_fields')
+ ) {
foreach my $field (eval '@FS::'. $new->table . '::encrypted_fields') {
$saved->{$field} = $new->getfield($field);
$new->setfield($field, $new->encrypt($new->getfield($field)));
@@ -1692,11 +1789,14 @@ sub batch_import {
my $record = $class->new( \%hash );
+ my $param = {};
while ( scalar(@later) ) {
my $sub = shift @later;
my $data = shift @later;
- &{$sub}($record, $data, $conf); # $record->&{$sub}($data, $conf);
+ &{$sub}($record, $data, $conf, $param); # $record->&{$sub}($data, $conf);
+ last if exists( $param->{skiprow} );
}
+ next if exists( $param->{skiprow} );
my $error = $record->insert;
@@ -1728,16 +1828,18 @@ sub _h_statement {
$time ||= time;
+ my %nohistory = map { $_=>1 } $self->nohistory_fields;
+
my @fields =
- grep { defined($self->getfield($_)) && $self->getfield($_) ne "" }
+ grep { defined($self->get($_)) && $self->get($_) ne "" && ! $nohistory{$_} }
real_fields($self->table);
;
- # If we're encrypting then don't ever store the payinfo or CVV2 in the history....
- # You can see if it changed by the paymask...
- if ($conf && $conf->exists('encryption') ) {
- @fields = grep $_ ne 'payinfo' && $_ ne 'cvv2', @fields;
+ # If we're encrypting then don't store the payinfo in the history
+ if ( $conf && $conf->exists('encryption') ) {
+ @fields = grep { $_ ne 'payinfo' } @fields;
}
+
my @values = map { _quote( $self->getfield($_), $self->table, $_) } @fields;
"INSERT INTO h_". $self->table. " ( ".
@@ -1941,10 +2043,26 @@ sub ut_money {
'';
}
+=item ut_moneyn COLUMN
+
+Check/untaint monetary numbers. May be negative. If there
+is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub ut_moneyn {
+ my($self,$field)=@_;
+ if ($self->getfield($field) eq '') {
+ $self->setfield($field, '');
+ return '';
+ }
+ $self->ut_money($field);
+}
+
=item ut_text COLUMN
Check/untaint text. Alphanumerics, spaces, and the following punctuation
-symbols are currently permitted: ! @ # $ % & ( ) - + ; : ' " , . ? / = [ ]
+symbols are currently permitted: ! @ # $ % & ( ) - + ; : ' " , . ? / = [ ] < >
May not be null. If there is an error, returns the error, otherwise returns
false.
@@ -1956,7 +2074,7 @@ sub ut_text {
#warn "notexist ". \&notexist. "\n";
#warn "AUTOLOAD ". \&AUTOLOAD. "\n";
$self->getfield($field)
- =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]+)$/
+ =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]\<\>]+)$/
or return gettext('illegal_or_empty_text'). " $field: ".
$self->getfield($field);
$self->setfield($field,$1);
@@ -2086,12 +2204,14 @@ sub ut_hexn {
}
=item ut_ip COLUMN
-Check/untaint ip addresses. IPv4 only for now.
+Check/untaint ip addresses. IPv4 only for now, though ::1 is auto-translated
+to 127.0.0.1.
=cut
sub ut_ip {
my( $self, $field ) = @_;
+ $self->setfield($field, '127.0.0.1') if $self->getfield($field) eq '::1';
$self->getfield($field) =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
or return "Illegal (IP address) $field: ". $self->getfield($field);
for ( $1, $2, $3, $4 ) { return "Illegal (IP address) $field" if $_ > 255; }
@@ -2101,7 +2221,8 @@ sub ut_ip {
=item ut_ipn COLUMN
-Check/untaint ip addresses. IPv4 only for now. May be null.
+Check/untaint ip addresses. IPv4 only for now, though ::1 is auto-translated
+to 127.0.0.1. May be null.
=cut
@@ -2321,7 +2442,7 @@ sub ut_enum {
my( $self, $field, $choices ) = @_;
foreach my $choice ( @$choices ) {
if ( $self->getfield($field) eq $choice ) {
- $self->setfield($choice);
+ $self->setfield($field, $choice);
return '';
}
}
@@ -2657,7 +2778,7 @@ sub _quote {
")\n" if $DEBUG > 2;
if ( $value eq '' && $nullable ) {
- 'NULL'
+ 'NULL';
} elsif ( $value eq '' && $column_type =~ /^(int|numeric)/ ) {
cluck "WARNING: Attempting to set non-null integer $table.$column null; ".
"using 0 instead";
@@ -2665,6 +2786,15 @@ sub _quote {
} elsif ( $value =~ /^\d+(\.\d+)?$/ &&
! $column_type =~ /(char|binary|text)$/i ) {
$value;
+ } elsif (( $column_type =~ /^bytea$/i || $column_type =~ /(blob|varbinary)/i )
+ && driver_name eq 'Pg'
+ )
+ {
+ no strict 'subs';
+# dbh->quote($value, { pg_type => PG_BYTEA() }); # doesn't work right
+ # Pg binary string quoting: convert each character to 3-digit octal prefixed with \\,
+ # single-quote the whole mess, and put an "E" in front.
+ return ("E'" . join('', map { sprintf('\\\\%03o', ord($_)) } split(//, $value) ) . "'");
} else {
dbh->quote($value);
}
diff --git a/FS/FS/Report/Table/Monthly.pm b/FS/FS/Report/Table/Monthly.pm
index d75f0be..845ab15 100644
--- a/FS/FS/Report/Table/Monthly.pm
+++ b/FS/FS/Report/Table/Monthly.pm
@@ -311,28 +311,99 @@ sub cust_bill_pkg {
my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_;
my $where = '';
+ my $comparison = '';
if ( $opt{'classnum'} =~ /^(\d+)$/ ) {
if ( $1 == 0 ) {
- $where = "classnum IS NULL";
+ $comparison = "IS NULL";
} else {
- $where = "classnum = $1";
+ $comparison = "= $1";
+ }
+
+ if ( $opt{'use_override'} ) {
+ $where = "(
+ part_pkg.classnum $comparison AND pkgpart_override IS NULL OR
+ override.classnum $comparison AND pkgpart_override IS NOT NULL
+ )";
+ } else {
+ $where = "part_pkg.classnum $comparison";
}
}
$agentnum ||= $opt{'agentnum'};
- $self->scalar_sql("
+ my $usage = cust_bill_pkg_detail(@_);
+
+ my $total = $self->scalar_sql("
SELECT SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)
FROM cust_bill_pkg
LEFT JOIN cust_bill USING ( invnum )
LEFT JOIN cust_main USING ( custnum )
LEFT JOIN cust_pkg USING ( pkgnum )
LEFT JOIN part_pkg USING ( pkgpart )
+ LEFT JOIN part_pkg AS override ON pkgpart_override = override.pkgpart
WHERE pkgnum != 0
AND $where
AND ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum)
);
+ if ($opt{use_usage} && $opt{use_usage} eq 'recurring') {
+ return $total-$usage;
+ } elsif ($opt{use_usage} && $opt{use_usage} eq 'usage') {
+ return $usage;
+ } else {
+ return $total;
+ }
+}
+
+sub cust_bill_pkg_detail {
+ my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_;
+
+ my @where = ( "cust_bill_pkg.pkgnum != 0" );
+ my $comparison = '';
+ if ( $opt{'classnum'} =~ /^(\d+)$/ ) {
+ if ( $1 == 0 ) {
+ $comparison = "IS NULL";
+ } else {
+ $comparison = "= $1";
+ }
+
+ if ( $opt{'use_override'} ) {
+ push @where, "(
+ part_pkg.classnum $comparison AND pkgpart_override IS NULL OR
+ override.classnum $comparison AND pkgpart_override IS NOT NULL
+ )";
+ } else {
+ push @where, "part_pkg.classnum $comparison";
+ }
+ }
+
+ if ( $opt{'usageclass'} =~ /^(\d+)$/ ) {
+ if ( $1 == 0 ) {
+ $comparison = "IS NULL";
+ } else {
+ $comparison = "= $1";
+ }
+
+ push @where, "cust_bill_pkg_detail.classnum $comparison";
+ }
+
+ $agentnum ||= $opt{'agentnum'};
+
+ my $where = join( ' AND ', @where );
+
+ $self->scalar_sql("
+ SELECT SUM(amount)
+ FROM cust_bill_pkg_detail
+ LEFT JOIN cust_bill_pkg USING ( billpkgnum )
+ LEFT JOIN cust_bill ON cust_bill_pkg.invnum = cust_bill.invnum
+ LEFT JOIN cust_main USING ( custnum )
+ LEFT JOIN cust_pkg ON cust_bill_pkg.pkgnum = cust_pkg.pkgnum
+ LEFT JOIN part_pkg USING ( pkgpart )
+ LEFT JOIN part_pkg AS override ON pkgpart_override = override.pkgpart
+ WHERE $where
+ AND ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum)
+ );
+
}
sub setup_pkg { shift->pkg_field( @_, 'setup' ); }
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 885eaaa..6f53b2a 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -320,6 +320,8 @@ sub tables_hashref {
my @perl_type = ( 'text', 'NULL', '' );
my @money_type = ( 'decimal', '', '10,2' );
my @money_typen = ( 'decimal', 'NULL', '10,2' );
+ my @taxrate_type = ( 'decimal', '', '14,8' ); # requires pg 8 for
+ my @taxrate_typen = ( 'decimal', 'NULL', '14,8' ); # fs-upgrade to work
my $username_len = 32; #usernamemax config file
@@ -370,18 +372,56 @@ sub tables_hashref {
'index' => [ ['typenum'] ],
},
+ 'cust_attachment' => {
+ 'columns' => [
+ 'attachnum', 'serial', '', '', '', '',
+ 'custnum', 'int', '', '', '', '',
+ '_date', @date_type, '', '',
+ 'otaker', 'varchar', '', 32, '', '',
+ 'filename', 'varchar', '', 32, '', '',
+ 'mime_type', 'varchar', '', 32, '', '',
+ 'body', 'blob', 'NULL', '', '', '',
+ 'disabled', @date_type, '', '',
+ ],
+ 'primary_key' => 'attachnum',
+ 'unique' => [],
+ 'index' => [ ['custnum'] ],
+ },
+
'cust_bill' => {
'columns' => [
- 'invnum', 'serial', '', '', '', '',
- 'custnum', 'int', '', '', '', '',
- '_date', @date_type, '', '',
- 'charged', @money_type, '', '',
- 'printed', 'int', '', '', '', '',
- 'closed', 'char', 'NULL', 1, '', '',
+ #regular fields
+ 'invnum', 'serial', '', '', '', '',
+ 'custnum', 'int', '', '', '', '',
+ '_date', @date_type, '', '',
+ 'charged', @money_type, '', '',
+ 'invoice_terms', 'varchar', 'NULL', $char_d, '', '',
+
+ #customer balance info at invoice generation time
+ 'previous_balance', @money_typen, '', '', #eventually not nullable
+ 'billing_balance', @money_typen, '', '', #eventually not nullable
+
+ #deprecated (unused by now, right?)
+ 'printed', 'int', '', '', '', '',
+
+ #specific use cases
+ 'closed', 'char', 'NULL', 1, '', '',
+ 'statementnum', 'int', 'NULL', '', '', '', #invoice aggregate statements
],
'primary_key' => 'invnum',
'unique' => [],
- 'index' => [ ['custnum'], ['_date'] ],
+ 'index' => [ ['custnum'], ['_date'], ['statementnum'], ],
+ },
+
+ 'cust_statement' => {
+ 'columns' => [
+ 'statementnum', 'serial', '', '', '', '',
+ 'custnum', 'int', '', '', '', '',
+ '_date', @date_type, '', '',
+ ],
+ 'primary_key' => 'statementnum',
+ 'unique' => [],
+ 'index' => [ ['custnum'], ['_date'], ],
},
'cust_bill_event' => {
@@ -396,7 +436,9 @@ sub tables_hashref {
'primary_key' => 'eventnum',
#no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
'unique' => [],
- 'index' => [ ['invnum'], ['status'], ['eventpart'] ],
+ 'index' => [ ['invnum'], ['status'], ['eventpart'],
+ ['statustext'], ['_date'],
+ ],
},
'part_bill_event' => {
@@ -493,7 +535,9 @@ sub tables_hashref {
'primary_key' => 'eventnum',
#no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
'unique' => [],
- 'index' => [ ['eventpart'], ['tablenum'], ['status'] ],
+ 'index' => [ ['eventpart'], ['tablenum'], ['status'],
+ ['statustext'], ['_date'],
+ ],
},
'cust_bill_pkg' => {
@@ -507,14 +551,16 @@ sub tables_hashref {
'sdate', @date_type, '', '',
'edate', @date_type, '', '',
'itemdesc', 'varchar', 'NULL', $char_d, '', '',
+ 'itemcomment', 'varchar', 'NULL', $char_d, '', '',
'section', 'varchar', 'NULL', $char_d, '', '',
'quantity', 'int', 'NULL', '', '', '',
'unitsetup', @money_typen, '', '',
'unitrecur', @money_typen, '', '',
+ 'hidden', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'billpkgnum',
'unique' => [],
- 'index' => [ ['invnum'], [ 'pkgnum' ] ],
+ 'index' => [ ['invnum'], [ 'pkgnum' ], [ 'itemdesc' ], ],
},
'cust_bill_pkg_detail' => {
@@ -523,9 +569,10 @@ sub tables_hashref {
'billpkgnum', 'int', 'NULL', '', '', '', # should not be nullable
'pkgnum', 'int', 'NULL', '', '', '', # deprecated
'invnum', 'int', 'NULL', '', '', '', # deprecated
- 'amount', @money_typen, '', '',
+ 'amount', 'decimal', 'NULL', '10,4', '', '',
'format', 'char', 'NULL', 1, '', '',
- 'classnum', 'char', 'NULL', 1, '', '',
+ 'classnum', 'int', 'NULL', '', '', '',
+ 'phonenum', 'varchar', 'NULL', 15, '', '',
'detail', 'varchar', '', 255, '', '',
],
'primary_key' => 'detailnum',
@@ -554,7 +601,7 @@ sub tables_hashref {
'billpkgtaxlocationnum', 'serial', '', '', '', '',
'billpkgnum', 'int', '', '', '', '',
'taxnum', 'int', '', '', '', '',
- 'taxtype', 'varchar', $char_d, '', '', '',
+ 'taxtype', 'varchar', '', $char_d, '', '',
'pkgnum', 'int', '', '', '', '',
'locationnum', 'int', '', '', '', '', #redundant?
'amount', @money_type, '', '',
@@ -564,6 +611,21 @@ sub tables_hashref {
'index' => [ [ 'billpkgnum' ], [ 'taxnum' ], [ 'pkgnum' ], [ 'locationnum' ] ],
},
+ 'cust_bill_pkg_tax_rate_location' => {
+ 'columns' => [
+ 'billpkgtaxratelocationnum', 'serial', '', '', '', '',
+ 'billpkgnum', 'int', '', '', '', '',
+ 'taxnum', 'int', '', '', '', '',
+ 'taxtype', 'varchar', '', $char_d, '', '',
+ 'locationtaxid', 'varchar', 'NULL', $char_d, '', '',
+ 'taxratelocationnum', 'int', '', '', '', '',
+ 'amount', @money_type, '', '',
+ ],
+ 'primary_key' => 'billpkgtaxratelocationnum',
+ 'unique' => [],
+ 'index' => [ [ 'billpkgnum' ], [ 'taxnum' ], [ 'taxratelocationnum' ] ],
+ },
+
'cust_credit' => {
'columns' => [
'crednum', 'serial', '', '', '', '',
@@ -575,6 +637,7 @@ sub tables_hashref {
'reasonnum', 'int', 'NULL', '', '', '',
'addlinfo', 'text', 'NULL', '', '', '',
'closed', 'char', 'NULL', 1, '', '',
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
],
'primary_key' => 'crednum',
'unique' => [],
@@ -588,6 +651,7 @@ sub tables_hashref {
'invnum', 'int', '', '', '', '',
'_date', @date_type, '', '',
'amount', @money_type, '', '',
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
],
'primary_key' => 'creditbillnum',
'unique' => [],
@@ -664,6 +728,7 @@ sub tables_hashref {
'paytype', 'varchar', 'NULL', $char_d, '', '',
'payip', 'varchar', 'NULL', 15, '', '',
'geocode', 'varchar', 'NULL', 20, '', '',
+ 'censustract', 'varchar', 'NULL', 20, '', '', # 7 to save space?
'tax', 'char', 'NULL', 1, '', '',
'otaker', 'varchar', '', 32, '', '',
'refnum', 'int', '', '', '', '',
@@ -671,7 +736,10 @@ sub tables_hashref {
'comments', 'text', 'NULL', '', '', '',
'spool_cdr','char', 'NULL', 1, '', '',
'squelch_cdr','char', 'NULL', 1, '', '',
+ 'cdr_termination_percentage', 'decimal', 'NULL', '', '', '',
'invoice_terms', 'varchar', 'NULL', $char_d, '', '',
+ 'archived', 'char', 'NULL', 1, '', '',
+ 'email_csv_cdr', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'custnum',
'unique' => [ [ 'agentnum', 'agent_custid' ] ],
@@ -680,6 +748,7 @@ sub tables_hashref {
[ 'agentnum' ], [ 'refnum' ], [ 'custbatch' ],
[ 'referral_custnum' ],
[ 'payby' ], [ 'paydate' ],
+ [ 'archived' ],
#billing
[ 'last' ], [ 'company' ],
[ 'county' ], [ 'state' ], [ 'country' ],
@@ -693,6 +762,32 @@ sub tables_hashref {
],
},
+ 'cust_recon' => { # what purpose does this serve?
+ 'columns' => [
+ 'reconid', 'serial', '', '', '', '',
+ 'recondate', @date_type, '', '',
+ 'custnum', 'int' , '', '', '', '',
+ 'agentnum', 'int', '', '', '', '',
+ 'last', 'varchar', '', $char_d, '', '',
+ 'first', 'varchar', '', $char_d, '', '',
+ 'address1', 'varchar', '', $char_d, '', '',
+ 'address2', 'varchar', 'NULL', $char_d, '', '',
+ 'city', 'varchar', '', $char_d, '', '',
+ 'state', 'varchar', 'NULL', $char_d, '', '',
+ 'zip', 'varchar', 'NULL', 10, '', '',
+ 'pkg', 'varchar', 'NULL', $char_d, '', '',
+ 'adjourn', @date_type, '', '',
+ 'status', 'varchar', 'NULL', 10, '', '',
+ 'agent_custid', 'varchar', '', $char_d, '', '',
+ 'agent_pkg', 'varchar', 'NULL', $char_d, '', '',
+ 'agent_adjourn', @date_type, '', '',
+ 'comments', 'text', 'NULL', '', '', '',
+ ],
+ 'primary_key' => 'reconid',
+ 'unique' => [],
+ 'index' => [],
+ },
+
#eventually use for billing & ship from cust_main too
#for now, just cust_pkg locations
'cust_location' => {
@@ -739,6 +834,33 @@ sub tables_hashref {
'index' => [ [ 'custnum' ], [ '_date' ], ],
},
+ 'cust_main_exemption' => {
+ 'columns' => [
+ 'exemptionnum', 'serial', '', '', '', '',
+ 'custnum', 'int', '', '', '', '',
+ 'taxname', 'varchar', '', $char_d, '', '',
+ #start/end dates? for reporting?
+ ],
+ 'primary_key' => 'exemptionnum',
+ 'unique' => [],
+ 'index' => [ [ 'custnum' ] ],
+ },
+
+ 'cust_tax_adjustment' => {
+ 'columns' => [
+ 'adjustmentnum', 'serial', '', '', '', '',
+ 'custnum', 'int', '', '', '', '',
+ 'taxname', 'varchar', '', $char_d, '', '',
+ 'amount', @money_type, '', '',
+ 'comment', 'varchar', 'NULL', $char_d, '', '',
+ 'billpkgnum', 'int', 'NULL', '', '', '',
+ #more? no cust_bill_pkg_tax_location?
+ ],
+ 'primary_key' => 'adjustmentnum',
+ 'unique' => [],
+ 'index' => [ [ 'custnum' ], [ 'billpkgnum' ] ],
+ },
+
'cust_main_county' => { #county+state+country are checked off the
#cust_main_county for validation and to provide
# a tax rate.
@@ -770,17 +892,17 @@ sub tables_hashref {
'location', 'varchar', 'NULL', $char_d, '', '',#provided by tax authority
'taxclassnum', 'int', '', '', '', '',
'effective_date', @date_type, '', '',
- 'tax', 'real', '', '', '', '', # tax %
- 'excessrate', 'real', 'NULL','', '', '', # second tax %
+ 'tax', @taxrate_type, '', '', # tax %
+ 'excessrate', @taxrate_typen, '', '', # second tax %
'taxbase', @money_typen, '', '', # amount at first tax rate
'taxmax', @money_typen, '', '', # maximum about at both rates
- 'usetax', 'real', 'NULL', '', '', '', # tax % when non-local
- 'useexcessrate', 'real', 'NULL', '', '', '', # second tax % when non-local
+ 'usetax', @taxrate_typen, '', '', # tax % when non-local
+ 'useexcessrate', @taxrate_typen, '', '', # second tax % when non-local
'unittype', 'int', 'NULL', '', '', '', # for fee
- 'fee', 'real', 'NULL', '', '', '', # amount tax per unit
- 'excessfee', 'real', 'NULL', '', '', '', # second amount tax per unit
- 'feebase', 'real', 'NULL', '', '', '', # units taxed at first rate
- 'feemax', 'real', 'NULL', '', '', '', # maximum number of unit taxed
+ 'fee', @taxrate_typen, '', '', # amount tax per unit
+ 'excessfee', @taxrate_typen, '', '', # second amount tax per unit
+ 'feebase', @taxrate_typen, '', '', # units taxed at first rate
+ 'feemax', @taxrate_typen, '', '', # maximum number of unit taxed
'maxtype', 'int', 'NULL', '', '', '', # indicator of how thresholds accumulate
'taxname', 'varchar', 'NULL', $char_d, '', '', # may appear on invoice
'taxauth', 'int', 'NULL', '', '', '', # tax authority
@@ -797,6 +919,21 @@ sub tables_hashref {
'index' => [ ['taxclassnum'], ['data_vendor', 'geocode'] ],
},
+ 'tax_rate_location' => {
+ 'columns' => [
+ 'taxratelocationnum', 'serial', '', '', '', '',
+ 'data_vendor', 'varchar', 'NULL', $char_d, '', '',
+ 'geocode', 'varchar', '', 20, '', '',
+ 'city', 'varchar', 'NULL', $char_d, '', '',
+ 'county', 'varchar', 'NULL', $char_d, '', '',
+ 'state', 'char', 'NULL', 2, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
+ ],
+ 'primary_key' => 'taxratelocationnum',
+ 'unique' => [],
+ 'index' => [ [ 'data_vendor', 'geocode', 'disabled' ] ],
+ },
+
'cust_tax_location' => {
'columns' => [
'custlocationnum', 'serial', '', '', '', '',
@@ -841,14 +978,18 @@ sub tables_hashref {
'payinfo', 'varchar', 'NULL', 512, '', '', #see cust_main above
'paymask', 'varchar', 'NULL', $char_d, '', '',
'paydate', 'varchar', 'NULL', 10, '', '',
+ 'recurring_billing', 'varchar', 'NULL', $char_d, '', '',
#'paybatch', 'varchar', 'NULL', $char_d, '', '', #for auditing purposes.
'payunique', 'varchar', 'NULL', $char_d, '', '', #separate paybatch "unique" functions from current usage
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
'status', 'varchar', '', $char_d, '', '',
+ 'session_id', 'varchar', 'NULL', $char_d, '', '', #only need 32
'statustext', 'text', 'NULL', '', '', '',
'gatewaynum', 'int', 'NULL', '', '', '',
#'cust_balance', @money_type, '', '',
'paynum', 'int', 'NULL', '', '', '',
+ 'jobnum', 'int', 'NULL', '', '', '',
],
'primary_key' => 'paypendingnum',
'unique' => [ [ 'payunique' ] ],
@@ -871,6 +1012,7 @@ sub tables_hashref {
'paybatch', 'varchar', 'NULL', $char_d, '', '', #for auditing purposes.
'payunique', 'varchar', 'NULL', $char_d, '', '', #separate paybatch "unique" functions from current usage
'closed', 'char', 'NULL', 1, '', '',
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
],
'primary_key' => 'paynum',
#i guess not now, with cust_pay_pending, if we actually make it here, we _do_ want to record it# 'unique' => [ [ 'payunique' ] ],
@@ -890,6 +1032,7 @@ sub tables_hashref {
'paymask', 'varchar', 'NULL', $char_d, '', '',
'paybatch', 'varchar', 'NULL', $char_d, '', '', #for auditing purposes.
'closed', 'char', 'NULL', 1, '', '',
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
'void_date', @date_type, '', '',
'reason', 'varchar', 'NULL', $char_d, '', '',
'otaker', 'varchar', '', 32, '', '',
@@ -906,6 +1049,7 @@ sub tables_hashref {
'paynum', 'int', '', '', '', '',
'amount', @money_type, '', '',
'_date', @date_type, '', '',
+ 'pkgnum', 'int', 'NULL', '', '', '', #desired pkgnum for pkg-balances
],
'primary_key' => 'billpaynum',
'unique' => [],
@@ -989,6 +1133,7 @@ sub tables_hashref {
'pkgpart', 'int', '', '', '', '',
'locationnum', 'int', 'NULL', '', '', '',
'otaker', 'varchar', '', 32, '', '',
+ 'start_date', @date_type, '', '',
'setup', @date_type, '', '',
'bill', @date_type, '', '',
'last_bill', @date_type, '', '',
@@ -1006,8 +1151,8 @@ sub tables_hashref {
'primary_key' => 'pkgnum',
'unique' => [],
'index' => [ ['custnum'], ['pkgpart'], [ 'locationnum' ],
- ['setup'], ['last_bill'], ['bill'], ['susp'], ['adjourn'],
- ['expire'], ['cancel'],
+ [ 'start_date' ], ['setup'], ['last_bill'], ['bill'],
+ ['susp'], ['adjourn'], ['expire'], ['cancel'],
['change_date'],
],
},
@@ -1124,9 +1269,12 @@ sub tables_hashref {
'plan', 'varchar', 'NULL', $char_d, '', '',
'plandata', 'text', 'NULL', '', '', '',
'disabled', 'char', 'NULL', 1, '', '',
+ 'custom', 'char', 'NULL', 1, '', '',
'taxclass', 'varchar', 'NULL', $char_d, '', '',
'classnum', 'int', 'NULL', '', '', '',
'taxproductnum', 'int', 'NULL', '', '', '',
+ 'setup_cost', @money_typen, '', '',
+ 'recur_cost', @money_typen, '', '',
'pay_weight', 'real', 'NULL', '', '', '',
'credit_weight', 'real', 'NULL', '', '', '',
'agentnum', 'int', 'NULL', '', '', '',
@@ -1139,24 +1287,28 @@ sub tables_hashref {
'part_pkg_link' => {
'columns' => [
- 'pkglinknum', 'serial', '', '', '', '',
- 'src_pkgpart', 'int', '', '', '', '',
- 'dst_pkgpart', 'int', '', '', '', '',
- 'link_type', 'varchar', '', $char_d, '', '',
+ 'pkglinknum', 'serial', '', '', '', '',
+ 'src_pkgpart', 'int', '', '', '', '',
+ 'dst_pkgpart', 'int', '', '', '', '',
+ 'link_type', 'varchar', '', $char_d, '', '',
+ 'hidden', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'pkglinknum',
- 'unique' => [ [ 'src_pkgpart', 'dst_pkgpart', 'link_type' ] ],
+ 'unique' => [ [ 'src_pkgpart', 'dst_pkgpart', 'link_type', 'hidden' ] ],
'index' => [ [ 'src_pkgpart' ] ],
},
+ # XXX somewhat borked unique: we don't really want a hidden and unhidden
+ # it turns out we'd prefer to use svc, bill, and invisibill (or something)
'part_pkg_taxclass' => {
'columns' => [
'taxclassnum', 'serial', '', '', '', '',
'taxclass', 'varchar', '', $char_d, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'taxclassnum',
'unique' => [ [ 'taxclass' ] ],
- 'index' => [],
+ 'index' => [ [ 'disabled' ] ],
},
'part_pkg_taxproduct' => {
@@ -1225,7 +1377,7 @@ sub tables_hashref {
],
'primary_key' => 'pkgsvcnum',
'unique' => [ ['pkgpart', 'svcpart'] ],
- 'index' => [ ['pkgpart'] ],
+ 'index' => [ ['pkgpart'], ['quantity'] ],
},
'part_referral' => {
@@ -1257,6 +1409,7 @@ sub tables_hashref {
'columnnum', 'serial', '', '', '', '',
'svcpart', 'int', '', '', '', '',
'columnname', 'varchar', '', 64, '', '',
+ 'columnlabel', 'varchar', 'NULL', $char_d, '', '',
'columnvalue', 'varchar', 'NULL', $char_d, '', '',
'columnflag', 'char', 'NULL', 1, '', '',
],
@@ -1298,7 +1451,7 @@ sub tables_hashref {
'columns' => [
'svcnum', 'int', '', '', '', '',
'username', 'varchar', '', $username_len, '', '',
- '_password', 'varchar', '', 512, '', '',
+ '_password', 'varchar', 'NULL', 512, '', '',
'_password_encoding', 'varchar', 'NULL', $char_d, '', '',
'sec_phrase', 'varchar', 'NULL', $char_d, '', '',
'popnum', 'int', 'NULL', '', '', '',
@@ -1495,16 +1648,20 @@ sub tables_hashref {
'svcnum', 'int', 'NULL', '', '', '',
'custnum', 'int', 'NULL', '', '', '',
'secure', 'char', 'NULL', 1, '', '',
+ 'priority', 'int', 'NULL', '', '', '',
],
'primary_key' => 'jobnum',
'unique' => [],
- 'index' => [ [ 'job' ], [ 'svcnum' ], [ 'custnum' ], [ 'status' ] ],
+ 'index' => [ [ 'secure' ], [ 'priority' ],
+ [ 'job' ], [ 'svcnum' ], [ 'custnum' ], [ 'status' ],
+ ],
},
'queue_arg' => {
'columns' => [
'argnum', 'serial', '', '', '', '',
'jobnum', 'int', '', '', '', '',
+ 'frozen', 'char', 'NULL', 1, '', '',
'arg', 'text', 'NULL', '', '', '',
],
'primary_key' => 'argnum',
@@ -1654,16 +1811,17 @@ sub tables_hashref {
'columns' => [
'svcnum', 'int', '', '', '', '',
'description', 'varchar', 'NULL', $char_d, '', '',
- 'blocknum', 'int', '', '', '', '',
+ 'blocknum', 'int', 'NULL', '', '', '',
'speed_up', 'int', '', '', '', '',
'speed_down', 'int', '', '', '', '',
- 'ip_addr', 'varchar', '', 15, '', '',
+ 'ip_addr', 'varchar', 'NULL', 15, '', '',
'mac_addr', 'varchar', 'NULL', 12, '', '',
'authkey', 'varchar', 'NULL', 32, '', '',
'latitude', 'decimal', 'NULL', '', '', '',
'longitude', 'decimal', 'NULL', '', '', '',
'altitude', 'decimal', 'NULL', '', '', '',
'vlan_profile', 'varchar', 'NULL', $char_d, '', '',
+ 'performance_profile', 'varchar', 'NULL', $char_d, '', '',
],
'primary_key' => 'svcnum',
'unique' => [ [ 'mac_addr' ] ],
@@ -1747,6 +1905,17 @@ sub tables_hashref {
'index' => [ [ 'pkgpart' ], [ 'optionname' ] ],
},
+ 'part_pkg_report_option' => {
+ 'columns' => [
+ 'num', 'serial', '', '', '', '',
+ 'name', 'varchar', '', $char_d, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
+ ],
+ 'primary_key' => 'num',
+ 'unique' => [ [ 'name' ] ],
+ 'index' => [ [ 'disabled' ] ],
+ },
+
'rate' => {
'columns' => [
'ratenum', 'serial', '', '', '', '',
@@ -1857,10 +2026,12 @@ sub tables_hashref {
'payment_gateway' => {
'columns' => [
'gatewaynum', 'serial', '', '', '', '',
+ 'gateway_namespace','varchar', 'NULL', $char_d, '', '',
'gateway_module', 'varchar', '', $char_d, '', '',
'gateway_username', 'varchar', 'NULL', $char_d, '', '',
'gateway_password', 'varchar', 'NULL', $char_d, '', '',
'gateway_action', 'varchar', 'NULL', $char_d, '', '',
+ 'gateway_callback_url', 'varchar', 'NULL', $char_d, '', '',
'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'gatewaynum',
@@ -1912,6 +2083,7 @@ sub tables_hashref {
'columns' => [
'categorynum', 'serial', '', '', '', '',
'categoryname', 'varchar', '', $char_d, '', '',
+ 'weight', 'int', 'NULL', '', '', '',
'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'categorynum',
@@ -1988,7 +2160,7 @@ sub tables_hashref {
# how it was rated internally...
'ratedetailnum', 'int', 'NULL', '', '', '',
- 'rated_price', 'decimal', 'NULL', '10,2', '', '',
+ 'rated_price', 'decimal', 'NULL', '10,4', '', '',
'distance', 'decimal', 'NULL', '', '', '',
'islocal', 'int', 'NULL', '', '', '', # '', '', 0, '' instead?
@@ -2017,14 +2189,45 @@ sub tables_hashref {
#NULL, done (or something)
'freesiderewritestatus', 'varchar', 'NULL', 32, '', '',
- 'cdrbatch', 'varchar', 'NULL', $char_d, '', '',
+ 'cdrbatch', 'varchar', 'NULL', 255, '', '',
],
'primary_key' => 'acctid',
'unique' => [],
- 'index' => [ [ 'calldate' ], [ 'src' ], [ 'dst' ], [ 'charged_party' ], [ 'accountcode' ], [ 'freesidestatus' ], [ 'freesiderewritestatus' ], [ 'cdrbatch' ], ],
+ 'index' => [ [ 'calldate' ],
+ [ 'src' ], [ 'dst' ], [ 'dcontext' ], [ 'charged_party' ],
+ [ 'accountcode' ], [ 'carrierid' ],
+ [ 'freesidestatus' ], [ 'freesiderewritestatus' ],
+ [ 'cdrbatch' ],
+ ],
+ },
+
+ 'cdr_termination' => {
+ 'columns' => [
+ 'cdrtermnum', 'bigserial', '', '', '', '',
+ 'acctid', 'bigint', '', '', '', '',
+ 'termpart', 'int', '', '', '', '',#future use see below
+ 'rated_price', 'decimal', 'NULL', '10,4', '', '',
+ 'status', 'varchar', 'NULL', 32, '', '',
+ ],
+ 'primary_key' => 'cdrtermnum',
+ 'unique' => [ [ 'acctid', 'termpart' ] ],
+ 'index' => [ [ 'acctid' ], [ 'status' ], ],
},
+ #to handle multiple termination/settlement passes...
+ # 'part_termination' => {
+ # 'columns' => [
+ # 'termpart', 'int', '', '', '', '',
+ # 'termname', 'varchar', '', $char_d, '', '',
+ # 'cdr_column', 'varchar', '', $char_d, '', '', #maybe set it here instead of in the price plan?
+ # ],
+ # 'primary_key' => 'termpart',
+ # 'unique' => [],
+ # 'index' => [],
+ # },
+
+ #the remaining cdr_ tables are not really used
'cdr_calltype' => {
'columns' => [
'calltypenum', 'serial', '', '', '', '',
@@ -2055,18 +2258,6 @@ sub tables_hashref {
'index' => [],
},
- #map upstream rateid to ours...
- 'cdr_upstream_rate' => {
- 'columns' => [
- 'upstreamratenum', 'serial', '', '', '', '',
- 'upstream_rateid', 'varchar', '', $char_d, '', '',
- 'ratedetailnum', 'int', 'NULL', '', '', '',
- ],
- 'primary_key' => 'upstreamratenum', #XXX need a primary key
- 'unique' => [ [ 'upstream_rateid' ] ], #unless we add another field, yeah
- 'index' => [],
- },
-
#'cdr_file' => {
# 'columns' => [
# 'filenum', 'serial', '', '', '', '',
@@ -2189,6 +2380,29 @@ sub tables_hashref {
'index' => [ [ 'countrycode', 'phonenum' ] ],
},
+ 'phone_device' => {
+ 'columns' => [
+ 'devicenum', 'serial', '', '', '', '',
+ 'devicepart', 'int', '', '', '', '',
+ 'svcnum', 'int', '', '', '', '',
+ 'mac_addr', 'varchar', 'NULL', 12, '', '',
+ ],
+ 'primary_key' => 'devicenum',
+ 'unique' => [ [ 'mac_addr' ], ],
+ 'index' => [ [ 'devicepart' ], [ 'svcnum' ], ],
+ },
+
+ 'part_device' => {
+ 'columns' => [
+ 'devicepart', 'serial', '', '', '', '',
+ 'devicename', 'varchar', '', $char_d, '', '',
+ #'classnum', #tie to an inventory class?
+ ],
+ 'primary_key' => 'devicepart',
+ 'unique' => [ [ 'devicename' ] ], #?
+ 'index' => [],
+ },
+
'phone_avail' => {
'columns' => [
'availnum', 'serial', '', '', '', '',
diff --git a/FS/FS/Setup.pm b/FS/FS/Setup.pm
index cba3c7e..edfe912 100644
--- a/FS/FS/Setup.pm
+++ b/FS/FS/Setup.pm
@@ -364,7 +364,7 @@ sub populate_access {
use FS::AccessRight;
use FS::access_right;
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => 1, #$supergroup->groupnum,
diff --git a/FS/FS/TicketSystem/RT_External.pm b/FS/FS/TicketSystem/RT_External.pm
index 3a9c7e8..8ccc937 100644
--- a/FS/FS/TicketSystem/RT_External.pm
+++ b/FS/FS/TicketSystem/RT_External.pm
@@ -156,14 +156,16 @@ sub _from_customer {
}
my $sql = "
- FROM Tickets
- JOIN Queues ON ( Tickets.Queue = Queues.id )
- JOIN Links ON ( Tickets.id = Links.LocalBase )
- JOIN Users ON ( Tickets.Owner = Users.id )
- $join
- WHERE ( ". join(' OR ', map "Status = '$_'", $self->statuses ). " )
- AND Target = 'freeside://freeside/cust_main/$custnum'
- $where
+ FROM Tickets
+ JOIN Queues ON ( Tickets.Queue = Queues.id )
+ JOIN Users ON ( Tickets.Owner = Users.id )
+ JOIN Links ON ( Tickets.id = Links.LocalBase
+ AND Links.Base LIKE '%/ticket/' || Tickets.id )
+ $join
+
+ WHERE ( ". join(' OR ', map "Status = '$_'", $self->statuses ). " )
+ AND Target = 'freeside://freeside/cust_main/$custnum'
+ $where
";
( $sql, @param );
@@ -349,5 +351,10 @@ sub transaction_status {
$self->_retrieve_single_value($sql);
}
+sub access_right {
+ warn "WARNING: no access rights available w/ external RT";
+ 0;
+}
+
1;
diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm
index d24a96c..033c746 100644
--- a/FS/FS/TicketSystem/RT_Internal.pm
+++ b/FS/FS/TicketSystem/RT_Internal.pm
@@ -1,13 +1,16 @@
package FS::TicketSystem::RT_Internal;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $DEBUG );
use FS::UID qw(dbh);
use FS::CGI qw(popurl);
use FS::TicketSystem::RT_Libs;
+use RT::CurrentUser;
@ISA = qw( FS::TicketSystem::RT_Libs );
+$DEBUG = 0;
+
sub sql_num_customer_tickets {
"( select count(*) from tickets
join links on ( tickets.id = links.localbase )
@@ -25,5 +28,111 @@ sub baseurl {
}
}
+#mapping/genericize??
+#ShowConfigTab ModifySelf
+sub access_right {
+ my( $self, $session, $right ) = @_;
+
+ #return '' unless $conf->config('ticket_system');
+ return '' unless FS::Conf->new->config('ticket_system');
+
+ $self->_web_external_auth($session)
+ unless $session
+ && $session->{'CurrentUser'};
+
+ $session->{'CurrentUser'}->HasRight( Right => $right,
+ Object => $RT::System );
+}
+
+#shameless false laziness w/rt/html/autohandler to get logged into RT from afar
+sub _web_external_auth {
+ my( $self, $session ) = @_;
+
+ my $user = $FS::CurrentUser::CurrentUser->username;
+
+ $session->{'CurrentUser'} = RT::CurrentUser->new();
+
+ warn "loading RT user for $user\n"
+ if $DEBUG;
+
+ $session->{'CurrentUser'}->Load($user);
+
+ if ( ! $session->{'CurrentUser'}->Id() ) {
+
+ # Create users on-the-fly
+
+ warn "can't load RT user for $user; auto-creating\n"
+ if $DEBUG;
+
+ my $UserObj = RT::User->new( RT::CurrentUser->new('RT_System') );
+
+ my ( $val, $msg ) = $UserObj->Create(
+ %{ ref($RT::AutoCreate) ? $RT::AutoCreate : {} },
+ Name => $user,
+ Gecos => $user,
+ );
+
+ if ($val) {
+
+ # now get user specific information, to better create our user.
+ my $new_user_info
+ = RT::Interface::Web::WebExternalAutoInfo($user);
+
+ # set the attributes that have been defined.
+ # FIXME: this is a horrible kludge. I'm sure there's something cleaner
+ foreach my $attribute (
+ 'Name', 'Comments',
+ 'Signature', 'EmailAddress',
+ 'PagerEmailAddress', 'FreeformContactInfo',
+ 'Organization', 'Disabled',
+ 'Privileged', 'RealName',
+ 'NickName', 'Lang',
+ 'EmailEncoding', 'WebEncoding',
+ 'ExternalContactInfoId', 'ContactInfoSystem',
+ 'ExternalAuthId', 'Gecos',
+ 'HomePhone', 'WorkPhone',
+ 'MobilePhone', 'PagerPhone',
+ 'Address1', 'Address2',
+ 'City', 'State',
+ 'Zip', 'Country'
+ )
+ {
+ #uhh, wrong root
+ #$m->comp( '/Elements/Callback', %ARGS,
+ # _CallbackName => 'NewUser' );
+
+ my $method = "Set$attribute";
+ $UserObj->$method( $new_user_info->{$attribute} )
+ if ( defined $new_user_info->{$attribute} );
+ }
+ $session->{'CurrentUser'}->Load($user);
+ }
+ else {
+
+ # we failed to successfully create the user. abort abort abort.
+ delete $session->{'CurrentUser'};
+
+ die "can't auto-create RT user"; #an error message would be nice :/
+ #$m->abort() unless $RT::WebFallbackToInternalAuth;
+ #$m->comp( '/Elements/Login', %ARGS,
+ # Error => loc( 'Cannot create user: [_1]', $msg ) );
+ }
+ }
+
+ unless ( $session->{'CurrentUser'}->Id() ) {
+ delete $session->{'CurrentUser'};
+
+ die "can't auto-create RT user";
+ #$user = $orig_user;
+ #
+ #if ($RT::WebExternalOnly) {
+ # $m->comp( '/Elements/Login', %ARGS,
+ # Error => loc('You are not an authorized user') );
+ # $m->abort();
+ #}
+ }
+
+}
+
1;
diff --git a/FS/FS/Tron.pm b/FS/FS/Tron.pm
index 26ab639..78af0fe 100644
--- a/FS/FS/Tron.pm
+++ b/FS/FS/Tron.pm
@@ -9,34 +9,56 @@ use FS::Record qw( qsearchs );
use FS::svc_external;
use FS::cust_svc_option;
-our @EXPORT_OK = qw( tron_scan tron_lint);
+our @EXPORT_OK = qw( tron_ping tron_scan tron_lint);
our %desired = (
- #lenient for now, so we can fix up important stuff
+ #less lenient, we need to make sure we upgrade deb 4 & pg 7.4
'freeside_version' => qr/^1\.(7\.3|9\.0)/,
- 'debian_version' => qr/^4/,
+ 'debian_version' => qr/^5/, #qr/^5.0.[2-9]$/ #qr/^4/,
'apache_mpm' => qw/^(Prefork|$)/,
+ 'pg_version' => qr/^8\.[1-9]/,
+ 'apache_version' => qr/^2/,
#payment gateway survey
# 'payment_gateway' => qw/^authorizenet$/,
#stuff to add/replace later
- #'pg_version' => qr/^8\.[1-9]/,
- #'apache_version' => qr/^2/,
#'apache_mpm' => qw/^Prefork/,
+ #'pg_version' => qr/^8\.[3-9]/,
);
-sub tron_scan {
- my $cust_svc = shift;
+sub _cust_svc_external {
+ my $cust_svc_or_svcnum = shift;
- my $svc_external;
- if ( ref($cust_svc) ) {
+ my ( $cust_svc, $svc_external );
+ if ( ref($cust_svc_or_svcnum) ) {
+ $cust_svc = $cust_svc_or_svcnum;
$svc_external = $cust_svc->svc_x;
} else {
- $svc_external = qsearchs('svc_external', { 'svcnum' => $cust_svc } );
+ $svc_external = qsearchs('svc_external', { svcnum=>$cust_svc_or_svcnum } );
$cust_svc = $svc_external->cust_svc;
}
+ ( $cust_svc, $svc_external );
+
+}
+
+sub tron_ping {
+ my( $cust_svc, $svc_external ) = _cust_svc_external(shift);
+
+ my %hash = ();
+ my $machine = $svc_external->title; # or better as a cust_svc_option??
+ sshopen2($machine, *READER, *WRITER, '/bin/echo pong');
+ my $pong = scalar(<READER>);
+ close READER;
+ close WRITER;
+
+ $pong =~ /pong/;
+}
+
+sub tron_scan {
+ my( $cust_svc, $svc_external ) = _cust_svc_external(shift);
+
#don't scan again if things are okay
my $bad = 0;
foreach my $option ( keys %desired ) {
@@ -48,7 +70,9 @@ sub tron_scan {
#do the scan
my %hash = ();
my $machine = $svc_external->title; # or better as a cust_svc_option??
- sshopen2($machine, *READER, *WRITER, '/usr/local/bin/freeside-yori all');
+ #sshopen2($machine, *READER, *WRITER, '/usr/local/bin/freeside-yori all');
+ #fix freeside users' patch if necessary, since packages put this in /usr/bin
+ sshopen2($machine, *READER, *WRITER, 'freeside-yori all');
while (<READER>) {
chomp;
my($option, $value) = split(/: ?/);
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index 3c52ca5..148085c 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -338,6 +338,8 @@ sub cust_sql_fields {
grep { my $field = $_; grep { $_ eq $field } @cust_fields }
( @add_fields, ( map "ship_$_", @add_fields ), 'payby' );
+ push @fields, 'agent_custid';
+
my @extra_fields = ();
if (grep { $_ eq 'current_balance' } @cust_fields) {
push @extra_fields, FS::cust_main->balance_sql . " AS current_balance";
@@ -585,7 +587,9 @@ sub job_status {
my @return;
if ( $job && $job->status ne 'failed' ) {
- @return = ( 'progress', $job->statustext );
+ my ($progress, $action) = split ',', $job->statustext, 2;
+ $action ||= 'Server processing job';
+ @return = ( 'progress', $progress, $action );
} elsif ( !$job ) { #handle job gone case : job successful
# so close popup, redirect parent window...
@return = ( 'complete' );
@@ -593,6 +597,7 @@ sub job_status {
@return = ( 'error', $job ? $job->statustext : $jobnum );
}
+ #to_json(\@return); #waiting on deb 5.0 for new JSON.pm?
objToJson(\@return);
}
diff --git a/FS/FS/UI/bytecount.pm b/FS/FS/UI/bytecount.pm
index 0891e6d..7e78bf5 100644
--- a/FS/FS/UI/bytecount.pm
+++ b/FS/FS/UI/bytecount.pm
@@ -1,10 +1,15 @@
package FS::UI::bytecount;
use strict;
-use vars qw($DEBUG $me);
+use vars qw($DEBUG $me @ISA @EXPORT_OK);
+use Exporter;
use FS::Conf;
use Number::Format 1.50;
+@ISA = qw( Exporter );
+
+@EXPORT_OK = qw( bytecount_unexact parse_bytecount display_bytecount );
+
$DEBUG = 0;
$me = '[FS::UID::bytecount]';
@@ -32,9 +37,9 @@ sub bytecount_unexact {
return("$bc bytes")
if ($bc < 1000);
return(sprintf("%.2f Kbytes", $bc/1024))
- if ($bc < 1000000);
+ if ($bc < 1048576);
return(sprintf("%.2f Mbytes", $bc/1048576))
- if ($bc < 1000000000);
+ if ($bc < 1073741824);
return(sprintf("%.2f Gbytes", $bc/1073741824));
}
diff --git a/FS/FS/UID.pm b/FS/FS/UID.pm
index 40d29c1..e3a4604 100644
--- a/FS/FS/UID.pm
+++ b/FS/FS/UID.pm
@@ -2,9 +2,9 @@ package FS::UID;
use strict;
use vars qw(
- @ISA @EXPORT_OK $DEBUG $me $cgi $dbh $freeside_uid $user
- $conf_dir $cache_dir $secrets $datasrc $db_user $db_pass %callback @callback
- $driver_name $AutoCommit $callback_hack $use_confcompat
+ @ISA @EXPORT_OK $DEBUG $me $cgi $freeside_uid $user $conf_dir $cache_dir
+ $secrets $datasrc $db_user $db_pass $schema $dbh $driver_name
+ $AutoCommit %callback @callback $callback_hack $use_confcompat
);
use subs qw(
getsecrets cgisetotaker
@@ -150,12 +150,24 @@ sub forksuidsetup {
}
sub myconnect {
- DBI->connect( getsecrets(@_), { 'AutoCommit' => 0,
- 'ChopBlanks' => 1,
- 'ShowErrorStatement' => 1,
- }
- )
+ my $handle = DBI->connect( getsecrets(@_), { 'AutoCommit' => 0,
+ 'ChopBlanks' => 1,
+ 'ShowErrorStatement' => 1,
+ }
+ )
or die "DBI->connect error: $DBI::errstr\n";
+
+ if ( $schema ) {
+ use DBIx::DBSchema::_util qw(_load_driver ); #quelle hack
+ my $driver = _load_driver($handle);
+ if ( $driver =~ /^Pg/ ) {
+ no warnings 'redefine';
+ eval "sub DBIx::DBSchema::DBD::${driver}::default_db_schema {'$schema'}";
+ die $@ if $@;
+ }
+ }
+
+ $handle;
}
=item install_callback
@@ -325,10 +337,11 @@ sub getsecrets {
$secrets = 'secrets';
}
- ($datasrc, $db_user, $db_pass) =
+ ($datasrc, $db_user, $db_pass, $schema) =
map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/$secrets")
or die "Can't get secrets: $conf_dir/$secrets: $!\n";
undef $driver_name;
+
($datasrc, $db_user, $db_pass);
}
diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm
index 97f24d4..e5cd5d3 100644
--- a/FS/FS/Upgrade.pm
+++ b/FS/FS/Upgrade.pm
@@ -91,6 +91,9 @@ sub upgrade_data {
tie my %hash, 'Tie::IxHash',
+ #cust_main (remove paycvv from history)
+ 'cust_main' => [],
+
#msgcat
'msgcat' => [],
@@ -126,6 +129,15 @@ sub upgrade_data {
#fixup access rights
'access_right' => [],
+ #change tax_rate column types
+ 'tax_rate' => [],
+
+ #change recur_flat and enable_prorate
+ 'part_pkg_option' => [],
+
+ #add weights to pkg_category
+ 'pkg_category' => [],
+
;
\%hash;
diff --git a/FS/FS/access_right.pm b/FS/FS/access_right.pm
index 4f8d1e9..bc6dd5d 100644
--- a/FS/FS/access_right.pm
+++ b/FS/FS/access_right.pm
@@ -153,8 +153,6 @@ sub _upgrade_data { # class method
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm
index cf56fd8..8cc8b64 100644
--- a/FS/FS/access_user.pm
+++ b/FS/FS/access_user.pm
@@ -1,7 +1,7 @@
package FS::access_user;
use strict;
-use vars qw( @ISA $DEBUG $me $htpasswd_file );
+use vars qw( @ISA $DEBUG $me $conf $htpasswd_file );
use FS::UID;
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
@@ -19,7 +19,7 @@ $me = '[FS::access_user]';
#kludge htpasswd for now (i hope this bootstraps okay)
FS::UID->install_callback( sub {
- my $conf = new FS::Conf;
+ $conf = new FS::Conf;
$htpasswd_file = $conf->base_dir. '/htpasswd';
} );
@@ -44,8 +44,8 @@ FS::access_user - Object methods for access_user records
=head1 DESCRIPTION
-An FS::access_user object represents an internal access user. FS::access_user inherits from
-FS::Record. The following fields are currently supported:
+An FS::access_user object represents an internal access user. FS::access_user
+inherits from FS::Record. The following fields are currently supported:
=over 4
@@ -274,6 +274,9 @@ sub name {
=item access_usergroup
+Returns links to the the groups this user is a part of, as FS::access_usergroup
+objects (see L<FS::access_usergroup>).
+
=cut
sub access_usergroup {
@@ -467,6 +470,23 @@ sub access_right {
}
+=item default_customer_view
+
+Returns the default customer view for this user, from the
+"default_customer_view" user preference, the "cust_main-default_view" config,
+or the hardcoded default, "jumbo" (may change to "basics" in the near future).
+
+=cut
+
+sub default_customer_view {
+ my $self = shift;
+
+ $self->option('default_customer_view')
+ || $conf->config('cust_main-default_view')
+ || 'jumbo'; #'basics' in 1.9.1?
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/access_usergroup.pm b/FS/FS/access_usergroup.pm
index 8e83060..8511fe5 100644
--- a/FS/FS/access_usergroup.pm
+++ b/FS/FS/access_usergroup.pm
@@ -133,8 +133,6 @@ sub access_group {
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm
index ff0a2b1..28d191a 100644
--- a/FS/FS/agent.pm
+++ b/FS/FS/agent.pm
@@ -3,12 +3,14 @@ package FS::agent;
use strict;
use vars qw( @ISA );
#use Crypt::YAPassGen;
+use Business::CreditCard 0.28;
use FS::Record qw( dbh qsearch qsearchs );
use FS::cust_main;
use FS::cust_pkg;
use FS::agent_type;
use FS::reg_code;
use FS::TicketSystem;
+use FS::Conf;
@ISA = qw( FS::m2m_Common FS::Record );
@@ -200,6 +202,119 @@ sub ticketing_queue {
FS::TicketSystem->queue($self->ticketing_queueid);
};
+=item payment_gateway [ OPTION => VALUE, ... ]
+
+Returns a payment gateway object (see L<FS::payment_gateway>) for this agent.
+
+Currently available options are I<nofatal>, I<invnum>, I<method>, and I<payinfo>.
+
+If I<nofatal> is set, and no gateway is available, then the empty string
+will be returned instead of throwing a fatal exception.
+
+If I<invnum> is set to the number of an invoice (see L<FS::cust_bill>) then
+an attempt will be made to select a gateway suited for the taxes paid on
+the invoice.
+
+The I<method> and I<payinfo> options can be used to influence the choice
+as well. Presently only 'CC' and 'ECHECK' methods are meaningful.
+
+When the I<method> is 'CC' then the card number in I<payinfo> can direct
+this routine to route to a gateway suited for that type of card.
+
+=cut
+
+sub payment_gateway {
+ my ( $self, %options ) = @_;
+
+ my $taxclass = '';
+ if ( $options{invnum} ) {
+
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{invnum} } );
+ die "invnum ". $options{'invnum'}. " not found" unless $cust_bill;
+
+ my @part_pkg =
+ map { $_->part_pkg }
+ grep { $_ }
+ map { $_->cust_pkg }
+ $cust_bill->cust_bill_pkg;
+
+ my @taxclasses = map $_->taxclass, @part_pkg;
+
+ $taxclass = $taxclasses[0]
+ unless grep { $taxclasses[0] ne $_ } @taxclasses; #unless there are
+ #different taxclasses
+ }
+
+ #look for an agent gateway override first
+ my $cardtype;
+ if ( $options{method} && $options{method} eq 'CC' ) {
+ $cardtype = cardtype($options{payinfo});
+ } elsif ( $options{method} && $options{method} eq 'ECHECK' ) {
+ $cardtype = 'ACH';
+ } else {
+ $cardtype = $options{method} || '';
+ }
+
+ my $override =
+ qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => $cardtype,
+ taxclass => $taxclass, } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => '',
+ taxclass => $taxclass, } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => $cardtype,
+ taxclass => '', } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => '',
+ taxclass => '', } );
+
+ my $payment_gateway = new FS::payment_gateway;
+ if ( $override ) { #use a payment gateway override
+
+ $payment_gateway = $override->payment_gateway;
+
+ } else { #use the standard settings from the config
+ # the standard settings from the config could be moved to a null agent
+ # agent_payment_gateway referenced payment_gateway
+
+ my $conf = new FS::Conf;
+ unless ( $conf->exists('business-onlinepayment') ) {
+ if ( $options{'nofatal'} ) {
+ return '';
+ } else {
+ die "Real-time processing not enabled\n";
+ }
+ }
+
+ #load up config
+ my $bop_config = 'business-onlinepayment';
+ $bop_config .= '-ach'
+ if ( $options{method}
+ && $options{method} =~ /^(ECHECK|CHEK)$/
+ && $conf->exists($bop_config. '-ach')
+ );
+ my ( $processor, $login, $password, $action, @bop_options ) =
+ $conf->config($bop_config);
+ $action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+ die "No real-time processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n"
+ unless $processor;
+
+ $payment_gateway->gateway_namespace( $conf->config('business-onlinepayment-namespace') ||
+ 'Business::OnlinePayment');
+ $payment_gateway->gateway_module($processor);
+ $payment_gateway->gateway_username($login);
+ $payment_gateway->gateway_password($password);
+ $payment_gateway->gateway_action($action);
+ $payment_gateway->set('options', [ @bop_options ]);
+
+ }
+
+ $payment_gateway;
+}
+
=item num_prospect_cust_main
Returns the number of prospects (customers with no packages ever ordered) for
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index 67c5c1c..d9c602f 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -13,7 +13,6 @@ use FS::Record qw( qsearch qsearchs );
use FS::cdr_type;
use FS::cdr_calltype;
use FS::cdr_carrier;
-use FS::cdr_upstream_rate;
@ISA = qw(FS::Record);
@EXPORT_OK = qw( _cdr_date_parser_maker _cdr_min_parser_maker );
@@ -153,6 +152,54 @@ points to. You can ask the object for a copy with the I<hash> method.
sub table { 'cdr'; }
+sub table_info {
+ {
+ 'fields' => {
+#XXX fill in some (more) nice names
+ #'acctid' => '',
+ 'calldate' => 'Call date',
+ 'clid' => 'Caller ID',
+ 'src' => 'Source',
+ 'dst' => 'Destination',
+ 'dcontext' => 'Dest. context',
+ 'channel' => 'Channel',
+ 'dstchannel' => 'Destination channel',
+ #'lastapp' => '',
+ #'lastdata' => '',
+ 'startdate' => 'Start date',
+ 'answerdate' => 'Answer date',
+ 'enddate' => 'End date',
+ 'duration' => 'Duration',
+ 'billsec' => 'Billable seconds',
+ 'disposition' => 'Disposition',
+ 'amaflags' => 'AMA flags',
+ 'accountcode' => 'Account code',
+ #'uniqueid' => '',
+ 'userfield' => 'User field',
+ #'cdrtypenum' => '',
+ 'charged_party' => 'Charged party',
+ #'upstream_currency' => '',
+ 'upstream_price' => 'Upstream price',
+ #'upstream_rateplanid' => '',
+ #'ratedetailnum' => '',
+ 'rated_price' => 'Rated price',
+ #'distance' => '',
+ #'islocal' => '',
+ #'calltypenum' => '',
+ #'description' => '',
+ #'quantity' => '',
+ 'carrierid' => 'Carrier ID',
+ #'upstream_rateid' => '',
+ 'svcnum' => 'Freeside service',
+ 'freesidestatus' => 'Freeside status',
+ 'freesiderewritestatus' => 'Freeside rewrite status',
+ 'cdrbatch' => 'Batch',
+ },
+
+ };
+
+}
+
=item insert
Adds this record to the database. If there is an error, returns the error,
@@ -269,6 +316,17 @@ sub check {
$self->SUPER::check;
}
+=item is_tollfree
+
+ Returns true when the cdr represents a toll free number and false otherwise.
+
+=cut
+
+sub is_tollfree {
+ my $self = shift;
+ ( $self->dst =~ /^(\+?1)?8(8|([02-7])\3)/ ) ? 1 : 0;
+}
+
=item set_charged_party
If the charged_party field is already set, does nothing. Otherwise:
@@ -284,17 +342,20 @@ or to the dst field if it is a toll free number.
sub set_charged_party {
my $self = shift;
- unless ( $self->charged_party ) {
+ my $conf = new FS::Conf;
- my $conf = new FS::Conf;
+ unless ( $self->charged_party ) {
if ( $conf->exists('cdr-charged_party-accountcode') && $self->accountcode ){
- $self->charged_party( $self->accountcode );
+ my $charged_party = $self->accountcode;
+ $charged_party =~ s/^0+//
+ if $conf->exists('cdr-charged_party-accountcode-trim_leading_0s');
+ $self->charged_party( $charged_party );
} else {
- if ( $self->dst =~ /^(\+?1)?8[02-8]{2}/ ) {
+ if ( $self->is_tollfree ) {
$self->charged_party($self->dst);
} else {
$self->charged_party($self->src);
@@ -304,9 +365,17 @@ sub set_charged_party {
}
+# my $prefix = $conf->config('cdr-charged_party-truncate_prefix');
+# my $prefix_len = length($prefix);
+# my $trunc_len = $conf->config('cdr-charged_party-truncate_length');
+#
+# $self->charged_party( substr($self->charged_party, 0, $trunc_len) )
+# if $prefix_len && $trunc_len
+# && substr($self->charged_party, 0, $prefix_len) eq $prefix;
+
}
-=item set_status_and_rated_price STATUS [ RATED_PRICE ]
+=item set_status_and_rated_price STATUS [ RATED_PRICE [ SVCNUM ] ]
Sets the status to the provided string. If there is an error, returns the
error, otherwise returns false.
@@ -314,9 +383,10 @@ error, otherwise returns false.
=cut
sub set_status_and_rated_price {
- my($self, $status, $rated_price) = @_;
+ my($self, $status, $rated_price, $svcnum) = @_;
$self->freesidestatus($status);
$self->rated_price($rated_price);
+ $self->svcnum($svcnum) if $svcnum;
$self->replace();
}
@@ -402,51 +472,11 @@ sub calltypename {
$cdr_calltype ? $cdr_calltype->calltypename : '';
}
-=item cdr_upstream_rate
-
-Returns the upstream rate mapping (see L<FS::cdr_upstream_rate>), or the empty
-string if no FS::cdr_upstream_rate object is associated with this CDR.
-
-=cut
-
-sub cdr_upstream_rate {
- my $self = shift;
- return '' unless $self->upstream_rateid;
- qsearchs('cdr_upstream_rate', { 'upstream_rateid' => $self->upstream_rateid })
- or '';
-}
-
-=item _convergent_format COLUMN [ COUNTRYCODE ]
-
-Returns the number in COLUMN formatted as follows:
-
-If the country code does not match COUNTRYCODE (default "61"), it is returned
-unchanged.
-
-If the country code does match COUNTRYCODE (default "61"), it is removed. In
-addiiton, "0" is prepended unless the number starts with 13, 18 or 19. (???)
-
-=cut
-
-sub _convergent_format {
- my( $self, $field ) = ( shift, shift );
- my $countrycode = scalar(@_) ? shift : '61'; #+61 = australia
- #my $number = $self->$field();
- my $number = $self->get($field);
- #if ( $number =~ s/^(\+|011)$countrycode// ) {
- if ( $number =~ s/^\+$countrycode// ) {
- $number = "0$number"
- unless $number =~ /^1[389]/; #???
- }
- $number;
-}
-
=item downstream_csv [ OPTION => VALUE, ... ]
=cut
my %export_names = (
- 'convergent' => {},
'simple' => {
'name' => 'Simple',
'invoice_header' => "Date,Time,Name,Destination,Duration,Price",
@@ -464,30 +494,28 @@ my %export_names = (
'name' => 'Default with source',
'invoice_header' => 'Caller,Date,Time,Number,Destination,Duration,Price',
},
+ 'accountcode_default' => {
+ 'name' => 'Default plus accountcode',
+ 'invoice_header' => 'Date,Time,Account,Number,Destination,Duration,Price',
+ },
);
+my $duration_sub = sub {
+ my($cdr, %opt) = @_;
+ if ( $opt{minutes} ) {
+ $opt{minutes}. ( $opt{granularity} ? 'm' : ' call' );
+ } else {
+ sprintf('%.2fm', $cdr->billsec / 60 );
+ }
+};
+
my %export_formats = (
- 'convergent' => [
- 'carriername', #CARRIER
- sub { shift->_convergent_format('src') }, #SERVICE_NUMBER
- sub { shift->_convergent_format('charged_party') }, #CHARGED_NUMBER
- sub { time2str('%Y-%m-%d', shift->calldate_unix ) }, #DATE
- sub { time2str('%T', shift->calldate_unix ) }, #TIME
- 'billsec', #'duration', #DURATION
- sub { shift->_convergent_format('dst') }, #NUMBER_DIALED
- '', #XXX add (from prefixes in most recent email) #FROM_DESC
- '', #XXX add (from prefixes in most recent email) #TO_DESC
- 'calltypename', #CLASS_CODE
- 'rated_price', #PRICE
- sub { shift->rated_price ? 'Y' : 'N' }, #RATED
- '', #OTHER_INFO
- ],
'simple' => [
sub { time2str('%D', shift->calldate_unix ) }, #DATE
sub { time2str('%r', shift->calldate_unix ) }, #TIME
'userfield', #USER
'dst', #NUMBER_DIALED
- sub { sprintf('%.2fm', shift->billsec / 60 ) }, #DURATION
+ $duration_sub, #DURATION
#sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE
],
@@ -495,9 +523,9 @@ my %export_formats = (
sub { time2str('%D', shift->calldate_unix ) }, #DATE
sub { time2str('%r', shift->calldate_unix ) }, #TIME
#'userfield', #USER
- 'dst', #NUMBER_DIALED
'src', #called from
- sub { sprintf('%.2fm', shift->billsec / 60 ) }, #DURATION
+ 'dst', #NUMBER_DIALED
+ $duration_sub, #DURATION
#sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE
],
@@ -518,9 +546,7 @@ my %export_formats = (
sub { my($cdr, %opt) = @_; $opt{dst_regionname}; },
#DURATION
- sub { my($cdr, %opt) = @_;
- $opt{minutes}. ( $opt{granularity} ? 'm' : ' call' );
- },
+ $duration_sub,
#PRICE
sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; },
@@ -528,11 +554,16 @@ my %export_formats = (
],
);
$export_formats{'source_default'} = [ 'src', @{ $export_formats{'default'} }, ];
+$export_formats{'accountcode_default'} =
+ [ @{ $export_formats{'default'} }[0,1],
+ 'accountcode',
+ @{ $export_formats{'default'} }[2..5],
+ ];
sub downstream_csv {
my( $self, %opt ) = @_;
- my $format = $opt{'format'}; # 'convergent';
+ my $format = $opt{'format'};
return "Unknown format $format" unless exists $export_formats{$format};
#my $conf = new FS::Conf;
@@ -654,10 +685,11 @@ sub _cdr_min_parse {
sub _cdr_date_parser_maker {
my $field = shift;
+ my %options = @_;
my @fields = ref($field) ? @$field : ($field);
return sub {
my( $cdr, $datestring ) = @_;
- my $unixdate = eval { _cdr_date_parse($datestring) };
+ my $unixdate = eval { _cdr_date_parse($datestring, %options) };
die "error parsing date for @fields from $datestring: $@\n" if $@;
$cdr->$_($unixdate) foreach @fields;
};
@@ -665,26 +697,40 @@ sub _cdr_date_parser_maker {
sub _cdr_date_parse {
my $date = shift;
+ my %options = @_;
return '' unless length($date); #that's okay, it becomes NULL
+ return '' if $date eq 'NA'; #sansay
+
+ if ( $date =~ /^([a-z]{3})\s+([a-z]{3})\s+(\d{1,2})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})\s+(\d{4})$/i && $7 > 1970 ) {
+ my $time = str2time($date);
+ return $time if $time > 100000; #just in case
+ }
my($year, $mon, $day, $hour, $min, $sec);
#$date =~ /^\s*(\d{4})[\-\/]\(\d{1,2})[\-\/](\d{1,2})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})\s*$/
#taqua #2007-10-31 08:57:24.113000000
- if ( $date =~ /^\s*(\d{4})\D(\d{1,2})\D(\d{1,2})\s+(\d{1,2})\D(\d{1,2})\D(\d{1,2})(\D|$)/ ) {
+ if ( $date =~ /^\s*(\d{4})\D(\d{1,2})\D(\d{1,2})\D+(\d{1,2})\D(\d{1,2})\D(\d{1,2})(\D|$)/ ) {
($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 );
} elsif ( $date =~ /^\s*(\d{1,2})\D(\d{1,2})\D(\d{4})\s+(\d{1,2})\D(\d{1,2})\D(\d{1,2})(\D|$)/ ) {
($mon, $day, $year, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 );
+ } elsif ( $date =~ /^\s*(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d+\.\d+)(\D|$)/ ) {
+ # broadsoft: 20081223201938.314
+ ($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6);
} else {
die "unparsable date: $date"; #maybe we shouldn't die...
}
- return '' if $year == 1900 && $mon == 1 && $day == 1
- && $hour == 0 && $min == 0 && $sec == 0;
+ return '' if ( $year == 1900 || $year == 1970 ) && $mon == 1 && $day == 1
+ && $hour == 0 && $min == 0 && $sec == 0;
- timelocal($sec, $min, $hour, $day, $mon-1, $year);
+ if ($options{gmt}) {
+ timegm($sec, $min, $hour, $day, $mon-1, $year);
+ } else {
+ timelocal($sec, $min, $hour, $day, $mon-1, $year);
+ }
}
=item batch_import HASHREF
diff --git a/FS/FS/cdr/broadsoft.pm b/FS/FS/cdr/broadsoft.pm
new file mode 100644
index 0000000..423e96f
--- /dev/null
+++ b/FS/FS/cdr/broadsoft.pm
@@ -0,0 +1,108 @@
+package FS::cdr::broadsoft;
+
+use strict;
+use base qw( FS::cdr );
+use vars qw( %info );
+use FS::cdr qw( _cdr_date_parser_maker _cdr_min_parser_maker );
+
+%info = (
+ 'name' => 'Broadsoft',
+ 'weight' => 500,
+ 'header' => 1, #0 default, set to 1 to ignore the first line, or
+ # to higher numbers to ignore that number of lines
+ 'type' => 'csv', #csv (default), fixedlength or xls
+ 'sep_char' => ',', #for csv, defaults to ,
+ 'disabled' => 0, #0 default, set to 1 to disable
+
+ #listref of what to do with each field from the CDR, in order
+ 'import_fields' => [
+
+ skip(2),
+ sub { my($cdr, $data, $conf, $param) = @_;
+ $param->{skiprow} = 1 if lc($data) ne 'normal';
+ '' }, # 3: type
+
+ trim('accountcode'), # 4: userNumber
+ skip(2),
+ trim('src'), # 7: callingNumber
+ skip(1),
+ trim('dst'), # 9: calledNumber
+
+ _cdr_date_parser_maker('startdate'), # 10: startTime
+ skip(1),
+ sub { my($cdr, $data) = @_;
+ $cdr->disposition(
+ lc($data) eq 'yes' ?
+ 'ANSWERED' : 'NO ANSWER') }, # 12: answerIndicator
+ _cdr_date_parser_maker('answerdate'), # 13: answerTime
+ _cdr_date_parser_maker('enddate'), # 14: releaseTime
+
+ ],
+
+);
+
+sub trim {
+ my $fieldname = shift;
+ return sub {
+ my($cdr, $data) = @_;
+ $data =~ s/^\+1//;
+ $cdr->$fieldname($data);
+ ''
+ }
+}
+
+sub skip {
+ map { undef } (1..$_[0]);
+}
+
+1;
+
+__END__
+
+list of freeside CDR fields, useful ones marked with *
+
+ acctid - primary key
+ *[1] calldate - Call timestamp (SQL timestamp)
+ clid - Caller*ID with text
+7 * src - Caller*ID number / Source number
+9 * dst - Destination extension
+ dcontext - Destination context
+ channel - Channel used
+ dstchannel - Destination channel if appropriate
+ lastapp - Last application if appropriate
+ lastdata - Last application data
+10 * startdate - Start of call (UNIX-style integer timestamp)
+13 answerdate - Answer time of call (UNIX-style integer timestamp)
+14 * enddate - End time of call (UNIX-style integer timestamp)
+ * duration - Total time in system, in seconds
+ * billsec - Total time call is up, in seconds
+12 *[2] disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
+ amaflags - What flags to use: BILL, IGNORE etc, specified on a per
+ channel basis like accountcode.
+4 *[3] accountcode - CDR account number to use: account
+ uniqueid - Unique channel identifier
+ userfield - CDR user-defined field
+ cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
+ *[4] charged_party - Service number to be billed
+ upstream_currency - Wholesale currency from upstream
+ *[5] upstream_price - Wholesale price from upstream
+ upstream_rateplanid - Upstream rate plan ID
+ rated_price - Rated (or re-rated) price
+ distance - km (need units field?)
+ islocal - Local - 1, Non Local = 0
+ *[6] calltypenum - Type of call - see FS::cdr_calltype
+ description - Description (cdr_type 7&8 only) (used for
+ cust_bill_pkg.itemdesc)
+ quantity - Number of items (cdr_type 7&8 only)
+ carrierid - Upstream Carrier ID (see FS::cdr_carrier)
+ upstream_rateid - Upstream Rate ID
+ svcnum - Link to customer service (see FS::cust_svc)
+ freesidestatus - NULL, done (or something)
+
+[1] Auto-populated from startdate if not present
+[2] Package options available to ignore calls without a specific disposition
+[3] When using 'cdr-charged_party-accountcode' config
+[4] Auto-populated from src (normal calls) or dst (toll free calls) if not present
+[5] When using 'upstream_simple' rating method.
+[6] Set to usage class classnum when using pre-rated CDRs and usage class-based
+ taxation (local/intrastate/interstate/international)
diff --git a/FS/FS/cdr/netcentrex.pm b/FS/FS/cdr/netcentrex.pm
index 7ccc3df..a434d5d 100644
--- a/FS/FS/cdr/netcentrex.pm
+++ b/FS/FS/cdr/netcentrex.pm
@@ -28,9 +28,12 @@ use FS::cdr qw(_cdr_date_parser_maker);
'', #04 Leg number (all 0)
_cdr_date_parser_maker('startdate'), #05 Authorize timestamp
_cdr_date_parser_maker('answerdate'), #06 Start timestamp
- 'billsec', #'duration', #07 Duration
- _e164_parser_maker('src'), #08 Caller
- _e164_parser_maker('dst'), #09 Callee
+ sub { my( $cdr, $duration ) = @_; #07 Duration
+ $cdr->duration($duration);
+ $cdr->billsec( $duration);
+ },
+ _e164_parser_maker('src', 'charged_party'), #08 Caller
+ _e164_parser_maker('dcontext', 'dst', 'norewrite_pivotonly'=>1) ,#09 Callee
'channel', #10 Source IP
'dstchannel', #11 Destination IP
'userfield', #12 selector Tag
@@ -80,43 +83,40 @@ use FS::cdr qw(_cdr_date_parser_maker);
);
sub _e164_parser_maker {
- my $field = shift;
+ my( $field, $pivot_field, %opt ) = @_;
return sub {
my( $cdr, $e164 ) = @_;
- eval { $cdr->$field( _e164_parse($e164) ); };
- die "error parsing e164 for $field from $e164: $@\n" if $@;
+ my( $pivot, $number ) = _e164_parse($e164);
+ if ( $opt{'norewrite_pivotonly'} && ! $pivot ) {
+ $cdr->$pivot_field( $number );
+ } else {
+ $cdr->$field( $number );
+ $cdr->$pivot_field( $pivot );
+ }
};
}
-my %e164_types = (
- '000000' => '',
- '100005' => '',
- '100009' => '',
- '100012' => '',
- '100014' => '',
- '100015' => '',
- '100016' => '',
- '300000' => '',
-);
-
sub _e164_parse {
my $e164 = shift;
$e164 =~ s/^e164://;
- my ($type, $number);
+ my ($pivot, $number);
if ( $e164 =~ /^O(\d+)$/ ) {
- $type = ''; #?
+ $pivot = ''; #?
$number = $1;
- } elsif ( $e164 =~ /^(\d{6})(\d+)$/ ) {
- $type = $1;
+ } elsif ( $e164 =~ /^000000(\d+)$/ ) {
+ $pivot = '';
+ $number = $1;
+ } elsif ( $e164 =~ /^(1\d{5})(\d+)$/ ) {
+ $pivot = $1;
$number = $2;
} else {
- $type = '';
+ $pivot = '';
$number = $e164; #unparsable...
}
- #$type...?
- $number;
+
+ ( $pivot, $number );
}
1;
diff --git a/FS/FS/cdr/sansay.pm b/FS/FS/cdr/sansay.pm
new file mode 100644
index 0000000..44accdc
--- /dev/null
+++ b/FS/FS/cdr/sansay.pm
@@ -0,0 +1,408 @@
+package FS::cdr::sansay;
+
+use strict;
+use base qw( FS::cdr );
+use vars qw( %info );
+use FS::cdr qw( _cdr_date_parser_maker _cdr_min_parser_maker );
+
+%info = (
+ 'name' => 'Sansay VSX',
+ 'weight' => 135,
+ 'header' => 1, #0 default, set to 1 to ignore the first line, or
+ # to higher numbers to ignore that number of lines
+ 'type' => 'csv', #csv (default), fixedlength or xls
+ 'sep_char' => ';', #for csv, defaults to ,
+ 'disabled' => 0, #0 default, set to 1 to disable
+
+
+ #listref of what to do with each field from the CDR, in order
+ 'import_fields' => [
+
+ # "Header" (I do not think this means what you think it means)
+ #002452502;V1.10;R;
+
+ # Record Sequence Number 9 Unique identification of this record
+ 'uniqueid',
+
+ '', #Version Number 5 Format version number of records to follow
+ # "V1.10"
+ '', #Record Type 1 Type of CDR being generated
+ # R ­ Normal CDR record, A - Audit
+
+ # "Body"
+ #WithMedia;181-1071459514@192.188.0.28;0001;Mon Dec 15 11:38:34 2003;Mon Dec 15 11:38:41 2003;Mon Dec 15 11:38:48 2003;480;EndedByRemoteUser;3;T;000200;H323;;192.188.0.38;9001;192.188.0.28;f0faff54-2e6c-11d8-8c4b-bd4d562c2265;192.188.0.38;18044;192.188.0.28;10756;G.729b;240;460;6066;14060;0;0;0;000200;H323;;192.188.0.28;8811;192.188.0.38;e83af3d3-1d2d-d811-9f98-003048424934;192.188.0.38;19236;192.188.0.28;10758;G.729b;460;240;14060;6066;0;0;0;F;9001;305;2;15;305000;00000011 44934567 45231267 2300BCC0;8587542200;
+
+ '', #ConnectionType 16 Type of connection : Media or No Media
+ '', #SessionID 32 Unique ID assigned to the call by
+ # SSM subsystem
+ '', #XXX #Release Cause 4 2.4 Internal process Release Cause
+
+ #Cause Code Descriptions
+ #01 Normal answered call
+ #02 No Answer, tear down by originator
+ #03 No answer, tear down by the termination
+ #04 NORMAL_NO_ANSWER, tear down by
+ # system
+ #402 Service Not Available
+ #403 Termination capability un-compatible
+ #404 Outbound digit translation failed
+ #405 Termination reject for some other reasons
+ #406 Termination Route is blocked
+ #500 Originator is not in the Authorized list
+ # (source verification failed)
+ #501 Origination digit translation failed
+ #502 Origination direction is not bi-directional or
+ # inbound
+ #503 Origination is not in service state
+ #600 Max system call handling reached
+ #601 System reject call
+ #602 System outbound digit translation error
+ # (maybe invalid configuration)
+ #603 System inbound digit translation error
+ # (Maybe invalid configuration)
+
+
+ #Start Time of Date 32 Indicates Time of Date when the call
+ # entered the system
+ _cdr_date_parser_maker('startddate'),
+
+ #Answer Time of Date 32 Indicates TOD when the call was
+ # answered
+ _cdr_date_parser_maker('answerdate'),
+
+ #Release TOD 32 Indicates the TOD when the call was
+ # disconnected
+ _cdr_date_parser_maker('enddate'),
+
+ #Minutes West of 32 Minutes West of Greenwich Mean
+ #Greenwich Mean Time Time. Used to calculate the time
+ # zone.
+ '', #XXX use this
+
+ #Release Cause from 32 Release cause string from either H323
+ #Protocol Stack or SIP protocol stack
+ #4. Release Cause String (Field #8 in CDR)
+ #- a string of text further identifying the teardown circumstance from terminating protocol message.
+ '',
+
+ #Binary Value of Release 4 Binary value of the protocol release
+ #Cause from Protocol cause
+ #stack
+ #
+ #3. Release Cause from Stack ( Field # 9 in CDR)
+ #- an integer value based on the releasing dialogues protocol.
+ # a. For a H.323 call leg originated release it will be the real Q.931 value received from the far
+ # side.
+ #Some of the Q.931 release causes;
+ #3: No route to destination
+ #16; Normal Clearing
+ #17: User Busy
+ #19: NO Answer from User
+ #21; Call Rejected
+ #28: Address Incomplete
+ #34: No Circuit Channel Available
+ #....
+ # b. For a SIP call leg originated release, it's a RFC 3261 release cause value received from the
+ # far side.
+ #The following is the list that VSX generated if certain event happen:
+ #"400 Parse Failed" - Malformed Message
+ #"405 Method Not Allowed" - Unsupported Method
+ #"480 Temporarily Unavailable" - Overload Throttle Rejection, Max Sessions
+ #Exceeded, Demo License Expired, Capacity Exceeded on Route, Radius Server Timeout
+ #"415 No valid codec" - No valid codec could be supported between origination and
+ #term call legs.
+ #"481 Transaction Does Not Exist" - Unknown Transaction or Dialog
+ #"487 Transaction Terminated" - Origination Cancel
+ #"488 ReInvite Rejected" - Relay of ReInvite was Rejected
+ #"504 Server Time-out" - Internal VSX Failure
+ #"500 Sequence Out of Order" - CSeq counter violation
+ # c. For a VSX system originated release, it an internal release cause for teardown.
+ #If the VSX initiates a call teardown, the following cause values and strings are written into the CDR:
+ #999, "Demo Licence Expired!"
+ #999, "VSX Capacity Exceeded"
+ #999, "VSX Operator Reset"
+ #999, "Route Rejected"
+ #999, "Radius Rejected"
+ #999, "Radius Access Timeout"
+ #999, "Gatekeeper Reject"
+ #999, "Enum Server Reject"
+ #999, "Enum Server Timeout"
+ #999, "DNS Server Reject"
+ #999, "DNS/GK Timeout"
+ #999, "Could not allocate media"
+ #999, "No Response to INVITE"
+ #999, "Ring No Answer Timeout"
+ #999, "200 OK Timeout"
+ #999, "Maximum Duration Exceeded"
+ #987, "Termination Capacity Exceeded"
+ #987, "Origination Capacity Exceeded"
+ #987, "Term CPS Capacity Exceeded"
+ #987, "Orig CPS Capacity Exceeded"
+ #987, "Max H323 Legs Exceeded"
+ '',
+
+ #1st release dialogue 1 O: origination, T: termination
+ #2. 1st Release Dialogue ( Field #10 in CDR)
+ #- one character value identifying the side of the call that i
+ # ,,O ­ origination initiated the teardown.
+ # ,,T ­ termination initiated the teardown.
+ # ,,N ­ the VSX internally initiated the teardown.
+ '',
+
+ #Trunk ID -- Origination 6 TrunkID for origination GW(resources)
+ 'accountcode', # right? # use cdr-charged_party-accountcode
+
+ #VoIP Protocol - Origination 6 VoIP protocol for origination dialogue
+ '',
+
+ #Origination Source Number 128 Source Number in Origination Dialogue
+ 'src',
+
+ #Origination Source Host Name 128 FQDN or IP address for Source GW in Origination Dialogue
+ 'channel',
+
+ #Origination Destination Number 128 Destination Number in Origination
+ #Dialogue
+ 'dst',
+
+ #Origination Destination Host Name 128 FQDN or IP address for Destination
+ #GW in Origination Dialogue
+ 'dstchannel',
+
+ #Origination Call ID 128 Unique ID for the origination dialogue(leg)
+ '', #'clid', #? that's not really the same call ID
+
+ #Origination Remote 16 Remote Payload IP address for
+ # Payload IP origination dialogue
+ # Address
+ '',
+
+ #Origination Remote 6 Remote Payload UDP address for
+ # Payload UDP origination dialogue
+ # Address
+ '',
+
+ #Origination Local 16 Local(SG) Payload IP address for
+ # Payload IP origination dialogue
+ # Address
+ '',
+
+ #Origination Local 6 Local(SG) Payload UDP address for
+ # Payload UDP origination dialogue
+ # Address
+ '',
+
+ #Origination Codec List 128 Supported Codec list( separated by
+ # comma) for origination dialogue
+ '',
+
+ #Origination Ingress 10 Number of Ingress( into Sansay
+ # Packets system) payload packets in
+ # origination dialogue
+ '',
+
+ #Origination Egress 10 Number of Egress( out from Sansay
+ # Packets system) payload packets in
+ # origination dialogue
+ '',
+
+ #Origination Ingress 10 Number of Ingress( into Sansay
+ # Octets system) payload octets in origination
+ # dialogue
+ '',
+
+ #Origination Egress 10 Number of Egress( out from Sansay
+ # Octets system) payload octets in origination
+ # dialogue
+ '',
+
+ #Origination Ingress 10 Number of Ingress( into Sansay
+ # Packet Loss system) payload packet loss in
+ # origination dialogue
+ '',
+
+ #Origination Ingress 10 Average Ingress( into Sansay system)
+ # Delay payload packets delay ( in ms) in
+ # origination dialogue
+ '',
+
+ #Origination Ingress 10 Average of Ingress( into Sansay
+ # Packet Jitter system) payload packet Jitter ( in ms)
+ # in origination dialogue
+ '',
+
+ #Trunk ID -- Termination 6 Trunk ID for termination GW(resources)
+ 'carrierid',
+
+ #VoIP Protocol - 6 VoIP protocol from termination GW
+ # Termination
+ '',
+
+ #Termination Source 128 Source Number in Termination
+ # Number Dialogue
+ '',
+
+ #Termination Source Host 128 FQDN or IP address for Source GW
+ # Name in Termination Dialogue
+ '',
+
+ #Termination Destination 128 Destination Number in Termination
+ # Number Dialogue
+ '',
+
+ #Termination Destination 128 FQDN or IP address for Destination
+ # Host Name GW in Termination Dialogue
+ '',
+
+ #Termination Call ID 128 Unique ID for the termination
+ # dialogue(leg)
+ '',
+
+ #Termination Remote 16 Remote Payload IP address for
+ # Payload IP termination dialogue
+ # Address
+ '',
+
+ #Termination Remote 6 Remote Payload UDP address for
+ # Payload UDP termination dialogue
+ # Address
+ '',
+
+ #Termination Local 16 Local(SG) Payload IP address for
+ # Payload IP termination dialogue
+ # Address
+ '',
+
+ #Termination Local 6 Local(SG) Payload UDP address for
+ # Payload UDP termination dialogue
+ # Address
+ '',
+
+ #Termination Codec List 128 Supported Codec list( separated by
+ # comma) for termination dialogue
+ '',
+
+ #Termination Ingress 10 Number of Ingress( into Sansay
+ # Packets system) payload packets in
+ # termination dialogue
+ '',
+
+ #Termination Egress 10 Number of Egress( out from Sansay
+ # Packets system) payload packets in
+ # termination dialogue
+ '',
+
+ #Termination Ingress 10 Number of Ingress( into Sansay
+ # Octets system) payload octets in
+ # termination dialogue
+ '',
+
+ #Termination Egress 10 Number of Egress( out from Sansay
+ # Octets system) payload octets in
+ # termination dialogue
+ '',
+
+ #Termination Ingress 10 Number of Ingress( into Sansay
+ # Packet Loss system) payload packet loss in
+ # termination dialogue
+ '',
+
+ #Termination Ingress 10 Average Ingress( into Sansay system)
+ # Delay payload packets delay ( in ms) in
+ # termination dialogue
+ '',
+
+ #Termination Ingress 10 Average of Ingress( into Sansay
+ # Packet Jitter system) payload packet Jitter ( in ms)
+ # in termination dialogue
+ '',
+
+ #Final Route Indication 1 F: Final Route Selection,
+ # I: Intermediate Route Attempts
+ '',
+
+ #Routing Digits 64 Routing Digit (Digit after Inbound
+ # translation, before Outbound
+ # Translation). This may also be the
+ # LRN if LNP feature is enabled
+ '',
+
+ #Call Duration in Second 6 Call Duration in Seconds. 0 if this is
+ # failed call
+ 'billsec',
+
+ #Post Dial Delay in 6 Post dial delay (from call attempt to
+ # Seconds ring). 0 if this is failed call
+ '',
+
+ #Ring Time in Second 6 Ring Time in Seconds. 0 if this is
+ # failed call
+ '',
+
+ #Duration in milliseconds 10 Call duration in milliseconds.
+ '',
+
+ #Conf ID 36 Unique Conference ID for this call in
+ # Cisco format
+ '',
+
+ #RPID/ANI 32 Inbound Remote Party ID line or
+ # Proxy Asserted Identity if provided
+ 'clid', #?
+
+ ],
+
+);
+
+1;
+
+__END__
+
+list of freeside CDR fields, useful ones marked with *
+
+N/A acctid - primary key
+FILLED_IN *[1] calldate - Call timestamp (SQL timestamp)
+DONE clid - Caller*ID with text
+DONE * src - Caller*ID number / Source number
+DONE * dst - Destination extension
+ dcontext - Destination context
+DONE channel - Channel used
+DONE dstchannel - Destination channel if appropriate
+ lastapp - Last application if appropriate
+ lastdata - Last application data
+DONE * startdate - Start of call (UNIX-style integer timestamp)
+DONE answerdate - Answer time of call (UNIX-style integer timestamp)
+DONE * enddate - End time of call (UNIX-style integer timestamp)
+* duration - Total time in system, in seconds
+DONE * billsec - Total time call is up, in seconds
+*[2] disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
+ amaflags - What flags to use: BILL, IGNORE etc, specified on a per
+ channel basis like accountcode.
+DONE *[3] accountcode - CDR account number to use: account
+ uniqueid - Unique channel identifier
+ userfield - CDR user-defined field
+ cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
+FILLED_IN *[4] charged_party - Service number to be billed
+ upstream_currency - Wholesale currency from upstream
+*[5] upstream_price - Wholesale price from upstream
+ upstream_rateplanid - Upstream rate plan ID
+ rated_price - Rated (or re-rated) price
+ distance - km (need units field?)
+ islocal - Local - 1, Non Local = 0
+*[6] calltypenum - Type of call - see FS::cdr_calltype
+ description - Description (cdr_type 7&8 only) (used for
+ cust_bill_pkg.itemdesc)
+ quantity - Number of items (cdr_type 7&8 only)
+DONE carrierid - Upstream Carrier ID (see FS::cdr_carrier)
+ upstream_rateid - Upstream Rate ID
+ svcnum - Link to customer service (see FS::cust_svc)
+ freesidestatus - NULL, done (or something)
+
+[1] Auto-populated from startdate if not present
+[2] Package options available to ignore calls without a specific disposition
+[3] When using 'cdr-charged_party-accountcode' config
+[4] Auto-populated from src (normal calls) or dst (toll free calls) if not present
+[5] When using 'upstream_simple' rating method.
+[6] Set to usage class classnum when using pre-rated CDRs and usage class-based
+ taxation (local/intrastate/interstate/international)
+
diff --git a/FS/FS/cdr/taqua.pm b/FS/FS/cdr/taqua.pm
index 3052f83..26c0bda 100644
--- a/FS/FS/cdr/taqua.pm
+++ b/FS/FS/cdr/taqua.pm
@@ -13,7 +13,13 @@ use FS::cdr qw(_cdr_date_parser_maker);
'import_fields' => [ #some of these are kind arbitrary...
#0
- 'cdrtypenum', #RecordType
+ #RecordType
+ sub {
+ my($cdr, $field, $conf, $hashref) = @_;
+ $hashref->{skiprow} = 1 unless ($field == 0 && $cdr->disposition == 100);
+ $cdr->cdrtypenum($field);
+ },
+
sub { my($cdr, $field) = @_; }, #all10#RecordVersion
sub { my($cdr, $field) = @_; }, #OrigShelfNumber
sub { my($cdr, $field) = @_; }, #OrigCardNumber
@@ -22,11 +28,20 @@ use FS::cdr qw(_cdr_date_parser_maker);
'uniqueid', #SequenceNumber
'accountcode', #SessionNumber
'src', #CallingPartyNumber
- 'dst', #CalledPartyNumber
+ #'dst', #CalledPartyNumber
+ #CalledPartyNumber
+ sub {
+ my( $cdr, $field, $conf ) = @_;
+ if ( $cdr->calltypenum == 6 && $cdr->cdrtypenum == 0 ) {
+ $cdr->dst("+$field");
+ } else {
+ $cdr->dst($field);
+ }
+ },
#10
- _cdr_date_parser_maker('startdate'), #CallArrivalTime
- _cdr_date_parser_maker('enddate'), #CallCompletionTime
+ _cdr_date_parser_maker('startdate', 'gmt' => 1), #CallArrivalTime
+ _cdr_date_parser_maker('enddate', 'gmt' => 1), #CallCompletionTime
#Disposition
#sub { my($cdr, $d ) = @_; $cdr->disposition( $disposition{$d}): },
@@ -42,7 +57,7 @@ use FS::cdr qw(_cdr_date_parser_maker);
# 201 => '',
# 203 => '',
- _cdr_date_parser_maker('answerdate'), #DispositionTime
+ _cdr_date_parser_maker('answerdate', 'gmt' => 1), #DispositionTime
sub { my($cdr, $field) = @_; }, #TCAP
sub { my($cdr, $field) = @_; }, #OutboundCarrierConnectTime
sub { my($cdr, $field) = @_; }, #OutboundCarrierDisconnectTime
@@ -79,7 +94,11 @@ use FS::cdr qw(_cdr_date_parser_maker);
return;
}
}
- $cdr->charged_party($field);
+ if ( $cdr->is_tollfree ) { # thankfully this is already available
+ $cdr->charged_party($cdr->dst); # and this
+ } else {
+ $cdr->charged_party($field);
+ }
},
sub { my($cdr, $field) = @_; }, #SubscriberNumber
diff --git a/FS/FS/cdr/transnexus.pm b/FS/FS/cdr/transnexus.pm
new file mode 100644
index 0000000..0ed7ad4
--- /dev/null
+++ b/FS/FS/cdr/transnexus.pm
@@ -0,0 +1,66 @@
+package FS::cdr::transnexus;
+
+use strict;
+use base qw( FS::cdr );
+use vars qw( %info );
+use MIME::Base64;
+use FS::cdr qw( _cdr_date_parser_maker _cdr_min_parser_maker );
+
+%info = (
+ 'name' => 'Transnexus',
+ 'weight' => 18,
+ 'type' => 'csv',
+ 'sep_char' => "\t",
+
+ #listref of what to do with each field from the CDR, in order
+ 'import_fields' => [
+
+ _cdr_date_parser_maker('startddate'), #O_CallStartTime
+ 'src', #CallingNumberReported
+ 'dst', #CalledNumberReported
+ 'channel', #SourceDeviceName / O_ReportingDeviceName
+ 'dstchannel', #O_ReportingDeviceName / DestinationDeviceName
+ sub { $_[0]->clid( decode_base64($_[1]) ); }, #CallId
+ 'uniqueid', #TransactionId
+ 'duration', #RatedDuration
+ 'billsec', #O_BillingDuration
+ 'upstream_price', #O_BillingAmountCustCurr
+ ],
+);
+
+1;
+
+__END__
+
+O_CallStartTime - Date and time stamp of the call setup as reported in the CDR from the source device.
+
+CallingNumberReported - Calling number from the source device reported in authorization request to the OSPrey server.
+
+CalledNumberReported - Called number from the source device reported in authorization request to the OSPrey server.
+
+----
+1.1.1 Customer CDR Archive File
+
+SourceDeviceName - The IP address or Domain Name of the device which is the call source.
+
+O_ReportingDeviceName - IP address or Domain Name of the source (Originating) device reporting the CDR to the OSPrey Server. If a proxy is used, (such as SIP proxy for signaling or FreeRADIUS for CDR reporting) this field is the IP address of the proxy device, not the actual source device.
+
+---
+or 1.1.2 Provider CDR Archive File
+
+O_ReportingDeviceName - IP address or Domain Name of the source (Originating) device reporting the CDR to the OSPrey Server. If a proxy is used, (such as SIP proxy for signaling or FreeRADIUS for CDR reporting) this field is the IP address of the proxy device, not the actual source device.
+
+DestinationDeviceName - The IP address or Domain Name of the destination device.
+
+----
+
+CallId - The Call Identifier generated by the source VoIP device.
+
+TransactionId - The unique Transaction Identification number created by the OSPrey server for each call
+
+RatedDuration - The rateable duration calculated by NexOSS.
+
+O_BillingDuration - The duration used to calculate the billable amount for a call from the source (Originating) network. This value is derived from RatedDuration and rounded up based on the ¿First Increment¿ or ¿Next Increment¿ rules defined in the Product or Customer Rate Plan used to rate the call.
+
+O_BillingAmountCustCurr - Amount billable to the source (Originating) Customer. Provided in the currency of the Product or Customer Rate Plan.
+
diff --git a/FS/FS/cdr/vitelity.pm b/FS/FS/cdr/vitelity.pm
new file mode 100644
index 0000000..97ed0c3
--- /dev/null
+++ b/FS/FS/cdr/vitelity.pm
@@ -0,0 +1,25 @@
+package FS::cdr::vitelity;
+
+use strict;
+use vars qw( @ISA %info );
+use FS::cdr qw(_cdr_date_parser_maker);
+
+@ISA = qw(FS::cdr);
+
+%info = (
+ 'name' => 'Vitelity',
+ 'weight' => 100,
+ 'header' => 1,
+ 'import_fields' => [
+ # Cheers to Vitelity for their concise, readable CDR format.
+ _cdr_date_parser_maker('startdate'),
+ 'src',
+ 'dst',
+ 'duration',
+ 'clid',
+ 'disposition',
+ 'upstream_price',
+ ],
+);
+
+1;
diff --git a/FS/FS/cdr_termination.pm b/FS/FS/cdr_termination.pm
new file mode 100644
index 0000000..e0cde6e
--- /dev/null
+++ b/FS/FS/cdr_termination.pm
@@ -0,0 +1,152 @@
+package FS::cdr_termination;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::cdr_termination - Object methods for cdr_termination records
+
+=head1 SYNOPSIS
+
+ use FS::cdr_termination;
+
+ $record = new FS::cdr_termination \%hash;
+ $record = new FS::cdr_termination { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cdr_termination object represents an CDR termination status.
+FS::cdr_termination inherits from FS::Record. The following fields are
+currently supported:
+
+=over 4
+
+=item cdrtermnum
+
+primary key
+
+=item acctid
+
+acctid
+
+=item termpart
+
+termpart
+
+=item rated_price
+
+rated_price
+
+=item status
+
+status
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cdr_termination'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('cdrtermnum')
+ || $self->ut_foreign_key('acctid', 'cdr', 'acctid')
+ #|| $self->ut_foreign_key('termpart', 'part_termination', 'termpart')
+ || $self->ut_number('termpart')
+ || $self->ut_float('rated_price')
+ || $self->ut_enum('status', [ '', 'done' ] ) # , 'skipped' ] )
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+#=item set_status_and_rated_price STATUS [ RATED_PRICE ]
+#
+#Sets the status to the provided string. If there is an error, returns the
+#error, otherwise returns false.
+#
+#=cut
+#
+#sub set_status_and_rated_price {
+# my($self, $status, $rated_price) = @_;
+# $self->status($status);
+# $self->rated_price($rated_price);
+# $self->replace();
+#}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cdr>, L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/clientapi_session_field.pm b/FS/FS/clientapi_session_field.pm
index bfa487d..085e956 100644
--- a/FS/FS/clientapi_session_field.pm
+++ b/FS/FS/clientapi_session_field.pm
@@ -113,8 +113,6 @@ sub check {
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::clientapi_session>, L<FS::ClientAPI>, L<FS::Record>, schema.html from the
diff --git a/FS/FS/cust_attachment.pm b/FS/FS/cust_attachment.pm
new file mode 100644
index 0000000..9527381
--- /dev/null
+++ b/FS/FS/cust_attachment.pm
@@ -0,0 +1,170 @@
+package FS::cust_attachment;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+use FS::Conf;
+
+=head1 NAME
+
+FS::cust_attachment - Object methods for cust_attachment records
+
+=head1 SYNOPSIS
+
+ use FS::cust_attachment;
+
+ $record = new FS::cust_attachment \%hash;
+ $record = new FS::cust_attachment { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_attachment object represents a file attached to a L<FS::cust_main>
+object. FS::cust_attachment inherits from FS::Record. The following fields
+are currently supported:
+
+=over 4
+
+=item attachnum
+
+Primary key (assigned automatically).
+
+=item custnum
+
+Customer number (see L<FS::cust_main>).
+
+=item _date
+
+The date the record was last updated.
+
+=item otaker
+
+Order taker (assigned automatically; see L<FS::UID>).
+
+=item filename
+
+The file's name.
+
+=item mime_type
+
+The Content-Type of the file.
+
+=item body
+
+The contents of the file.
+
+=item disabled
+
+If the attachment was disabled, this contains the date it was disabled.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new attachment object.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cust_attachment'; }
+
+sub nohistory_fields { 'body'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid example. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $conf = new FS::Conf;
+ my $error;
+ if($conf->config('disable_cust_attachment') ) {
+ $error = 'Attachments disabled (see configuration)';
+ }
+
+ $error =
+ $self->ut_numbern('attachnum')
+ || $self->ut_number('custnum')
+ || $self->ut_numbern('_date')
+ || $self->ut_text('otaker')
+ || $self->ut_text('filename')
+ || $self->ut_text('mime_type')
+ || $self->ut_numbern('disabled')
+ || $self->ut_anything('body')
+ ;
+ if($conf->config('max_attachment_size')
+ and $self->size > $conf->config('max_attachment_size') ) {
+ $error = 'Attachment too large'
+ }
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=item size
+
+Returns the size of the attachment in bytes.
+
+=cut
+
+sub size {
+ my $self = shift;
+ return length($self->body);
+}
+
+=back
+
+=head1 BUGS
+
+Doesn't work on non-Postgres systems.
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 704b350..493bc09 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -16,6 +16,7 @@ use FS::Misc qw( send_email send_fax generate_ps generate_pdf do_print );
use FS::Record qw( qsearch qsearchs dbh );
use FS::cust_main_Mixin;
use FS::cust_main;
+use FS::cust_statement;
use FS::cust_bill_pkg;
use FS::cust_bill_pkg_display;
use FS::cust_credit;
@@ -82,6 +83,8 @@ owes you money. The specific charges are itemized as B<cust_bill_pkg> records
(see L<FS::cust_bill_pkg>). FS::cust_bill inherits from FS::Record. The
following fields are currently supported:
+Regular fields
+
=over 4
=item invnum - primary key (assigned automatically for new invoices)
@@ -93,10 +96,38 @@ L<Time::Local> and L<Date::Parse> for conversion functions.
=item charged - amount of this invoice
+=item invoice_terms - optional terms override for this specific invoice
+
+=back
+
+Customer info at invoice generation time
+
+=over 4
+
+=item previous_balance
+
+=item billing_balance
+
+=back
+
+Deprecated
+
+=over 4
+
=item printed - deprecated
+=back
+
+Specific use cases
+
+=over 4
+
=item closed - books closed flag, empty or `Y'
+=item statementnum - invoice aggregation (see L<FS::cust_statement>)
+
+=item agent_invid - legacy invoice number
+
=back
=head1 METHODS
@@ -141,7 +172,50 @@ Really, don't use it.
sub delete {
my $self = shift;
return "Can't delete closed invoice" if $self->closed =~ /^Y/i;
- $self->SUPER::delete(@_);
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $table (qw(
+ cust_bill_event
+ cust_event
+ cust_credit_bill
+ cust_bill_pay
+ cust_bill_pay
+ cust_credit_bill
+ cust_pay_batch
+ cust_bill_pay_batch
+ cust_bill_pkg
+ )) {
+
+ foreach my $linked ( $self->$table() ) {
+ my $error = $linked->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ }
+
+ my $error = $self->SUPER::delete(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
}
=item replace OLD_RECORD
@@ -183,17 +257,16 @@ sub check {
my $error =
$self->ut_numbern('invnum')
- || $self->ut_number('custnum')
+ || $self->ut_foreign_key('custnum', 'cust_main', 'custnum' )
|| $self->ut_numbern('_date')
|| $self->ut_money('charged')
|| $self->ut_numbern('printed')
|| $self->ut_enum('closed', [ '', 'Y' ])
+ || $self->ut_foreign_keyn('statementnum', 'cust_statement', 'statementnum' )
+ || $self->ut_numbern('agent_invid') #varchar?
;
return $error if $error;
- return "Unknown customer"
- unless qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
-
$self->_date(time) unless $self->_date;
$self->printed(0) if $self->printed eq '';
@@ -201,6 +274,22 @@ sub check {
$self->SUPER::check;
}
+=item display_invnum
+
+Returns the displayed invoice number for this invoice: agent_invid if
+cust_bill-default_agent_invid is set and it has a value, invnum otherwise.
+
+=cut
+
+sub display_invnum {
+ my $self = shift;
+ if ( $conf->exists('cust_bill-default_agent_invid') && $self->agent_invid ){
+ return $self->agent_invid;
+ } else {
+ return $self->invnum;
+ }
+}
+
=item previous
Returns a list consisting of the total previous balance for this customer,
@@ -235,6 +324,25 @@ sub cust_bill_pkg {
);
}
+=item cust_bill_pkg_pkgnum PKGNUM
+
+Returns the line items (see L<FS::cust_bill_pkg>) for this invoice and
+specified pkgnum.
+
+=cut
+
+sub cust_bill_pkg_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ qsearch(
+ { 'table' => 'cust_bill_pkg',
+ 'hashref' => { 'invnum' => $self->invnum,
+ 'pkgnum' => $pkgnum,
+ },
+ 'order_by' => 'ORDER BY billpkgnum',
+ }
+ );
+}
+
=item cust_pkg
Returns the packages (see L<FS::cust_pkg>) corresponding to the line items for
@@ -407,6 +515,16 @@ sub cust_pay {
#;
}
+sub cust_pay_batch {
+ my $self = shift;
+ qsearch('cust_pay_batch', { 'invnum' => $self->invnum } );
+}
+
+sub cust_bill_pay_batch {
+ my $self = shift;
+ qsearch('cust_bill_pay_batch', { 'invnum' => $self->invnum } );
+}
+
=item cust_bill_pay
Returns all payment applications (see L<FS::cust_bill_pay>) for this invoice.
@@ -415,23 +533,71 @@ Returns all payment applications (see L<FS::cust_bill_pay>) for this invoice.
sub cust_bill_pay {
my $self = shift;
+ map { $_ } #return $self->num_cust_bill_pay unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_bill_pay', { 'invnum' => $self->invnum } );
}
=item cust_credited
+=item cust_credit_bill
+
Returns all applied credits (see L<FS::cust_credit_bill>) for this invoice.
=cut
sub cust_credited {
my $self = shift;
+ map { $_ } #return $self->num_cust_credit_bill unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_credit_bill', { 'invnum' => $self->invnum } )
;
}
+sub cust_credit_bill {
+ shift->cust_credited(@_);
+}
+
+=item cust_bill_pay_pkgnum PKGNUM
+
+Returns all payment applications (see L<FS::cust_bill_pay>) for this invoice
+with matching pkgnum.
+
+=cut
+
+sub cust_bill_pay_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ map { $_ } #return $self->num_cust_bill_pay_pkgnum($pkgnum) unless wantarray;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_bill_pay', { 'invnum' => $self->invnum,
+ 'pkgnum' => $pkgnum,
+ }
+ );
+}
+
+=item cust_credited_pkgnum PKGNUM
+
+=item cust_credit_bill_pkgnum PKGNUM
+
+Returns all applied credits (see L<FS::cust_credit_bill>) for this invoice
+with matching pkgnum.
+
+=cut
+
+sub cust_credited_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ map { $_ } #return $self->num_cust_credit_bill_pkgnum($pkgnum) unless wantarray;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_credit_bill', { 'invnum' => $self->invnum,
+ 'pkgnum' => $pkgnum,
+ }
+ );
+}
+
+sub cust_credit_bill_pkgnum {
+ shift->cust_credited_pkgnum(@_);
+}
+
=item tax
Returns the tax amount (see L<FS::cust_bill_pkg>) for this invoice.
@@ -465,12 +631,35 @@ sub owed {
$balance;
}
-=item apply_payments_and_credits
+sub owed_pkgnum {
+ my( $self, $pkgnum ) = @_;
+
+ #my $balance = $self->charged;
+ my $balance = 0;
+ $balance += $_->setup + $_->recur for $self->cust_bill_pkg_pkgnum($pkgnum);
+
+ $balance -= $_->amount for $self->cust_bill_pay_pkgnum($pkgnum);
+ $balance -= $_->amount for $self->cust_credited_pkgnum($pkgnum);
+
+ $balance = sprintf( "%.2f", $balance);
+ $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp
+ $balance;
+}
+
+=item apply_payments_and_credits [ OPTION => VALUE ... ]
+
+Applies unapplied payments and credits to this invoice.
+
+A hash of optional arguments may be passed. Currently "manual" is supported.
+If true, a payment receipt is sent instead of a statement when
+'payment_receipt_email' configuration option is set.
+
+If there is an error, returns the error, otherwise returns false.
=cut
sub apply_payments_and_credits {
- my $self = shift;
+ my( $self, %options ) = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -488,6 +677,13 @@ sub apply_payments_and_credits {
my @payments = grep { $_->unapplied > 0 } $self->cust_main->cust_pay;
my @credits = grep { $_->credited > 0 } $self->cust_main->cust_credit;
+ if ( $conf->exists('pkg-balances') ) {
+ # limit @payments & @credits to those w/ a pkgnum grepped from $self
+ my %pkgnums = map { $_ => 1 } map $_->pkgnum, $self->cust_bill_pkg;
+ @payments = grep { ! $_->pkgnum || $pkgnums{$_->pkgnum} } @payments;
+ @credits = grep { ! $_->pkgnum || $pkgnums{$_->pkgnum} } @credits;
+ }
+
while ( $self->owed > 0 and ( @payments || @credits ) ) {
my $app = '';
@@ -525,31 +721,42 @@ sub apply_payments_and_credits {
die "guru meditation #12 and 35";
}
+ my $unapp_amount;
if ( $app eq 'pay' ) {
my $payment = shift @payments;
-
- $app = new FS::cust_bill_pay {
- 'paynum' => $payment->paynum,
- 'amount' => sprintf('%.2f', min( $payment->unapplied, $self->owed ) ),
- };
+ $unapp_amount = $payment->unapplied;
+ $app = new FS::cust_bill_pay { 'paynum' => $payment->paynum };
+ $app->pkgnum( $payment->pkgnum )
+ if $conf->exists('pkg-balances') && $payment->pkgnum;
} elsif ( $app eq 'credit' ) {
my $credit = shift @credits;
-
- $app = new FS::cust_credit_bill {
- 'crednum' => $credit->crednum,
- 'amount' => sprintf('%.2f', min( $credit->credited, $self->owed ) ),
- };
+ $unapp_amount = $credit->credited;
+ $app = new FS::cust_credit_bill { 'crednum' => $credit->crednum };
+ $app->pkgnum( $credit->pkgnum )
+ if $conf->exists('pkg-balances') && $credit->pkgnum;
} else {
die "guru meditation #12 and 35";
}
+ my $owed;
+ if ( $conf->exists('pkg-balances') && $app->pkgnum ) {
+ warn "owed_pkgnum ". $app->pkgnum;
+ $owed = $self->owed_pkgnum($app->pkgnum);
+ } else {
+ $owed = $self->owed;
+ }
+ next unless $owed > 0;
+
+ warn "min ( $unapp_amount, $owed )\n" if $DEBUG;
+ $app->amount( sprintf('%.2f', min( $unapp_amount, $owed ) ) );
+
$app->invnum( $self->invnum );
- my $error = $app->insert;
+ my $error = $app->insert(%options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "Error inserting ". $app->table. " record: $error";
@@ -585,6 +792,10 @@ text attachment arrayref, optional
email subject, optional
+=item notice_name
+
+notice name instead of "Invoice", optional
+
=back
Returns an argument list to be passed to L<FS::Misc::send_email>.
@@ -605,11 +816,19 @@ sub generate_email {
'subject' => (($args{'subject'}) ? $args{'subject'} : 'Invoice'),
);
+ my %opt = (
+ 'unsquelch_cdr' => $conf->exists('voip-cdr_email'),
+ 'template' => $args{'template'},
+ 'notice_name' => ( $args{'notice_name'} || 'Invoice' ),
+ );
+
+ my $cust_main = $self->cust_main;
+
if (ref($args{'to'}) eq 'ARRAY') {
$return{'to'} = $args{'to'};
} else {
$return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ }
- $self->cust_main->invoicing_list
+ $cust_main->invoicing_list
];
}
@@ -643,7 +862,7 @@ sub generate_email {
if ( ref($args{'print_text'}) eq 'ARRAY' ) {
$data = $args{'print_text'};
} else {
- $data = [ $self->print_text('', $args{'template'}) ];
+ $data = [ $self->print_text(\%opt) ];
}
}
@@ -660,21 +879,22 @@ sub generate_email {
my $from = $1 || 'example.com';
my $content_id = join('.', rand()*(2**32), $$, time). "\@$from";
- my $path = "$FS::UID::conf_dir/conf.$FS::UID::datasrc";
- my $file;
+ my $logo;
+ my $agentnum = $cust_main->agentnum;
if ( defined($args{'template'}) && length($args{'template'})
- && -e "$path/logo_". $args{'template'}. ".png"
+ && $conf->exists( 'logo_'. $args{'template'}. '.png', $agentnum )
)
{
- $file = "$path/logo_". $args{'template'}. ".png";
+ $logo = 'logo_'. $args{'template'}. '.png';
} else {
- $file = "$path/logo.png";
+ $logo = "logo.png";
}
+ my $image_data = $conf->config_binary( $logo, $agentnum);
my $image = build MIME::Entity
'Type' => 'image/png',
'Encoding' => 'base64',
- 'Path' => $file,
+ 'Data' => $image_data,
'Filename' => 'logo.png',
'Content-ID' => "<$content_id>",
;
@@ -689,7 +909,7 @@ sub generate_email {
' </title>',
' </head>',
' <body bgcolor="#e8e8e8">',
- $self->print_html('', $args{'template'}, $content_id),
+ $self->print_html({ 'cid'=>$content_id, %opt }),
' </body>',
'</html>',
],
@@ -697,6 +917,21 @@ sub generate_email {
#'Filename' => 'invoice.pdf',
);
+ my @otherparts = ();
+ if ( $cust_main->email_csv_cdr ) {
+
+ push @otherparts, build MIME::Entity
+ 'Type' => 'text/csv',
+ 'Encoding' => '7bit',
+ 'Data' => [ map { "$_\n" }
+ $self->call_details('prepend_billed_number' => 1)
+ ],
+ 'Disposition' => 'attachment',
+ 'Filename' => 'usage-'. $self->invnum. '.csv',
+ ;
+
+ }
+
if ( $conf->exists('invoice_email_pdf') ) {
#attaching pdf too:
@@ -722,9 +957,9 @@ sub generate_email {
$related->add_part($image);
- my $pdf = build MIME::Entity $self->mimebuild_pdf('', $args{'template'});
+ my $pdf = build MIME::Entity $self->mimebuild_pdf(\%opt);
- $return{'mimeparts'} = [ $related, $pdf ];
+ $return{'mimeparts'} = [ $related, $pdf, @otherparts ];
} else {
@@ -736,7 +971,7 @@ sub generate_email {
# image/png
$return{'content-type'} = 'multipart/related';
- $return{'mimeparts'} = [ $alternative, $image ];
+ $return{'mimeparts'} = [ $alternative, $image, @otherparts ];
$return{'type'} = 'multipart/alternative'; #Content-Type of first part...
#$return{'disposition'} = 'inline';
@@ -750,7 +985,7 @@ sub generate_email {
#mime parts arguments a la MIME::Entity->build().
$return{'mimeparts'} = [
- { $self->mimebuild_pdf('', $args{'template'}) }
+ { $self->mimebuild_pdf(\%opt) }
];
}
@@ -770,7 +1005,7 @@ sub generate_email {
if ( ref($args{'print_text'}) eq 'ARRAY' ) {
$return{'body'} = $args{'print_text'};
} else {
- $return{'body'} = [ $self->print_text('', $args{'template'}) ];
+ $return{'body'} = [ $self->print_text(\%opt) ];
}
}
@@ -795,26 +1030,31 @@ sub mimebuild_pdf {
'Encoding' => 'base64',
'Data' => [ $self->print_pdf(@_) ],
'Disposition' => 'attachment',
- 'Filename' => 'invoice.pdf',
+ 'Filename' => 'invoice-'. $self->invnum. '.pdf',
);
}
-=item send [ TEMPLATENAME [ , AGENTNUM [ , INVOICE_FROM ] ] ]
+=item send HASHREF | [ TEMPLATE [ , AGENTNUM [ , INVOICE_FROM [ , AMOUNT ] ] ] ]
Sends this invoice to the destinations configured for this customer: sends
email, prints and/or faxes. See L<FS::cust_main_invoice>.
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+Options can be passed as a hashref (recommended) or as a list of up to
+four values for templatename, agentnum, invoice_from and amount.
+
+I<template>, if specified, is the name of a suffix for alternate invoices.
-AGENTNUM, if specified, means that this invoice will only be sent for customers
+I<agentnum>, if specified, means that this invoice will only be sent for customers
of the specified agent or agent(s). AGENTNUM can be a scalar agentnum (for a
single agent) or an arrayref of agentnums.
-INVOICE_FROM, if specified, overrides the default email invoice From: address.
+I<invoice_from>, if specified, overrides the default email invoice From: address.
-AMOUNT, if specified, only sends the invoice if the total amount owed on this
+I<amount>, if specified, only sends the invoice if the total amount owed on this
invoice and all older invoices is greater than the specified amount.
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
sub queueable_send {
@@ -834,48 +1074,73 @@ sub queueable_send {
sub send {
my $self = shift;
- my $template = scalar(@_) ? shift : '';
- if ( scalar(@_) && $_[0] ) {
- my $agentnums = ref($_[0]) ? shift : [ shift ];
- return 'N/A' unless grep { $_ == $self->cust_main->agentnum } @$agentnums;
- }
- my $invoice_from =
- scalar(@_)
- ? shift
- : ( $self->_agent_invoice_from || #XXX should go away
- $conf->config('invoice_from', $self->cust_main->agentnum )
- );
+ my( $template, $invoice_from, $notice_name );
+ my $agentnums = '';
+ my $balance_over = 0;
- my $balance_over = ( scalar(@_) && $_[0] !~ /^\s*$/ ) ? shift : 0;
+ if ( ref($_[0]) ) {
+ my $opt = shift;
+ $template = $opt->{'template'} || '';
+ if ( $agentnums = $opt->{'agentnum'} ) {
+ $agentnums = [ $agentnums ] unless ref($agentnums);
+ }
+ $invoice_from = $opt->{'invoice_from'};
+ $balance_over = $opt->{'balance_over'} if $opt->{'balance_over'};
+ $notice_name = $opt->{'notice_name'};
+ } else {
+ $template = scalar(@_) ? shift : '';
+ if ( scalar(@_) && $_[0] ) {
+ $agentnums = ref($_[0]) ? shift : [ shift ];
+ }
+ $invoice_from = shift if scalar(@_);
+ $balance_over = shift if scalar(@_) && $_[0] !~ /^\s*$/;
+ }
+
+ return 'N/A' unless ! $agentnums
+ or grep { $_ == $self->cust_main->agentnum } @$agentnums;
return ''
unless $self->cust_main->total_owed_date($self->_date) > $balance_over;
+ $invoice_from ||= $self->_agent_invoice_from || #XXX should go away
+ $conf->config('invoice_from', $self->cust_main->agentnum );
+
+ my %opt = (
+ 'template' => $template,
+ 'invoice_from' => $invoice_from,
+ 'notice_name' => ( $notice_name || 'Invoice' ),
+ );
+
my @invoicing_list = $self->cust_main->invoicing_list;
- #$self->email_invoice($template, $invoice_from)
- $self->email($template, $invoice_from)
+ #$self->email_invoice(\%opt)
+ $self->email(\%opt)
if grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list or !@invoicing_list;
- #$self->print_invoice($template)
- $self->print($template)
+ #$self->print_invoice(\%opt)
+ $self->print(\%opt)
if grep { $_ eq 'POST' } @invoicing_list; #postal
- $self->fax_invoice($template)
+ $self->fax_invoice(\%opt)
if grep { $_ eq 'FAX' } @invoicing_list; #fax
'';
}
-=item email [ TEMPLATENAME [ , INVOICE_FROM ] ]
+=item email HASHREF | [ TEMPLATE [ , INVOICE_FROM ] ]
Emails this invoice.
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+Options can be passed as a hashref (recommended) or as a list of up to
+two values for templatename and invoice_from.
+
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<invoice_from>, if specified, overrides the default email invoice From: address.
-INVOICE_FROM, if specified, overrides the default email invoice From: address.
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
=cut
@@ -897,14 +1162,21 @@ sub queueable_email {
#sub email_invoice {
sub email {
my $self = shift;
- my $template = scalar(@_) ? shift : '';
- my $invoice_from =
- scalar(@_)
- ? shift
- : ( $self->_agent_invoice_from || #XXX should go away
- $conf->config('invoice_from', $self->cust_main->agentnum )
- );
+ my( $template, $invoice_from, $notice_name );
+ if ( ref($_[0]) ) {
+ my $opt = shift;
+ $template = $opt->{'template'} || '';
+ $invoice_from = $opt->{'invoice_from'};
+ $notice_name = $opt->{'notice_name'} || 'Invoice';
+ } else {
+ $template = scalar(@_) ? shift : '';
+ $invoice_from = shift if scalar(@_);
+ $notice_name = 'Invoice';
+ }
+
+ $invoice_from ||= $self->_agent_invoice_from || #XXX should go away
+ $conf->config('invoice_from', $self->cust_main->agentnum );
my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ }
$self->cust_main->invoicing_list;
@@ -916,10 +1188,11 @@ sub email {
my $error = send_email(
$self->generate_email(
- 'from' => $invoice_from,
- 'to' => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ],
- 'subject' => $subject,
- 'template' => $template,
+ 'from' => $invoice_from,
+ 'to' => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ],
+ 'subject' => $subject,
+ 'template' => $template,
+ 'notice_name' => $notice_name,
)
);
die "can't email invoice: $error\n" if $error;
@@ -945,48 +1218,98 @@ sub email_subject {
eval qq("$subject");
}
-=item lpr_data [ TEMPLATENAME ]
+=item lpr_data HASHREF | [ TEMPLATE ]
Returns the postscript or plaintext for this invoice as an arrayref.
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+Options can be passed as a hashref (recommended) or as a single optional value
+for template.
+
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
=cut
sub lpr_data {
- my( $self, $template) = @_;
- $conf->exists('invoice_latex')
- ? [ $self->print_ps('', $template) ]
- : [ $self->print_text('', $template) ];
+ my $self = shift;
+ my( $template, $notice_name );
+ if ( ref($_[0]) ) {
+ my $opt = shift;
+ $template = $opt->{'template'} || '';
+ $notice_name = $opt->{'notice_name'} || 'Invoice';
+ } else {
+ $template = scalar(@_) ? shift : '';
+ $notice_name = 'Invoice';
+ }
+
+ my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+ );
+
+ my $method = $conf->exists('invoice_latex') ? 'print_ps' : 'print_text';
+ [ $self->$method( \%opt ) ];
}
-=item print [ TEMPLATENAME ]
+=item print HASHREF | [ TEMPLATE ]
Prints this invoice.
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+Options can be passed as a hashref (recommended) or as a single optional
+value for template.
+
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
=cut
#sub print_invoice {
sub print {
my $self = shift;
- my $template = scalar(@_) ? shift : '';
+ my( $template, $notice_name );
+ if ( ref($_[0]) ) {
+ my $opt = shift;
+ $template = $opt->{'template'} || '';
+ $notice_name = $opt->{'notice_name'} || 'Invoice';
+ } else {
+ $template = scalar(@_) ? shift : '';
+ $notice_name = 'Invoice';
+ }
- do_print $self->lpr_data($template);
+ my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+ );
+
+ do_print $self->lpr_data(\%opt);
}
-=item fax_invoice [ TEMPLATENAME ]
+=item fax_invoice HASHREF | [ TEMPLATE ]
Faxes this invoice.
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+Options can be passed as a hashref (recommended) or as a single optional
+value for template.
+
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
=cut
sub fax_invoice {
my $self = shift;
- my $template = scalar(@_) ? shift : '';
+ my( $template, $notice_name );
+ if ( ref($_[0]) ) {
+ my $opt = shift;
+ $template = $opt->{'template'} || '';
+ $notice_name = $opt->{'notice_name'} || 'Invoice';
+ } else {
+ $template = scalar(@_) ? shift : '';
+ $notice_name = 'Invoice';
+ }
die 'FAX invoice destination not (yet?) supported with plain text invoices.'
unless $conf->exists('invoice_latex');
@@ -994,7 +1317,12 @@ sub fax_invoice {
my $dialstring = $self->cust_main->getfield('fax');
#Check $dialstring?
- my $error = send_fax( 'docdata' => $self->lpr_data($template),
+ my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+ );
+
+ my $error = send_fax( 'docdata' => $self->lpr_data(\%opt),
'dialstring' => $dialstring,
);
die $error if $error;
@@ -1456,11 +1784,9 @@ sub print_csv {
} else { #pkgnum tax
next unless $cust_bill_pkg->setup != 0;
- my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc')
- ? ( $cust_bill_pkg->itemdesc || 'Tax' )
- : 'Tax';
- ($pkg, $setup, $recur, $sdate, $edate) =
- ( $itemdesc, sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' );
+ $pkg = $cust_bill_pkg->desc;
+ $setup = sprintf('%10.2f', $cust_bill_pkg->setup );
+ ( $sdate, $edate ) = ( '', '' );
}
$csv->combine(
@@ -1600,28 +1926,45 @@ sub _agent_invoice_from {
$self->cust_main->agent_invoice_from;
}
-=item print_text [ TIME [ , TEMPLATE ] ]
+=item print_text HASHREF | [ TIME [ , TEMPLATE [ , OPTION => VALUE ... ] ] ]
Returns an text invoice, as a list of lines.
-TIME an optional value used to control the printing of overdue messages. The
+Options can be passed as a hashref (recommended) or as a list of time, template
+and then any key/value pairs for any other options.
+
+I<time>, if specified, is used to control the printing of overdue messages. The
default is now. It isn't the date of the invoice; that's the `_date' field.
It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
sub print_text {
- my( $self, $today, $template ) = @_;
+ my $self = shift;
+ my( $today, $template, %opt );
+ if ( ref($_[0]) ) {
+ %opt = %{ shift() };
+ $today = delete($opt{'time'}) || '';
+ $template = delete($opt{template}) || '';
+ } else {
+ ( $today, $template, %opt ) = @_;
+ }
my %params = ( 'format' => 'template' );
$params{'time'} = $today if $today;
$params{'template'} = $template if $template;
+ $params{$_} = $opt{$_}
+ foreach grep $opt{$_}, qw( unsquealch_cdr notice_name );
$self->print_generic( %params );
}
-=item print_latex [ TIME [ , TEMPLATE ] ]
+=item print_latex HASHREF | [ TIME [ , TEMPLATE [ , OPTION => VALUE ... ] ] ]
Internal method - returns a filename of a filled-in LaTeX template for this
invoice (Note: add ".tex" to get the actual filename), and a filename of
@@ -1629,19 +1972,36 @@ an associated logo (with the .eps extension included).
See print_ps and print_pdf for methods that return PostScript and PDF output.
-TIME an optional value used to control the printing of overdue messages. The
+Options can be passed as a hashref (recommended) or as a list of time, template
+and then any key/value pairs for any other options.
+
+I<time>, if specified, is used to control the printing of overdue messages. The
default is now. It isn't the date of the invoice; that's the `_date' field.
It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
sub print_latex {
- my( $self, $today, $template ) = @_;
+ my $self = shift;
+ my( $today, $template, %opt );
+ if ( ref($_[0]) ) {
+ %opt = %{ shift() };
+ $today = delete($opt{'time'}) || '';
+ $template = delete($opt{template}) || '';
+ } else {
+ ( $today, $template, %opt ) = @_;
+ }
my %params = ( 'format' => 'latex' );
$params{'time'} = $today if $today;
$params{'template'} = $template if $template;
+ $params{$_} = $opt{$_}
+ foreach grep $opt{$_}, qw( unsquealch_cdr notice_name );
$template ||= $self->_agent_template;
@@ -1679,7 +2039,7 @@ sub print_latex {
}
-=item print_generic OPTIONS_HASH
+=item print_generic OPTION => VALUE ...
Internal method - returns a filled-in template for this invoice as a scalar.
@@ -1701,15 +2061,17 @@ cid -
unsquelch_cdr - overrides any per customer cdr squelching when true
+notice_name - overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
#what's with all the sprintf('%10.2f')'s in here? will it cause any
-# (alignment?) problems to change them all to '%.2f' ?
+# (alignment in text invoice?) problems to change them all to '%.2f' ?
sub print_generic {
my( $self, %params ) = @_;
my $today = $params{today} ? $params{today} : time;
- warn "FS::cust_bill::print_generic called on $self with suffix $params{template}\n"
+ warn "$me print_generic called on $self with suffix $params{template}\n"
if $DEBUG;
my $format = $params{format};
@@ -1761,6 +2123,7 @@ sub print_generic {
'smallfooter' => sub { map "$_", @_ },
'returnaddress' => sub { map "$_", @_ },
'coupon' => sub { map "$_", @_ },
+ 'summary' => sub { map "$_", @_ },
},
'html' => {
'notes' =>
@@ -1794,6 +2157,7 @@ sub print_generic {
} @_
},
'coupon' => sub { "" },
+ 'summary' => sub { "" },
},
'template' => {
'notes' =>
@@ -1824,6 +2188,7 @@ sub print_generic {
} @_
},
'coupon' => sub { "" },
+ 'summary' => sub { "" },
},
);
@@ -1909,37 +2274,53 @@ sub print_generic {
}
my %invoice_data = (
+
+ #invoice from info
'company_name' => scalar( $conf->config('company_name', $self->cust_main->agentnum) ),
'company_address' => join("\n", $conf->config('company_address', $self->cust_main->agentnum) ). "\n",
- 'custnum' => $cust_main->display_custnum,
+ 'returnaddress' => $returnaddress,
+ 'agent' => &$escape_function($cust_main->agent->agent),
+
+ #invoice info
'invnum' => $self->invnum,
'date' => time2str($date_format, $self->_date),
'today' => time2str('%b %o, %Y', $today),
- 'agent' => &$escape_function($cust_main->agent->agent),
- 'agent_custid' => &$escape_function($cust_main->agent_custid),
- 'payname' => &$escape_function($cust_main->payname),
- 'company' => &$escape_function($cust_main->company),
- 'address1' => &$escape_function($cust_main->address1),
- 'address2' => &$escape_function($cust_main->address2),
- 'city' => &$escape_function($cust_main->city),
- 'state' => &$escape_function($cust_main->state),
- 'zip' => &$escape_function($cust_main->zip),
- 'fax' => &$escape_function($cust_main->fax),
- 'returnaddress' => $returnaddress,
- #'quantity' => 1,
'terms' => $self->terms,
'template' => $template, #params{'template'},
- #'notes' => join("\n", $conf->config('invoice_latexnotes') ),
- # better hang on to conf_dir for a while
- 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
- 'page' => 1,
- 'total_pages' => 1,
+ 'notice_name' => ($params{'notice_name'} || 'Invoice'),#escape_function?
'current_charges' => sprintf("%.2f", $self->charged),
'duedate' => $self->due_date2str('%m/%d/%Y'), #date_format?
+
+ #customer info
+ 'custnum' => $cust_main->display_custnum,
+ 'agent_custid' => &$escape_function($cust_main->agent_custid),
+ ( map { $_ => &$escape_function($cust_main->$_()) } qw(
+ payname company address1 address2 city state zip fax
+ )),
+
+ #global config
'ship_enable' => $conf->exists('invoice-ship_address'),
'unitprices' => $conf->exists('invoice-unitprice'),
+ 'smallernotes' => $conf->exists('invoice-smallernotes'),
+ 'smallerfooter' => $conf->exists('invoice-smallerfooter'),
+
+ # better hang on to conf_dir for a while (for old templates)
+ 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
+
+ #these are only used when doing paged plaintext
+ 'page' => 1,
+ 'total_pages' => 1,
+
);
+ $invoice_data{finance_section} = '';
+ if ( $conf->config('finance_pkgclass') ) {
+ my $pkg_class =
+ qsearchs('pkg_class', { classnum => $conf->config('finance_pkgclass') });
+ $invoice_data{finance_section} = $pkg_class->categoryname;
+ }
+ $invoice_data{finance_amount} = '0.00';
+
my $countrydefault = $conf->config('countrydefault') || 'US';
my $prefix = $cust_main->has_ship_address ? 'ship_' : '';
foreach ( qw( contact company address1 address2 city state zip country fax) ){
@@ -1986,18 +2367,29 @@ sub print_generic {
# my( $cr_total, @cr_cust_credit ) = $self->cust_credit; #credits
#my $balance_due = $self->owed + $pr_total - $cr_total;
my $balance_due = $self->owed + $pr_total;
+ $invoice_data{'true_previous_balance'} = sprintf("%.2f", ($self->previous_balance || 0) );
+ $invoice_data{'balance_adjustments'} = sprintf("%.2f", ($self->previous_balance || 0) - ($self->billing_balance || 0) );
$invoice_data{'previous_balance'} = sprintf("%.2f", $pr_total);
$invoice_data{'balance'} = sprintf("%.2f", $balance_due);
+ my $agentnum = $self->cust_main->agentnum;
+
+ my $summarypage = '';
+ if ( $conf->exists('invoice_usesummary', $agentnum) ) {
+ $summarypage = 1;
+ }
+ $invoice_data{'summarypage'} = $summarypage;
+
#do variable substitution in notes, footer, smallfooter
foreach my $include (qw( notes footer smallfooter coupon )) {
my $inc_file = $conf->key_orbase("invoice_${format}$include", $template);
my @inc_src;
- if ( $conf->exists($inc_file) && length( $conf->config($inc_file) ) ) {
+ if ( $conf->exists($inc_file, $agentnum)
+ && length( $conf->config($inc_file, $agentnum) ) ) {
- @inc_src = $conf->config($inc_file);
+ @inc_src = $conf->config($inc_file, $agentnum);
} else {
@@ -2009,7 +2401,7 @@ sub print_generic {
s/--\@\]/$delimiters{$format}[1]/g;
$_;
}
- &$convert_map( $conf->config($inc_file) );
+ &$convert_map( $conf->config($inc_file, $agentnum) );
}
@@ -2047,6 +2439,7 @@ sub print_generic {
'template' => '',
);
my $other_money_char = $other_money_chars{$format};
+ $invoice_data{'dollar'} = $other_money_char;
my @detail_items = ();
my @total_items = ();
@@ -2057,56 +2450,66 @@ sub print_generic {
$invoice_data{'total_items'} = \@total_items;
$invoice_data{'buf'} = \@buf;
$invoice_data{'sections'} = \@sections;
-
+
my $previous_section = { 'description' => 'Previous Charges',
'subtotal' => $other_money_char.
sprintf('%.2f', $pr_total),
+ 'summarized' => $summarypage ? 'Y' : '',
};
my $taxtotal = 0;
my $tax_section = { 'description' => 'Taxes, Surcharges, and Fees',
- 'subtotal' => $taxtotal }; # adjusted below
+ 'subtotal' => $taxtotal, # adjusted below
+ 'summarized' => $summarypage ? 'Y' : '',
+ };
my $adjusttotal = 0;
my $adjust_section = { 'description' => 'Credits, Payments, and Adjustments',
- 'subtotal' => 0 }; # adjusted below
+ 'subtotal' => 0, # adjusted below
+ 'summarized' => $summarypage ? 'Y' : '',
+ };
my $unsquelched = $params{unsquelch_cdr} || $cust_main->squelch_cdr ne 'Y';
my $multisection = $conf->exists('invoice_sections', $cust_main->agentnum);
my $late_sections = [];
if ( $multisection ) {
- push @sections, $self->_items_sections( $late_sections );
+ push @sections,
+ $self->_items_sections( $late_sections, $summarypage, $escape_function );
}else{
push @sections, { 'description' => '', 'subtotal' => '' };
}
- foreach my $line_item ( $conf->exists('disable_previous_balance')
- ? ()
- : $self->_items_previous
- )
+ unless ( $conf->exists('disable_previous_balance')
+ || $conf->exists('previous_balance-summary_only')
+ )
{
- my $detail = {
- ext_description => [],
- };
- $detail->{'ref'} = $line_item->{'pkgnum'};
- $detail->{'quantity'} = 1;
- $detail->{'section'} = $previous_section;
- $detail->{'description'} = &$escape_function($line_item->{'description'});
- if ( exists $line_item->{'ext_description'} ) {
- @{$detail->{'ext_description'}} = map {
- &$escape_function($_);
- } @{$line_item->{'ext_description'}};
+
+ foreach my $line_item ( $self->_items_previous ) {
+
+ my $detail = {
+ ext_description => [],
+ };
+ $detail->{'ref'} = $line_item->{'pkgnum'};
+ $detail->{'quantity'} = 1;
+ $detail->{'section'} = $previous_section;
+ $detail->{'description'} = &$escape_function($line_item->{'description'});
+ if ( exists $line_item->{'ext_description'} ) {
+ @{$detail->{'ext_description'}} = map {
+ &$escape_function($_);
+ } @{$line_item->{'ext_description'}};
+ }
+ $detail->{'amount'} = ( $old_latex ? '' : $money_char).
+ $line_item->{'amount'};
+ $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
+
+ push @detail_items, $detail;
+ push @buf, [ $detail->{'description'},
+ $money_char. sprintf("%10.2f", $line_item->{'amount'}),
+ ];
}
- $detail->{'amount'} = ( $old_latex ? '' : $money_char).
- $line_item->{'amount'};
- $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
-
- push @detail_items, $detail;
- push @buf, [ $detail->{'description'},
- $money_char. sprintf("%10.2f", $line_item->{'amount'}),
- ];
+
}
-
+
if ( @pr_cust_bill && !$conf->exists('disable_previous_balance') ) {
push @buf, ['','-----------'];
push @buf, [ 'Total Previous Balance',
@@ -2116,6 +2519,10 @@ sub print_generic {
foreach my $section (@sections, @$late_sections) {
+ $invoice_data{finance_amount} = sprintf('%.2f', $section->{'subtotal'} )
+ if ( $invoice_data{finance_section} &&
+ $section->{'description'} eq $invoice_data{finance_section} );
+
$section->{'subtotal'} = $other_money_char.
sprintf('%.2f', $section->{'subtotal'})
if $multisection;
@@ -2132,6 +2539,7 @@ sub print_generic {
$options{'escape_function'} = $escape_function;
$options{'format_function'} = sub { () } unless $unsquelched;
$options{'unsquelched'} = $unsquelched;
+ $options{'summary_page'} = $summarypage;
foreach my $line_item ( $self->_items_pkg(%options) ) {
my $detail = {
@@ -2170,6 +2578,9 @@ sub print_generic {
}
+ $invoice_data{current_less_finance} =
+ sprintf('%.2f', $self->charged - $invoice_data{finance_amount} );
+
if ( $multisection && !$conf->exists('disable_previous_balance') ) {
unshift @sections, $previous_section if $pr_total;
}
@@ -2226,7 +2637,7 @@ sub print_generic {
}
}
$invoice_data{'taxtotal'} = sprintf('%.2f', $taxtotal);
-
+
push @buf,['','-----------'];
push @buf,[( $conf->exists('disable_previous_balance')
? 'Total Charges'
@@ -2272,7 +2683,8 @@ sub print_generic {
# credits
my $credittotal = 0;
- foreach my $credit ( $self->_items_credits ) {
+ foreach my $credit ( $self->_items_credits('trim_len'=>60) ) {
+
my $total;
$total->{'total_item'} = &$escape_function($credit->{'description'});
$credittotal += $credit->{'amount'};
@@ -2289,24 +2701,16 @@ sub print_generic {
product_code => '',
section => $adjust_section,
};
- }else{
+ } else {
push @total_items, $total;
}
+
}
$invoice_data{'credittotal'} = sprintf('%.2f', $credittotal);
-
- # credits (again)
- foreach ( $self->cust_credited ) {
-
- #something more elaborate if $_->amount ne $_->cust_credit->credited ?
-
- my $reason = substr($_->cust_credit->reason,0,32);
- $reason .= '...' if length($reason) < length($_->cust_credit->reason);
- $reason = " ($reason) " if $reason;
- push @buf,[
- "Credit #". $_->crednum. " (". time2str("%x",$_->cust_credit->_date) .")". $reason,
- $money_char. sprintf("%10.2f",$_->amount)
- ];
+
+ #credits (again)
+ foreach my $credit ( $self->_items_credits('trim_len'=>32) ) {
+ push @buf, [ $credit->{'description'}, $money_char.$credit->{'amount'} ];
}
# payments
@@ -2348,7 +2752,11 @@ sub print_generic {
$total->{'total_item'} = &$embolden_function($self->balance_due_msg);
$total->{'total_amount'} =
&$embolden_function(
- $other_money_char. sprintf('%.2f', $self->owed + $pr_total )
+ $other_money_char. sprintf('%.2f', $summarypage
+ ? $self->charged +
+ $self->billing_balance
+ : $self->owed + $pr_total
+ )
);
if ( $multisection ) {
$adjust_section->{'posttotal'} = $total->{'total_item'}. ' '.
@@ -2367,6 +2775,49 @@ sub print_generic {
if $unsquelched;
}
+ my @includelist = ();
+ push @includelist, 'summary' if $summarypage;
+ foreach my $include ( @includelist ) {
+
+ my $inc_file = $conf->key_orbase("invoice_${format}$include", $template);
+ my @inc_src;
+
+ if ( length( $conf->config($inc_file, $agentnum) ) ) {
+
+ @inc_src = $conf->config($inc_file, $agentnum);
+
+ } else {
+
+ $inc_file = $conf->key_orbase("invoice_latex$include", $template);
+
+ my $convert_map = $convert_maps{$format}{$include};
+
+ @inc_src = map { s/\[\@--/$delimiters{$format}[0]/g;
+ s/--\@\]/$delimiters{$format}[1]/g;
+ $_;
+ }
+ &$convert_map( $conf->config($inc_file, $agentnum) );
+
+ }
+
+ my $inc_tt = new Text::Template (
+ TYPE => 'ARRAY',
+ SOURCE => [ map "$_\n", @inc_src ],
+ DELIMITERS => $delimiters{$format},
+ ) or die "Can't create new Text::Template object: $Text::Template::ERROR";
+
+ unless ( $inc_tt->compile() ) {
+ my $error = "Can't compile $inc_file template: $Text::Template::ERROR\n";
+ warn $error. "Template:\n". join('', map "$_\n", @inc_src);
+ die $error;
+ }
+
+ $invoice_data{$include} = $inc_tt->fill_in( HASH => \%invoice_data );
+
+ $invoice_data{$include} =~ s/\n+$//
+ if ($format eq 'latex');
+ }
+
$invoice_lines = 0;
my $wasfunc = 0;
foreach ( grep /invoice_lines\(\d*\)/, @invoice_template ) { #kludgy
@@ -2417,15 +2868,20 @@ sub print_generic {
}
}
-=item print_ps [ TIME [ , TEMPLATE ] ]
+=item print_ps HASHREF | [ TIME [ , TEMPLATE ] ]
Returns an postscript invoice, as a scalar.
-TIME an optional value used to control the printing of overdue messages. The
+Options can be passed as a hashref (recommended) or as a list of time, template
+and then any key/value pairs for any other options.
+
+I<time> an optional value used to control the printing of overdue messages. The
default is now. It isn't the date of the invoice; that's the `_date' field.
It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
sub print_ps {
@@ -2438,15 +2894,22 @@ sub print_ps {
$ps;
}
-=item print_pdf [ TIME [ , TEMPLATE ] ]
+=item print_pdf HASHREF | [ TIME [ , TEMPLATE ] ]
Returns an PDF invoice, as a scalar.
-TIME an optional value used to control the printing of overdue messages. The
+Options can be passed as a hashref (recommended) or as a list of time, template
+and then any key/value pairs for any other options.
+
+I<time> an optional value used to control the printing of overdue messages. The
default is now. It isn't the date of the invoice; that's the `_date' field.
It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
=cut
sub print_pdf {
@@ -2459,16 +2922,20 @@ sub print_pdf {
$pdf;
}
-=item print_html [ TIME [ , TEMPLATE [ , CID ] ] ]
+=item print_html HASHREF | [ TIME [ , TEMPLATE [ , CID ] ] ]
Returns an HTML invoice, as a scalar.
-TIME an optional value used to control the printing of overdue messages. The
+I<time> an optional value used to control the printing of overdue messages. The
default is now. It isn't the date of the invoice; that's the `_date' field.
It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
-CID is a MIME Content-ID used to create a "cid:" URL for the logo image, used
+I<template>, if specified, is the name of a suffix for alternate invoices.
+
+I<notice_name>, if specified, overrides "Invoice" as the name of the sent document (templates from 10/2009 or newer required)
+
+I<cid> is a MIME Content-ID used to create a "cid:" URL for the logo image, used
when emailing the invoice as part of a multipart/related MIME email.
=cut
@@ -2476,7 +2943,7 @@ when emailing the invoice as part of a multipart/related MIME email.
sub print_html {
my $self = shift;
my %params;
- if ( ref $_[0] ) {
+ if ( ref($_[0]) ) {
%params = %{ shift() };
}else{
$params{'time'} = shift;
@@ -2534,10 +3001,10 @@ sub _translate_old_latex_format {
$line_item_line =~ s/\$(\w+)/'. \$_tr_line->{$1}. '/g;
push @template, " \$OUT .= '$line_item_line';";
}
-
+
push @template, '}',
'--@]';
-
+ #' doh, gvim
} elsif ( $line =~ /^%%TotalDetails\s*$/ ) {
push @template, '[@--',
@@ -2571,14 +3038,15 @@ sub _translate_old_latex_format {
sub terms {
my $self = shift;
- #check for an invoice- specific override (eventually)
+ #check for an invoice-specific override
+ return $self->invoice_terms if $self->invoice_terms;
#check for a customer- specific override
- return $self->cust_main->invoice_terms
- if $self->cust_main->invoice_terms;
+ my $cust_main = $self->cust_main;
+ return $cust_main->invoice_terms if $cust_main->invoice_terms;
- #use configured default or default default
- $conf->config('invoice_default_terms') || 'Payable upon receipt';
+ #use configured default
+ $conf->config('invoice_default_terms') || '';
}
sub due_date {
@@ -2643,21 +3111,30 @@ sub _date_pretty {
sub _items_sections {
my $self = shift;
my $late = shift;
+ my $summarypage = shift;
+ my $escape = shift;
my %s = ();
my %l = ();
+ my %not_tax = ();
foreach my $cust_bill_pkg ( $self->cust_bill_pkg )
{
- if ( $cust_bill_pkg->pkgnum > 0 ) {
+
my $usage = $cust_bill_pkg->usage;
foreach my $display ($cust_bill_pkg->cust_bill_pkg_display) {
+ next if ( $display->summary && $summarypage );
+
my $desc = $display->section;
my $type = $display->type;
- if ( $display->post_total ) {
+ if ( $cust_bill_pkg->pkgnum > 0 ) {
+ $not_tax{$desc} = 1;
+ }
+
+ if ( $display->post_total && !$summarypage ) {
if (! $type || $type eq 'S') {
$l{$desc} += $cust_bill_pkg->setup
if ( $cust_bill_pkg->setup != 0 );
@@ -2701,16 +3178,29 @@ sub _items_sections {
}
- }
-
}
- push @$late, map { { 'description' => $_,
+ my %cache = map { $_->categoryname => $_ }
+ qsearch( 'pkg_category', {disabled => 'Y'} );
+ $cache{$_->categoryname} = $_
+ foreach qsearch( 'pkg_category', {disabled => ''} );
+
+ push @$late, map { { 'description' => &{$escape}($_),
'subtotal' => $l{$_},
'post_total' => 1,
- } } sort keys %l;
-
- map { {'description' => $_, 'subtotal' => $s{$_}} } sort keys %s;
+ } }
+ sort { $cache{$a}->weight <=> $cache{$b}->weight } keys %l;
+
+ map { { 'description' => &{$escape}($_),
+ 'subtotal' => $s{$_},
+ 'summarized' => $not_tax{$_} ? '' : 'Y',
+ 'tax_section' => $not_tax{$_} ? '' : 'Y',
+ } }
+ sort { $cache{$a}->weight <=> $cache{$b}->weight }
+ ( $summarypage
+ ? ( grep { exists($s{$_}) || !$cache{$_}->disabled } keys %cache )
+ : ( keys %s )
+ );
}
@@ -2792,22 +3282,33 @@ sub _items_cust_bill_pkg {
my $format_function = $opt{format_function} || '';
my $unsquelched = $opt{unsquelched} || '';
my $section = $opt{section}->{description} if $opt{section};
+ my $summary_page = $opt{summary_page} || '';
my @b = ();
+ my ($s, $r, $u) = ( undef, undef, undef );
foreach my $cust_bill_pkg ( @$cust_bill_pkg )
{
+
+ foreach ( $s, $r, $u ) {
+ if ( $_ && !$cust_bill_pkg->hidden ) {
+ $_->{amount} = sprintf( "%.2f", $_->{amount} ),
+ $_->{unit_amount} = sprintf( "%.2f", $_->{unit_amount} ),
+ push @b, { %$_ };
+ $_ = undef;
+ }
+ }
+
foreach my $display ( grep { defined($section)
? $_->section eq $section
: 1
}
+ grep { $_->summary || !$summary_page }
$cust_bill_pkg->cust_bill_pkg_display
)
{
my $type = $display->type;
- my $cust_pkg = $cust_bill_pkg->cust_pkg;
-
my $desc = $cust_bill_pkg->desc;
$desc = substr($desc, 0, 50). '...'
if $format eq 'latex' && length($desc) > 50;
@@ -2819,24 +3320,35 @@ sub _items_cust_bill_pkg {
if ( $cust_bill_pkg->pkgnum > 0 ) {
+ my $cust_pkg = $cust_bill_pkg->cust_pkg;
+
if ( $cust_bill_pkg->setup != 0 && (!$type || $type eq 'S') ) {
my $description = $desc;
$description .= ' Setup' if $cust_bill_pkg->recur != 0;
- my @d = map &{$escape_function}($_),
- $cust_pkg->h_labels_short($self->_date);
+ my @d = ();
+ push @d, map &{$escape_function}($_),
+ $cust_pkg->h_labels_short($self->_date)
+ unless $cust_pkg->part_pkg->hide_svc_detail
+ || $cust_bill_pkg->hidden;
push @d, $cust_bill_pkg->details(%details_opt)
if $cust_bill_pkg->recur == 0;
- push @b, {
- description => $description,
- #pkgpart => $part_pkg->pkgpart,
- pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $cust_bill_pkg->setup),
- unit_amount => sprintf("%.2f", $cust_bill_pkg->unitsetup),
- quantity => $cust_bill_pkg->quantity,
- ext_description => \@d,
+ if ( $cust_bill_pkg->hidden ) {
+ $s->{amount} += $cust_bill_pkg->setup;
+ $s->{unit_amount} += $cust_bill_pkg->unitsetup;
+ push @{ $s->{ext_description} }, @d;
+ } else {
+ $s = {
+ description => $description,
+ #pkgpart => $part_pkg->pkgpart,
+ pkgnum => $cust_bill_pkg->pkgnum,
+ amount => $cust_bill_pkg->setup,
+ unit_amount => $cust_bill_pkg->unitsetup,
+ quantity => $cust_bill_pkg->quantity,
+ ext_description => \@d,
+ };
};
}
@@ -2847,23 +3359,31 @@ sub _items_cust_bill_pkg {
{
my $is_summary = $display->summary;
- my $description = $is_summary ? "Usage charges" : $desc;
+ my $description = ($is_summary && $type && $type eq 'U')
+ ? "Usage charges" : $desc;
unless ( $conf->exists('disable_line_item_date_ranges') ) {
$description .= " (" . time2str("%x", $cust_bill_pkg->sdate).
" - ". time2str("%x", $cust_bill_pkg->edate). ")";
}
+ my @d = ();
+
#at least until cust_bill_pkg has "past" ranges in addition to
#the "future" sdate/edate ones... see #3032
- my @d = ();
+ my @dates = ( $self->_date );
+ my $prev = $cust_bill_pkg->previous_cust_bill_pkg;
+ push @dates, $prev->sdate if $prev;
+
push @d, map &{$escape_function}($_),
- $cust_pkg->h_labels_short($self->_date)
- #$cust_bill_pkg->edate,
- #$cust_bill_pkg->sdate),
- ;
-
- @d = () if ($cust_bill_pkg->itemdesc || $is_summary);
+ $cust_pkg->h_labels_short(@dates)
+ #$cust_bill_pkg->edate,
+ #$cust_bill_pkg->sdate)
+ unless $cust_pkg->part_pkg->hide_svc_detail
+ || $cust_bill_pkg->itemdesc
+ || $cust_bill_pkg->hidden
+ || $is_summary && $type && $type eq 'U';
+
push @d, $cust_bill_pkg->details(%details_opt)
unless ($is_summary || $type && $type eq 'R');
@@ -2876,17 +3396,45 @@ sub _items_cust_bill_pkg {
$amount = $cust_bill_pkg->usage;
}
- push @b, {
- description => $description,
- #pkgpart => $part_pkg->pkgpart,
- pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $amount),
- unit_amount => sprintf("%.2f", $cust_bill_pkg->unitrecur),
- quantity => $cust_bill_pkg->quantity,
- ext_description => \@d,
- } unless ( $type eq 'U' && ! $amount );
+ if ( !$type || $type eq 'R' ) {
+
+ if ( $cust_bill_pkg->hidden ) {
+ $r->{amount} += $amount;
+ $r->{unit_amount} += $cust_bill_pkg->unitrecur;
+ push @{ $r->{ext_description} }, @d;
+ } else {
+ $r = {
+ description => $description,
+ #pkgpart => $part_pkg->pkgpart,
+ pkgnum => $cust_bill_pkg->pkgnum,
+ amount => $amount,
+ unit_amount => $cust_bill_pkg->unitrecur,
+ quantity => $cust_bill_pkg->quantity,
+ ext_description => \@d,
+ };
+ }
+
+ } elsif ( $amount ) { # && $type eq 'U'
+
+ if ( $cust_bill_pkg->hidden ) {
+ $u->{amount} += $amount;
+ $u->{unit_amount} += $cust_bill_pkg->unitrecur;
+ push @{ $u->{ext_description} }, @d;
+ } else {
+ $u = {
+ description => $description,
+ #pkgpart => $part_pkg->pkgpart,
+ pkgnum => $cust_bill_pkg->pkgnum,
+ amount => $amount,
+ unit_amount => $cust_bill_pkg->unitrecur,
+ quantity => $cust_bill_pkg->quantity,
+ ext_description => \@d,
+ };
+ }
- }
+ }
+
+ } # recurring or usage with recurring charge
} else { #pkgnum tax or one-shot line item (??)
@@ -2911,12 +3459,21 @@ sub _items_cust_bill_pkg {
}
+ foreach ( $s, $r, $u ) {
+ if ( $_ ) {
+ $_->{amount} = sprintf( "%.2f", $_->{amount} ),
+ $_->{unit_amount} = sprintf( "%.2f", $_->{unit_amount} ),
+ push @b, { %$_ };
+ }
+ }
+
@b;
}
sub _items_credits {
- my $self = shift;
+ my( $self, %opt ) = @_;
+ my $trim_len = $opt{'trim_len'} || 60;
my @b;
#credits
@@ -2924,10 +3481,10 @@ sub _items_credits {
#something more elaborate if $_->amount ne $_->cust_credit->credited ?
- my $reason = $_->cust_credit->reason;
- #my $reason = substr($_->cust_credit->reason,0,32);
- #$reason .= '...' if length($reason) < length($_->cust_credit->reason);
+ my $reason = substr($_->cust_credit->reason, 0, $trim_len);
+ $reason .= '...' if length($reason) < length($_->cust_credit->reason);
$reason = " ($reason) " if $reason;
+
push @b, {
#'description' => 'Credit ref\#'. $_->crednum.
# " (". time2str("%x",$_->cust_credit->_date) .")".
@@ -2937,12 +3494,6 @@ sub _items_credits {
'amount' => sprintf("%.2f",$_->amount),
};
}
- #foreach ( @cr_cust_credit ) {
- # push @buf,[
- # "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
- # $money_char. sprintf("%10.2f",$_->credited)
- # ];
- #}
@b;
@@ -2968,6 +3519,38 @@ sub _items_payments {
}
+=item call_details [ OPTION => VALUE ... ]
+
+Returns an array of CSV strings representing the call details for this invoice
+The only option available is the boolean prepend_billed_number
+
+=cut
+
+sub call_details {
+ my ($self, %opt) = @_;
+
+ my $format_function = sub { shift };
+
+ if ($opt{prepend_billed_number}) {
+ $format_function = sub {
+ my $detail = shift;
+ my $row = shift;
+
+ $row->amount ? $row->phonenum. ",". $detail : '"Billed number",'. $detail;
+
+ };
+ }
+
+ my @details = map { $_->details( 'format_function' => $format_function,
+ 'escape_function' => sub{ return() },
+ )
+ }
+ grep { $_->pkgnum }
+ $self->cust_bill_pkg;
+ my $header = $details[0];
+ ( $header, grep { $_ ne $header } @details );
+}
+
=back
diff --git a/FS/FS/cust_bill_ApplicationCommon.pm b/FS/FS/cust_bill_ApplicationCommon.pm
index af7e087..7449679 100644
--- a/FS/FS/cust_bill_ApplicationCommon.pm
+++ b/FS/FS/cust_bill_ApplicationCommon.pm
@@ -1,7 +1,7 @@
package FS::cust_bill_ApplicationCommon;
use strict;
-use vars qw( @ISA $DEBUG $me );
+use vars qw( @ISA $DEBUG $me $skip_apply_to_lineitems_hack );
use List::Util qw(min);
use FS::Schema qw( dbdef );
use FS::Record qw( qsearch qsearchs dbh );
@@ -11,6 +11,8 @@ use FS::Record qw( qsearch qsearchs dbh );
$DEBUG = 0;
$me = '[FS::cust_bill_ApplicationCommon]';
+$skip_apply_to_lineitems_hack = 0;
+
=head1 NAME
FS::cust_bill_ApplicationCommon - Base class for bill application classes
@@ -54,7 +56,7 @@ sub insert {
my $dbh = dbh;
my $error = $self->SUPER::insert(@_)
- || $self->apply_to_lineitems;
+ || $self->apply_to_lineitems(@_);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -111,10 +113,15 @@ Auto-applies this invoice application to specific line items, if possible.
=cut
sub apply_to_lineitems {
- my $self = shift;
+ #my $self = shift;
+ my( $self, %options ) = @_;
+
+ return '' if $skip_apply_to_lineitems_hack;
my @apply = ();
+ my $conf = new FS::Conf;
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
@@ -127,6 +134,8 @@ sub apply_to_lineitems {
my $dbh = dbh;
my @open = $self->cust_bill->open_cust_bill_pkg; #FOR UPDATE...?
+ @open = grep { $_->pkgnum == $self->pkgnum } @open
+ if $conf->exists('pkg-balances') && $self->pkgnum;
warn "$me ". scalar(@open). " open line items for invoice ".
$self->cust_bill->invnum. ": ". join(', ', @open). "\n"
if $DEBUG;
@@ -314,7 +323,7 @@ sub apply_to_lineitems {
'sdate' => $cust_bill_pkg->sdate,
'edate' => $cust_bill_pkg->edate,
});
- my $error = $application->insert;
+ my $error = $application->insert(%options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
diff --git a/FS/FS/cust_bill_pay.pm b/FS/FS/cust_bill_pay.pm
index b7ba2b7..831d7f2 100644
--- a/FS/FS/cust_bill_pay.pm
+++ b/FS/FS/cust_bill_pay.pm
@@ -7,6 +7,7 @@ use FS::cust_main_Mixin;
use FS::cust_bill_ApplicationCommon;
use FS::cust_bill;
use FS::cust_pay;
+use FS::cust_pkg;
@ISA = qw( FS::cust_main_Mixin FS::cust_bill_ApplicationCommon );
@@ -121,6 +122,7 @@ sub check {
|| $self->ut_foreign_key('invnum', 'cust_bill', 'invnum' )
|| $self->ut_numbern('_date')
|| $self->ut_money('amount')
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
;
return $error if $error;
@@ -148,6 +150,25 @@ sub cust_pay {
qsearchs( 'cust_pay', { 'paynum' => $self->paynum } );
}
+=item send_receipt HASHREF | OPTION => VALUE ...
+
+
+Sends a payment receipt for the associated payment, against this specific
+invoice. If there is an error, returns the error, otherwise returns false.
+
+See L<FS::cust_pay/send_receipt>.
+
+=cut
+
+sub send_receipt {
+ my $self = shift;
+ my $opt = ref($_[0]) ? shift : { @_ };
+ $self->cust_pay->send_receipt(
+ 'cust_bill' => $self->cust_bill,
+ %$opt,
+ );
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill_pay_pkg.pm b/FS/FS/cust_bill_pay_pkg.pm
index cdbace9..48c4364 100644
--- a/FS/FS/cust_bill_pay_pkg.pm
+++ b/FS/FS/cust_bill_pay_pkg.pm
@@ -2,7 +2,10 @@ package FS::cust_bill_pay_pkg;
use strict;
use vars qw( @ISA );
+use FS::Conf;
use FS::Record qw( qsearch qsearchs );
+use FS::cust_bill_pay;
+use FS::cust_bill_pkg;
@ISA = qw(FS::Record);
@@ -77,7 +80,39 @@ otherwise returns false.
=cut
-# the insert method can be inherited from FS::Record
+sub insert {
+ my($self, %options) = @_;
+
+ #local $SIG{HUP} = 'IGNORE';
+ #local $SIG{INT} = 'IGNORE';
+ #local $SIG{QUIT} = 'IGNORE';
+ #local $SIG{TERM} = 'IGNORE';
+ #local $SIG{TSTP} = 'IGNORE';
+ #local $SIG{PIPE} = 'IGNORE';
+ #
+ #my $oldAutoCommit = $FS::UID::AutoCommit;
+ #local $FS::UID::AutoCommit = 0;
+ #my $dbh = dbh;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ #$dbh->rollback if $oldAutoCommit;
+ return "error inserting $self: $error";
+ }
+
+ #payment receipt
+ my $conf = new FS::Conf;
+ my $trigger = $conf->config('payment_receipt-trigger') || 'cust_pay';
+ if ( $trigger eq 'cust_bill_pay_pkg' ) {
+ my $error = $self->send_receipt(
+ 'manual' => $options{'manual'},
+ );
+ warn "can't send payment receipt/statement: $error" if $error;
+ }
+
+ '';
+
+}
=item delete
@@ -124,6 +159,47 @@ sub check {
$self->SUPER::check;
}
+=item cust_bill_pay
+
+Returns the FS::cust_bill_pay object (payment application to the overall
+invoice).
+
+=cut
+
+sub cust_bill_pay {
+ my $self = shift;
+ qsearchs('cust_bill_pay', { 'billpaynum' => $self->billpaynum } );
+}
+
+=item cust_bill_pkg
+
+Returns the FS::cust_bill_pkg object (line item to which payment is applied).
+
+=cut
+
+sub cust_bill_pkg {
+ my $self = shift;
+ qsearchs('cust_bill_pkg', { 'billpkgnum' => $self->billpkgnum } );
+}
+
+=item send_receipt
+
+Sends a payment receipt for the associated payment, against this specific
+invoice and packages. If there is an error, returns the error, otherwise
+returns false.
+
+=cut
+
+sub send_receipt {
+ my $self = shift;
+ my $opt = ref($_[0]) ? shift : { @_ };
+ $self->cust_bill_pay->send_receipt(
+ 'cust_pkg' => $self->cust_bill_pkg->cust_pkg,
+ %$opt,
+ );
+}
+
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index 6c0589a..d3bdfd1 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -1,7 +1,7 @@
package FS::cust_bill_pkg;
use strict;
-use vars qw( @ISA $DEBUG );
+use vars qw( @ISA $DEBUG $me );
use FS::Record qw( qsearch qsearchs dbdef dbh );
use FS::cust_main_Mixin;
use FS::cust_pkg;
@@ -12,10 +12,14 @@ use FS::cust_bill_pkg_display;
use FS::cust_bill_pay_pkg;
use FS::cust_credit_bill_pkg;
use FS::cust_tax_exempt_pkg;
+use FS::cust_bill_pkg_tax_location;
+use FS::cust_bill_pkg_tax_rate_location;
+use FS::cust_tax_adjustment;
@ISA = qw( FS::cust_main_Mixin FS::Record );
-$DEBUG = 0;
+$DEBUG = 2;
+$me = '[FS::cust_bill_pkg]';
=head1 NAME
@@ -40,28 +44,57 @@ supported:
=over 4
-=item billpkgnum - primary key
+=item billpkgnum
-=item invnum - invoice (see L<FS::cust_bill>)
+primary key
-=item pkgnum - package (see L<FS::cust_pkg>) or 0 for the special virtual sales tax package, or -1 for the virtual line item (itemdesc is used for the line)
+=item invnum
-=item pkgpart_override - optional package definition (see L<FS::part_pkg>) override
-=item setup - setup fee
+invoice (see L<FS::cust_bill>)
-=item recur - recurring fee
+=item pkgnum
-=item sdate - starting date of recurring fee
+package (see L<FS::cust_pkg>) or 0 for the special virtual sales tax package, or -1 for the virtual line item (itemdesc is used for the line)
-=item edate - ending date of recurring fee
+=item pkgpart_override
-=item itemdesc - Line item description (overrides normal package description)
+optional package definition (see L<FS::part_pkg>) override
-=item quantity - If not set, defaults to 1
+=item setup
-=item unitsetup - If not set, defaults to setup
+setup fee
-=item unitrecur - If not set, defaults to recur
+=item recur
+
+recurring fee
+
+=item sdate
+
+starting date of recurring fee
+
+=item edate
+
+ending date of recurring fee
+
+=item itemdesc
+
+Line item description (overrides normal package description)
+
+=item quantity
+
+If not set, defaults to 1
+
+=item unitsetup
+
+If not set, defaults to setup
+
+=item unitrecur
+
+If not set, defaults to recur
+
+=item hidden
+
+If set to Y, indicates data should not appear as separate line item on invoice
=back
@@ -109,7 +142,7 @@ sub insert {
return $error;
}
- if ( defined dbdef->table('cust_bill_pkg_detail') && $self->get('details') ) {
+ if ( $self->get('details') ) {
foreach my $detail ( @{$self->get('details')} ) {
my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail {
'billpkgnum' => $self->billpkgnum,
@@ -117,22 +150,23 @@ sub insert {
'detail' => (ref($detail) ? $detail->[1] : $detail ),
'amount' => (ref($detail) ? $detail->[2] : '' ),
'classnum' => (ref($detail) ? $detail->[3] : '' ),
+ 'phonenum' => (ref($detail) ? $detail->[4] : '' ),
};
$error = $cust_bill_pkg_detail->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return $error;
+ return "error inserting cust_bill_pkg_detail: $error";
}
}
}
- if ( defined dbdef->table('cust_bill_pkg_display') && $self->get('display') ){
+ if ( $self->get('display') ) {
foreach my $cust_bill_pkg_display ( @{ $self->get('display') } ) {
$cust_bill_pkg_display->billpkgnum($self->billpkgnum);
$error = $cust_bill_pkg_display->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return $error;
+ return "error inserting cust_bill_pkg_display: $error";
}
}
}
@@ -143,7 +177,7 @@ sub insert {
$error = $cust_tax_exempt_pkg->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return $error;
+ return "error inserting cust_tax_exempt_pkg: $error";
}
}
}
@@ -152,16 +186,36 @@ sub insert {
if ( $tax_location ) {
foreach my $cust_bill_pkg_tax_location ( @$tax_location ) {
$cust_bill_pkg_tax_location->billpkgnum($self->billpkgnum);
- warn $cust_bill_pkg_tax_location;
$error = $cust_bill_pkg_tax_location->insert;
- warn $error;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return $error;
+ return "error inserting cust_bill_pkg_tax_location: $error";
+ }
+ }
+ }
+
+ my $tax_rate_location = $self->get('cust_bill_pkg_tax_rate_location');
+ if ( $tax_rate_location ) {
+ foreach my $cust_bill_pkg_tax_rate_location ( @$tax_rate_location ) {
+ $cust_bill_pkg_tax_rate_location->billpkgnum($self->billpkgnum);
+ $error = $cust_bill_pkg_tax_rate_location->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error inserting cust_bill_pkg_tax_rate_location: $error";
}
}
}
+ my $cust_tax_adjustment = $self->get('cust_tax_adjustment');
+ if ( $cust_tax_adjustment ) {
+ $cust_tax_adjustment->billpkgnum($self->billpkgnum);
+ $error = $cust_tax_adjustment->replace;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error replacing cust_tax_adjustment: $error";
+ }
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
@@ -169,13 +223,65 @@ sub insert {
=item delete
-Currently unimplemented. I don't remove line items because there would then be
-no record the items ever existed (which is bad, no?)
+Not recommended.
=cut
sub delete {
- return "Can't delete cust_bill_pkg records!";
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $table (qw(
+ cust_bill_pkg_detail
+ cust_bill_pkg_display
+ cust_bill_pkg_tax_location
+ cust_bill_pkg_tax_rate_location
+ cust_tax_exempt_pkg
+ cust_bill_pay_pkg
+ cust_credit_bill_pkg
+ )) {
+
+ foreach my $linked ( qsearch($table, { billpkgnum=>$self->billpkgnum }) ) {
+ my $error = $linked->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ }
+
+ foreach my $cust_tax_adjustment (
+ qsearch('cust_tax_adjustment', { billpkgnum=>$self->billpkgnum })
+ ) {
+ $cust_tax_adjustment->billpkgnum(''); #NULL
+ my $error = $cust_tax_adjustment->replace;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ my $error = $self->SUPER::delete(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
}
#alas, bin/follow-tax-rename
@@ -211,6 +317,8 @@ sub check {
|| $self->ut_numbern('sdate')
|| $self->ut_numbern('edate')
|| $self->ut_textn('itemdesc')
+ || $self->ut_textn('itemcomment')
+ || $self->ut_enum('hidden', [ '', 'Y' ])
;
return $error if $error;
@@ -234,6 +342,7 @@ Returns the package (see L<FS::cust_pkg>) for this invoice line item.
sub cust_pkg {
my $self = shift;
+ #warn "$me $self -> cust_pkg"; #carp?
qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
}
@@ -248,7 +357,10 @@ sub part_pkg {
if ( $self->pkgpart_override ) {
qsearchs('part_pkg', { 'pkgpart' => $self->pkgpart_override } );
} else {
- $self->cust_pkg->part_pkg;
+ my $part_pkg;
+ my $cust_pkg = $self->cust_pkg;
+ $part_pkg = $cust_pkg->part_pkg if $cust_pkg;
+ $part_pkg;
}
}
@@ -263,6 +375,24 @@ sub cust_bill {
qsearchs( 'cust_bill', { 'invnum' => $self->invnum } );
}
+=item previous_cust_bill_pkg
+
+Returns the previous cust_bill_pkg for this package, if any.
+
+=cut
+
+sub previous_cust_bill_pkg {
+ my $self = shift;
+ return unless $self->sdate;
+ qsearchs({
+ 'table' => 'cust_bill_pkg',
+ 'hashref' => { 'pkgnum' => $self->pkgnum,
+ 'sdate' => { op=>'<', value=>$self->sdate },
+ },
+ 'order_by' => 'ORDER BY sdate DESC LIMIT 1',
+ });
+}
+
=item details [ OPTION => VALUE ... ]
Returns an array of detail information for the invoice line item.
@@ -325,7 +455,7 @@ sub details {
$format_sub = $opt{format_function} if $opt{format_function};
map { ( $_->format eq 'C'
- ? &{$format_sub}( $_->detail )
+ ? &{$format_sub}( $_->detail, $_ )
: &{$escape_function}( $_->detail )
)
}
@@ -351,7 +481,9 @@ sub desc {
if ( $self->pkgnum > 0 ) {
$self->itemdesc || $self->part_pkg->pkg;
} else {
- $self->itemdesc || 'Tax';
+ my $desc = $self->itemdesc || 'Tax';
+ $desc .= ' '. $self->itemcomment if $self->itemcomment =~ /\S/;
+ $desc;
}
}
diff --git a/FS/FS/cust_bill_pkg_detail.pm b/FS/FS/cust_bill_pkg_detail.pm
index 8a48888..f8c9d1a 100644
--- a/FS/FS/cust_bill_pkg_detail.pm
+++ b/FS/FS/cust_bill_pkg_detail.pm
@@ -1,9 +1,10 @@
package FS::cust_bill_pkg_detail;
use strict;
-use vars qw( @ISA $me $DEBUG );
-use FS::Record qw( qsearch qsearchs dbdef );
+use vars qw( @ISA $me $DEBUG %GetInfoType );
+use FS::Record qw( qsearch qsearchs dbdef dbh );
use FS::cust_bill_pkg;
+use FS::Conf;
@ISA = qw(FS::Record);
$me = '[ FS::cust_bill_pkg_detail ]';
@@ -102,10 +103,27 @@ and replace methods.
sub check {
my $self = shift;
+ my $conf = new FS::Conf;
+
+ my $phonenum = $self->phonenum;
+ my $phonenum_check_method;
+ if ( $conf->exists('svc_phone-allow_alpha_phonenum') ) {
+ $phonenum =~ s/\W//g;
+ $phonenum_check_method = 'ut_alphan';
+ } else {
+ $phonenum =~ s/\D//g;
+ $phonenum_check_method = 'ut_numbern';
+ }
+ $self->phonenum($phonenum);
+
$self->ut_numbern('detailnum')
|| $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum')
+ #|| $self->ut_moneyn('amount')
+ || $self->ut_floatn('amount')
|| $self->ut_enum('format', [ '', 'C' ] )
|| $self->ut_text('detail')
+ || $self->ut_foreign_keyn('classnum', 'usage_class', 'classnum')
+ || $self->$phonenum_check_method('phonenum')
|| $self->SUPER::check
;
@@ -121,6 +139,79 @@ sub _upgrade_data { # class method
warn "$me upgrading $class\n" if $DEBUG;
+ my $columndef = dbdef->table($class->table)->column('classnum');
+ unless ($columndef->type eq 'int4') {
+
+ my $dbh = dbh;
+ if ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+
+ eval "use DBI::Const::GetInfoType;";
+ die $@ if $@;
+
+ my $major_version = 0;
+ $dbh->get_info( $GetInfoType{SQL_DBMS_VER} ) =~ /^(\d{2})/
+ && ( $major_version = sprintf("%d", $1) );
+
+ if ( $major_version > 7 ) {
+
+ # ideally this would be supported in DBIx-DBSchema and friends
+
+ foreach my $table ( qw( cust_bill_pkg_detail h_cust_bill_pkg_detail ) ){
+
+ warn "updating $table column classnum to integer\n" if $DEBUG;
+ my $sql = "ALTER TABLE $table ALTER classnum TYPE int USING ".
+ "int4(classnum)";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+
+ } elsif ( $dbh->{pg_server_version} =~ /^704/ ) { # earlier?
+
+ # ideally this would be supported in DBIx-DBSchema and friends
+
+ # XXX_FIXME better locking
+
+ foreach my $table ( qw( cust_bill_pkg_detail h_cust_bill_pkg_detail ) ){
+
+ warn "updating $table column classnum to integer\n" if $DEBUG;
+
+ my $sql = "ALTER TABLE $table RENAME classnum TO old_classnum";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ my $def = dbdef->table($table)->column('classnum');
+ $def->type('integer');
+ $def->length('');
+ $sql = "ALTER TABLE $table ADD COLUMN ". $def->line($dbh);
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ $sql = "UPDATE $table SET classnum = int4( text( old_classnum ) )";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ $sql = "ALTER TABLE $table DROP old_classnum";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+
+ } else {
+
+ die "cust_bill_pkg_detail classnum upgrade unsupported for this Pg version\n";
+
+ }
+
+ } else {
+
+ die "cust_bill_pkg_detail classnum upgrade only supported for Pg 8+\n";
+
+ }
+
+ }
+
+
if ( defined( dbdef->table($class->table)->column('billpkgnum') ) &&
defined( dbdef->table($class->table)->column('invnum') ) &&
defined( dbdef->table($class->table)->column('pkgnum') )
diff --git a/FS/FS/cust_bill_pkg_display.pm b/FS/FS/cust_bill_pkg_display.pm
index 93c6e87..cf70cbd 100644
--- a/FS/FS/cust_bill_pkg_display.pm
+++ b/FS/FS/cust_bill_pkg_display.pm
@@ -52,7 +52,12 @@ sub section {
if ( defined($value) ) {
$self->setfield('section', $value);
} else {
- $self->getfield('section') || $self->cust_bill_pkg->part_pkg->categoryname;
+ my $section = $self->getfield('section');
+ unless ($section) {
+ my $part_pkg = $self->cust_bill_pkg->part_pkg;
+ $section = $part_pkg->categoryname if $part_pkg;
+ }
+ $section;
}
}
diff --git a/FS/FS/cust_bill_pkg_tax_rate_location.pm b/FS/FS/cust_bill_pkg_tax_rate_location.pm
new file mode 100644
index 0000000..fc5734f
--- /dev/null
+++ b/FS/FS/cust_bill_pkg_tax_rate_location.pm
@@ -0,0 +1,136 @@
+package FS::cust_bill_pkg_tax_rate_location;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+use FS::cust_bill_pkg;
+use FS::cust_pkg;
+use FS::cust_location;
+
+=head1 NAME
+
+FS::cust_bill_pkg_tax_rate_location - Object methods for cust_bill_pkg_tax_rate_location records
+
+=head1 SYNOPSIS
+
+ use FS::cust_bill_pkg_tax_rate_location;
+
+ $record = new FS::cust_bill_pkg_tax_rate_location \%hash;
+ $record = new FS::cust_bill_pkg_tax_rate_location { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_bill_pkg_tax_rate_location object represents an record of taxation
+based on package location. FS::cust_bill_pkg_tax_rate_location inherits from
+FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item billpkgtaxratelocationnum
+
+billpkgtaxratelocationnum
+
+=item billpkgnum
+
+billpkgnum
+
+=item taxnum
+
+taxnum
+
+=item taxtype
+
+taxtype
+
+=item locationtaxid
+
+locationtaxid
+
+=item taxratelocationnum
+
+taxratelocationnum
+
+=item amount
+
+amount
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'cust_bill_pkg_tax_rate_location'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('billpkgtaxratelocationnum')
+ || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum' )
+ || $self->ut_number('taxnum') #cust_bill_pkg/tax_rate key, based on taxtype
+ || $self->ut_enum('taxtype', [ qw( FS::cust_main_county FS::tax_rate ) ] )
+ || $self->ut_textn('locationtaxid')
+ || $self->ut_foreign_key('taxratelocationnum', 'tax_rate_location', 'taxratelocationnum' )
+ || $self->ut_money('amount')
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm
index 47a8119..6c3effa 100644
--- a/FS/FS/cust_credit.pm
+++ b/FS/FS/cust_credit.pm
@@ -8,6 +8,7 @@ use FS::Misc qw(send_email);
use FS::Record qw( qsearch qsearchs dbdef );
use FS::cust_main_Mixin;
use FS::cust_main;
+use FS::cust_pkg;
use FS::cust_refund;
use FS::cust_credit_bill;
use FS::part_pkg;
@@ -95,6 +96,10 @@ Text
Books closed flag, empty or `Y'
+=item pkgnum
+
+Desired pkgnum when using experimental package balances.
+
=back
=head1 METHODS
@@ -295,6 +300,7 @@ sub check {
|| $self->ut_foreign_key('reasonnum', 'reason', 'reasonnum')
|| $self->ut_textn('addlinfo')
|| $self->ut_enum('closed', [ '', 'Y' ])
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
;
return $error if $error;
diff --git a/FS/FS/cust_credit_bill.pm b/FS/FS/cust_credit_bill.pm
index 375c885..900a5c0 100644
--- a/FS/FS/cust_credit_bill.pm
+++ b/FS/FS/cust_credit_bill.pm
@@ -8,6 +8,7 @@ use FS::cust_main_Mixin;
use FS::cust_bill_ApplicationCommon;
use FS::cust_bill;
use FS::cust_credit;
+use FS::cust_pkg;
@ISA = qw( FS::cust_main_Mixin FS::cust_bill_ApplicationCommon );
@@ -122,6 +123,7 @@ sub check {
|| $self->ut_foreign_key('invnum', 'cust_bill', 'invnum' )
|| $self->ut_numbern('_date')
|| $self->ut_money('amount')
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
;
return $error if $error;
diff --git a/FS/FS/cust_event.pm b/FS/FS/cust_event.pm
index 5ca8167..10fb0ac 100644
--- a/FS/FS/cust_event.pm
+++ b/FS/FS/cust_event.pm
@@ -1,7 +1,7 @@
package FS::cust_event;
use strict;
-use vars qw( @ISA $DEBUG );
+use vars qw( @ISA $DEBUG $me );
use Carp qw( croak confess );
use FS::Record qw( qsearch qsearchs dbdef );
use FS::cust_main_Mixin;
@@ -14,6 +14,7 @@ use FS::cust_bill;
@ISA = qw(FS::cust_main_Mixin FS::Record);
$DEBUG = 0;
+$me = '[FS::cust_event]';
=head1 NAME
@@ -295,6 +296,100 @@ sub retriable {
$self->replace($old);
}
+=item join_cust_sql
+
+=cut
+
+sub join_sql {
+ #my $class = shift;
+
+ "
+ JOIN part_event USING ( eventpart )
+ LEFT JOIN cust_bill ON ( eventtable = 'cust_bill' AND tablenum = invnum )
+ LEFT JOIN cust_pkg ON ( eventtable = 'cust_pkg' AND tablenum = pkgnum )
+ LEFT JOIN cust_main ON ( ( eventtable = 'cust_main' AND tablenum = cust_main.custnum )
+ OR ( eventtable = 'cust_bill' AND cust_bill.custnum = cust_main.custnum )
+ OR ( eventtable = 'cust_pkg' AND cust_pkg.custnum = cust_main.custnum )
+ )
+ ";
+
+}
+
+=item search_sql HASHREF
+
+Class method which returns an SQL WHERE fragment to search for parameters
+specified in HASHREF. Valid parameters are
+
+=over 4
+
+=item
+
+=item
+
+=back
+
+=cut
+
+#Note: validates all passed-in data; i.e. safe to use with unchecked CGI params.
+#sub
+
+sub search_sql {
+ my($class, $param) = @_;
+ if ( $DEBUG ) {
+ warn "$me search_sql called with params: \n".
+ join("\n", map { " $_: ". $param->{$_} } keys %$param ). "\n";
+ }
+
+ my @search = ();
+
+ if ( $param->{'agentnum'} && $param->{'agentnum'} =~ /^(\d+)$/ ) {
+ push @search, "cust_main.agentnum = $1";
+ #my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ #die "unknown agentnum $1" unless $agent;
+ }
+
+ if ( $param->{'beginning'} =~ /^(\d+)$/ ) {
+ push @search, "cust_event._date >= $1";
+ }
+ if ( $param->{'ending'} =~ /^(\d+)$/ ) {
+ push @search, "cust_event._date <= $1";
+ }
+
+ if ( $param->{'failed'} ) {
+ push @search, "statustext != ''",
+ "statustext IS NOT NULL",
+ "statustext != 'N/A'";
+ }
+
+ #if ( $param->{'part_event.payby'} =~ /^(\w+)$/ ) {
+ # push @search, "part_event.payby = '$1'";
+ #}
+
+ if ( $param->{'custnum'} =~ /^(\d+)$/ ) {
+ push @search, "cust_main.custnum = '$1'";
+ }
+
+ if ( $param->{'invnum'} =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_bill'",
+ "tablenum = '$1'";
+ }
+
+ if ( $param->{'pkgnum'} =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_pkg'",
+ "tablenum = '$1'";
+ }
+
+ #here is the agent virtualization
+ push @search,
+ $FS::CurrentUser::CurrentUser->agentnums_sql( 'table' => 'cust_main' );
+
+ my $where = 'WHERE '. join(' AND ', @search );
+
+
+ join(' AND ', @search );
+
+}
+
=back
=head1 SUBROUTINES
@@ -336,42 +431,43 @@ sub process_re_X {
re_X(
$method,
- $param->{'beginning'},
- $param->{'ending'},
- $param->{'failed'},
+ $param,
$job,
);
}
-#this needs some updating based on the 1.7 cust_bill_event.pm still, i think
sub re_X {
- my($method, $beginning, $ending, $failed, $job) = @_;
+ my($method, $param, $job) = @_;
+
+ my $search_sql = FS::cust_event->search_sql($param);
- my $from = 'LEFT JOIN part_event USING ( eventpart )';
+ #maybe not...? we do want the "re-" action to match the search more closely
+ # # yuck! hardcoded *AND* sequential scans!
+ #my $where = " WHERE action LIKE 'cust_bill_send%' ".
+ # ( $search_sql ? " AND $search_sql" : "" );
- # yuck! hardcoed *AND* sequential scans!
- my $where = " WHERE action LIKE 'cust_bill_send%'".
- " AND cust_event._date >= $beginning".
- " AND cust_event._date <= $ending";
- $where .= " AND statustext != '' AND statustext IS NOT NULL"
- if $failed;
+ my $where = ( $search_sql ? " WHERE $search_sql" : "" );
my @cust_event = qsearch({
'table' => 'cust_event',
- 'addl_from' => $from,
+ 'addl_from' => FS::cust_event->join_sql(),
'hashref' => {},
'extra_sql' => $where,
});
+ warn "$me re_X found ". scalar(@cust_event). " events\n"
+ if $DEBUG;
+
my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
foreach my $cust_event ( @cust_event ) {
- # XXX
- $cust_event->cust_bill->$method(
- $cust_event->part_event->templatename
- || $cust_event->cust_main->agent_template
- );
+ my $cust_X = $cust_event->cust_X; # cust_bill
+ next unless $cust_X->can($method);
+
+ $cust_X->$method( $cust_event->part_event->templatename
+ || $cust_X->agent_template
+ );
if ( $job ) { #progressbar foo
$num++;
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 865632f..c83acc6 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -9,6 +9,7 @@ use Safe;
use Carp;
use Exporter;
use Scalar::Util qw( blessed );
+use List::Util qw( min );
use Time::Local qw(timelocal);
use Data::Dumper;
use Tie::IxHash;
@@ -23,12 +24,14 @@ use FS::UID qw( getotaker dbh driver_name );
use FS::Record qw( qsearchs qsearch dbdef );
use FS::Misc qw( generate_email send_email generate_ps do_print );
use FS::Msgcat qw(gettext);
+use FS::payby;
use FS::cust_pkg;
use FS::cust_svc;
use FS::cust_bill;
use FS::cust_bill_pkg;
use FS::cust_bill_pkg_display;
use FS::cust_bill_pkg_tax_location;
+use FS::cust_bill_pkg_tax_rate_location;
use FS::cust_pay;
use FS::cust_pay_pending;
use FS::cust_pay_void;
@@ -38,7 +41,10 @@ use FS::cust_refund;
use FS::part_referral;
use FS::cust_main_county;
use FS::cust_location;
+use FS::cust_main_exemption;
+use FS::cust_tax_adjustment;
use FS::tax_rate;
+use FS::tax_rate_location;
use FS::cust_tax_location;
use FS::part_pkg_taxrate;
use FS::agent;
@@ -75,6 +81,8 @@ $skip_fuzzyfiles = 0;
$ignore_expired_card = 0;
@encrypted_fields = ('payinfo', 'paycvv');
+sub nohistory_fields { ('paycvv'); }
+
@paytypes = ('', 'Personal checking', 'Personal savings', 'Business checking', 'Business savings');
#ask FS::UID to run this stuff for us later
@@ -358,7 +366,7 @@ invoicing_list destination to the newly-created svc_acct. Here's an example:
$cust_main->insert( {}, [ $email, 'POST' ] );
-Currently available options are: I<depend_jobnum> and I<noexport>.
+Currently available options are: I<depend_jobnum>, I<noexport> and I<tax_exemption>.
If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
on the supplied jobnum (they will not run until the specific job completes).
@@ -369,6 +377,9 @@ The I<noexport> option is deprecated. If I<noexport> is set true, no
provisioning jobs (exports) are scheduled. (You can schedule them later with
the B<reexport> method.)
+The I<tax_exemption> option can be set to an arrayref of tax names.
+FS::cust_main_exemption records will be created and inserted.
+
=cut
sub insert {
@@ -392,7 +403,7 @@ sub insert {
my $dbh = dbh;
my $prepay_identifier = '';
- my( $amount, $seconds ) = ( 0, 0 );
+ my( $amount, $seconds, $upbytes, $downbytes, $totalbytes ) = (0, 0, 0, 0, 0);
my $payby = '';
if ( $self->payby eq 'PREPAY' ) {
@@ -403,7 +414,13 @@ sub insert {
warn " looking up prepaid card $prepay_identifier\n"
if $DEBUG > 1;
- my $error = $self->get_prepay($prepay_identifier, \$amount, \$seconds);
+ my $error = $self->get_prepay( $prepay_identifier,
+ 'amount_ref' => \$amount,
+ 'seconds_ref' => \$seconds,
+ 'upbytes_ref' => \$upbytes,
+ 'downbytes_ref' => \$downbytes,
+ 'totalbytes_ref' => \$totalbytes,
+ );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
#return "error applying prepaid card (transaction rolled back): $error";
@@ -448,6 +465,24 @@ sub insert {
$self->invoicing_list( $invoicing_list );
}
+ warn " setting cust_main_exemption\n"
+ if $DEBUG > 1;
+
+ my $tax_exemption = delete $options{'tax_exemption'};
+ if ( $tax_exemption ) {
+ foreach my $taxname ( @$tax_exemption ) {
+ my $cust_main_exemption = new FS::cust_main_exemption {
+ 'custnum' => $self->custnum,
+ 'taxname' => $taxname,
+ };
+ my $error = $cust_main_exemption->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "inserting cust_main_exemption (transaction rolled back): $error";
+ }
+ }
+ }
+
if ( $conf->config('cust_main-skeleton_tables')
&& $conf->config('cust_main-skeleton_custnum') ) {
@@ -465,7 +500,13 @@ sub insert {
warn " ordering packages\n"
if $DEBUG > 1;
- $error = $self->order_pkgs($cust_pkgs, \$seconds, %options);
+ $error = $self->order_pkgs( $cust_pkgs,
+ %options,
+ 'seconds_ref' => \$seconds,
+ 'upbytes_ref' => \$upbytes,
+ 'downbytes_ref' => \$downbytes,
+ 'totalbytes_ref' => \$totalbytes,
+ );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -475,6 +516,10 @@ sub insert {
$dbh->rollback if $oldAutoCommit;
return "No svc_acct record to apply pre-paid time";
}
+ if ( $upbytes || $downbytes || $totalbytes ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "No svc_acct record to apply pre-paid data";
+ }
if ( $amount ) {
warn " inserting initial $payby payment of $amount\n"
@@ -688,6 +733,14 @@ jobs will have a dependancy on the supplied job (they will not run until the
specific job completes). This can be used to defer provisioning until some
action completes (such as running the customer's credit card successfully).
+=item ticket_subject
+
+Optional subject for a ticket created and attached to this customer
+
+=item ticket_subject
+
+Optional queue name for ticket additions
+
=back
=cut
@@ -701,13 +754,15 @@ sub order_pkg {
if $DEBUG;
my $cust_pkg = $opt->{'cust_pkg'};
- my $seconds = $opt->{'seconds'};
my $svcs = $opt->{'svcs'} || [];
my %svc_options = ();
$svc_options{'depend_jobnum'} = $opt->{'depend_jobnum'}
if exists($opt->{'depend_jobnum'}) && $opt->{'depend_jobnum'};
+ my %insert_params = map { $opt->{$_} ? ( $_ => $opt->{$_} ) : () }
+ qw( ticket_subject ticket_queue );
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
@@ -731,7 +786,7 @@ sub order_pkg {
$cust_pkg->custnum( $self->custnum );
- my $error = $cust_pkg->insert;
+ my $error = $cust_pkg->insert( %insert_params );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "inserting cust_pkg (transaction rolled back): $error";
@@ -745,9 +800,12 @@ sub order_pkg {
$error = $new_cust_svc->replace($old_cust_svc);
} else {
$svc_something->pkgnum( $cust_pkg->pkgnum );
- if ( $seconds && $$seconds && $svc_something->isa('FS::svc_acct') ) {
- $svc_something->seconds( $svc_something->seconds + $$seconds );
- $$seconds = 0;
+ if ( $svc_something->isa('FS::svc_acct') ) {
+ foreach ( grep { $opt->{$_.'_ref'} && ${ $opt->{$_.'_ref'} } }
+ qw( seconds upbytes downbytes totalbytes ) ) {
+ $svc_something->$_( $svc_something->$_() + ${ $opt->{$_.'_ref'} } );
+ ${ $opt->{$_.'_ref'} } = 0;
+ }
}
$error = $svc_something->insert(%svc_options);
}
@@ -762,7 +820,8 @@ sub order_pkg {
}
-=item order_pkgs HASHREF, [ SECONDSREF, [ , OPTION => VALUE ... ] ]
+#deprecated #=item order_pkgs HASHREF [ , SECONDSREF ] [ , OPTION => VALUE ... ]
+=item order_pkgs HASHREF [ , OPTION => VALUE ... ]
Like the insert method on an existing record, this method orders multiple
packages and included services atomicaly. Pass a Tie::RefHash data structure
@@ -776,12 +835,13 @@ example:
$cust_pkg => [ $svc_acct ],
...
);
- $cust_main->order_pkgs( \%hash, \'0', 'noexport'=>1 );
+ $cust_main->order_pkgs( \%hash, 'noexport'=>1 );
Services can be new, in which case they are inserted, or existing unaudited
services, in which case they are linked to the newly-created package.
-Currently available options are: I<depend_jobnum> and I<noexport>.
+Currently available options are: I<depend_jobnum>, I<noexport>, I<seconds_ref>,
+I<upbytes_ref>, I<downbytes_ref>, and I<totalbytes_ref>.
If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
on the supplied jobnum (they will not run until the specific job completes).
@@ -794,13 +854,18 @@ the B<reexport> method for each cust_pkg object. Using the B<reexport> method
on the cust_main object is not recommended, as existing services will also be
reexported.)
+If I<seconds_ref>, I<upbytes_ref>, I<downbytes_ref>, or I<totalbytes_ref> is
+provided, the scalars (provided by references) will be incremented by the
+values of the prepaid card.`
+
=cut
sub order_pkgs {
my $self = shift;
my $cust_pkgs = shift;
- my $seconds = shift;
+ my $seconds_ref = ref($_[0]) ? shift : ''; #deprecated
my %options = @_;
+ $seconds_ref ||= $options{'seconds_ref'};
warn "$me order_pkgs called with options ".
join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
@@ -821,11 +886,14 @@ sub order_pkgs {
foreach my $cust_pkg ( keys %$cust_pkgs ) {
- my $error = $self->order_pkg( 'cust_pkg' => $cust_pkg,
- 'svcs' => $cust_pkgs->{$cust_pkg},
- 'seconds' => $seconds,
- 'depend_jobnum' => $options{'depend_jobnum'},
- );
+ my $error = $self->order_pkg(
+ 'cust_pkg' => $cust_pkg,
+ 'svcs' => $cust_pkgs->{$cust_pkg},
+ 'seconds_ref' => $seconds_ref,
+ map { $_ => $options{$_} } qw( upbytes_ref downbytes_ref totalbytes_ref
+ depend_jobnum
+ )
+ );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -844,13 +912,14 @@ L<FS::prepay_credit>), specified either by I<identifier> or as an
FS::prepay_credit object. If there is an error, returns the error, otherwise
returns false.
-Optionally, four scalar references can be passed as well. They will have their
-values filled in with the amount, number of seconds, and number of upload and
-download bytes applied by this prepaid
-card.
+Optionally, five scalar references can be passed as well. They will have their
+values filled in with the amount, number of seconds, and number of upload,
+download, and total bytes applied by this prepaid card.
=cut
+#the ref bullshit here should be refactored like get_prepay. MyAccount.pm is
+#the only place that uses these args
sub recharge_prepay {
my( $self, $prepay_credit, $amountref, $secondsref,
$upbytesref, $downbytesref, $totalbytesref ) = @_;
@@ -868,8 +937,13 @@ sub recharge_prepay {
my( $amount, $seconds, $upbytes, $downbytes, $totalbytes) = ( 0, 0, 0, 0, 0 );
- my $error = $self->get_prepay($prepay_credit, \$amount,
- \$seconds, \$upbytes, \$downbytes, \$totalbytes)
+ my $error = $self->get_prepay( $prepay_credit,
+ 'amount_ref' => \$amount,
+ 'seconds_ref' => \$seconds,
+ 'upbytes_ref' => \$upbytes,
+ 'downbytes_ref' => \$downbytes,
+ 'totalbytes_ref' => \$totalbytes,
+ )
|| $self->increment_seconds($seconds)
|| $self->increment_upbytes($upbytes)
|| $self->increment_downbytes($downbytes)
@@ -896,13 +970,13 @@ sub recharge_prepay {
}
-=item get_prepay IDENTIFIER | PREPAY_CREDIT_OBJ , AMOUNTREF, SECONDSREF
+=item get_prepay IDENTIFIER | PREPAY_CREDIT_OBJ [ , OPTION => VALUE ... ]
Looks up and deletes a prepaid card (see L<FS::prepay_credit>),
specified either by I<identifier> or as an FS::prepay_credit object.
-References to I<amount> and I<seconds> scalars should be passed as arguments
-and will be incremented by the values of the prepaid card.
+Available options are: I<amount_ref>, I<seconds_ref>, I<upbytes_ref>, I<downbytes_ref>, and I<totalbytes_ref>. The scalars (provided by references) will be
+incremented by the values of the prepaid card.
If the prepaid card specifies an I<agentnum> (see L<FS::agent>), it is used to
check or set this customer's I<agentnum>.
@@ -913,8 +987,7 @@ If there is an error, returns the error, otherwise returns false.
sub get_prepay {
- my( $self, $prepay_credit, $amountref, $secondsref,
- $upref, $downref, $totalref) = @_;
+ my( $self, $prepay_credit, %opt ) = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -959,11 +1032,8 @@ sub get_prepay {
return "removing prepay_credit (transaction rolled back): $error";
}
- $$amountref += $prepay_credit->amount;
- $$secondsref += $prepay_credit->seconds;
- $$upref += $prepay_credit->upbytes;
- $$downref += $prepay_credit->downbytes;
- $$totalref += $prepay_credit->totalbytes;
+ ${ $opt{$_.'_ref'} } += $prepay_credit->$_()
+ for grep $opt{$_.'_ref'}, qw( amount seconds upbytes downbytes totalbytes );
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
@@ -1249,6 +1319,16 @@ sub delete {
}
}
+ foreach my $cust_main_exemption (
+ qsearch( 'cust_main_exemption', { 'custnum' => $self->custnum } )
+ ) {
+ my $error = $cust_main_exemption->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
my $error = $self->SUPER::delete;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
@@ -1260,7 +1340,8 @@ sub delete {
}
-=item replace [ OLD_RECORD ] [ INVOICING_LIST_ARYREF ]
+=item replace [ OLD_RECORD ] [ INVOICING_LIST_ARYREF ] [ , OPTION => VALUE ... ] ]
+
Replaces the OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
@@ -1272,6 +1353,11 @@ check_invoicing_list first. Here's an example:
$new_cust_main->replace( $old_cust_main, [ $email, 'POST' ] );
+Currently available options are: I<tax_exemption>.
+
+The I<tax_exemption> option can be set to an arrayref of tax names.
+FS::cust_main_exemption records will be deleted and inserted as appropriate.
+
=cut
sub replace {
@@ -1318,7 +1404,7 @@ sub replace {
return $error;
}
- if ( @param ) { # INVOICING_LIST_ARYREF
+ if ( @param && ref($param[0]) eq 'ARRAY' ) { # INVOICING_LIST_ARYREF
my $invoicing_list = shift @param;
$error = $self->check_invoicing_list( $invoicing_list );
if ( $error ) {
@@ -1328,6 +1414,40 @@ sub replace {
$self->invoicing_list( $invoicing_list );
}
+ my %options = @param;
+
+ my $tax_exemption = delete $options{'tax_exemption'};
+ if ( $tax_exemption ) {
+
+ my %cust_main_exemption =
+ map { $_->taxname => $_ }
+ qsearch('cust_main_exemption', { 'custnum' => $old->custnum } );
+
+ foreach my $taxname ( @$tax_exemption ) {
+
+ next if delete $cust_main_exemption{$taxname};
+
+ my $cust_main_exemption = new FS::cust_main_exemption {
+ 'custnum' => $self->custnum,
+ 'taxname' => $taxname,
+ };
+ my $error = $cust_main_exemption->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "inserting cust_main_exemption (transaction rolled back): $error";
+ }
+ }
+
+ foreach my $cust_main_exemption ( values %cust_main_exemption ) {
+ my $error = $cust_main_exemption->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "deleting cust_main_exemption (transaction rolled back): $error";
+ }
+ }
+
+ }
+
if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ &&
grep { $self->get($_) ne $old->get($_) } qw(payinfo paydate payname) ) {
# card/check/lec info has changed, want to retry realtime_ invoice events
@@ -1433,6 +1553,7 @@ sub check {
|| $self->ut_textn('stateid_state')
|| $self->ut_textn('invoice_terms')
|| $self->ut_alphan('geocode')
+ || $self->ut_floatn('cdr_termination_percentage')
;
#barf. need message catalogs. i18n. etc.
@@ -1450,6 +1571,13 @@ sub check {
unless ! $self->referral_custnum
|| qsearchs( 'cust_main', { 'custnum' => $self->referral_custnum } );
+ if ( $self->censustract ne '' ) {
+ $self->censustract =~ /^\s*(\d{9})\.?(\d{2})\s*$/
+ or return "Illegal census tract: ". $self->censustract;
+
+ $self->censustract("$1.$2");
+ }
+
if ( $self->ss eq '' ) {
$self->ss('');
} else {
@@ -1717,6 +1845,8 @@ sub check {
my( $m, $y );
if ( $self->paydate =~ /^(\d{1,2})[\/\-](\d{2}(\d{2})?)$/ ) {
( $m, $y ) = ( $1, length($2) == 4 ? $2 : "20$2" );
+ } elsif ( $self->paydate =~ /^19(\d{2})[\/\-](\d{1,2})[\/\-]\d+$/ ) {
+ ( $m, $y ) = ( $2, "19$1" );
} elsif ( $self->paydate =~ /^(20)?(\d{2})[\/\-](\d{1,2})[\/\-]\d+$/ ) {
( $m, $y ) = ( $3, "20$2" );
} else {
@@ -1741,7 +1871,7 @@ sub check {
$self->payname($1);
}
- foreach my $flag (qw( tax spool_cdr squelch_cdr )) {
+ foreach my $flag (qw( tax spool_cdr squelch_cdr archived email_csv_cdr )) {
$self->$flag() =~ /^(Y?)$/ or return "Illegal $flag: ". $self->$flag();
$self->$flag($1);
}
@@ -1778,7 +1908,7 @@ sub has_ship_address {
scalar( grep { $self->getfield("ship_$_") ne '' } $self->addr_fields );
}
-=item all_pkgs
+=item all_pkgs [ EXTRA_QSEARCH_PARAMS_HASHREF ]
Returns all packages (see L<FS::cust_pkg>) for this customer.
@@ -1786,14 +1916,15 @@ Returns all packages (see L<FS::cust_pkg>) for this customer.
sub all_pkgs {
my $self = shift;
+ my $extra_qsearch = ref($_[0]) ? shift : {};
- return $self->num_pkgs unless wantarray;
+ return $self->num_pkgs unless wantarray || keys(%$extra_qsearch);
my @cust_pkg = ();
if ( $self->{'_pkgnum'} ) {
@cust_pkg = values %{ $self->{'_pkgnum'}->cache };
} else {
- @cust_pkg = qsearch( 'cust_pkg', { 'custnum' => $self->custnum });
+ @cust_pkg = $self->_cust_pkg($extra_qsearch);
}
sort sort_packages @cust_pkg;
@@ -1820,7 +1951,7 @@ sub cust_location {
qsearch('cust_location', { 'custnum' => $self->custnum } );
}
-=item ncancelled_pkgs
+=item ncancelled_pkgs [ EXTRA_QSEARCH_PARAMS_HASHREF ]
Returns all non-cancelled packages (see L<FS::cust_pkg>) for this customer.
@@ -1828,6 +1959,7 @@ Returns all non-cancelled packages (see L<FS::cust_pkg>) for this customer.
sub ncancelled_pkgs {
my $self = shift;
+ my $extra_qsearch = ref($_[0]) ? shift : {};
return $self->num_ncancelled_pkgs unless wantarray;
@@ -1846,33 +1978,56 @@ sub ncancelled_pkgs {
$self->custnum. "\n"
if $DEBUG > 1;
- @cust_pkg =
- qsearch( 'cust_pkg', {
- 'custnum' => $self->custnum,
- 'cancel' => '',
- });
- push @cust_pkg,
- qsearch( 'cust_pkg', {
- 'custnum' => $self->custnum,
- 'cancel' => 0,
- });
+ $extra_qsearch->{'extra_sql'} .= ' AND ( cancel IS NULL OR cancel = 0 ) ';
+
+ @cust_pkg = $self->_cust_pkg($extra_qsearch);
+
}
sort sort_packages @cust_pkg;
}
+sub _cust_pkg {
+ my $self = shift;
+ my $extra_qsearch = ref($_[0]) ? shift : {};
+
+ $extra_qsearch->{'select'} ||= '*';
+ $extra_qsearch->{'select'} .=
+ ',( SELECT COUNT(*) FROM cust_svc WHERE cust_pkg.pkgnum = cust_svc.pkgnum )
+ AS _num_cust_svc';
+
+ map {
+ $_->{'_num_cust_svc'} = $_->get('_num_cust_svc');
+ $_;
+ }
+ qsearch({
+ %$extra_qsearch,
+ 'table' => 'cust_pkg',
+ 'hashref' => { 'custnum' => $self->custnum },
+ });
+
+}
+
# This should be generalized to use config options to determine order.
sub sort_packages {
- if ( $a->get('cancel') and $b->get('cancel') ) {
- $a->pkgnum <=> $b->pkgnum;
- } elsif ( $a->get('cancel') or $b->get('cancel') ) {
+
+ if ( $a->get('cancel') xor $b->get('cancel') ) {
return -1 if $b->get('cancel');
return 1 if $a->get('cancel');
+ #shouldn't get here...
return 0;
} else {
- $a->pkgnum <=> $b->pkgnum;
+ my $a_num_cust_svc = $a->num_cust_svc;
+ my $b_num_cust_svc = $b->num_cust_svc;
+ return 0 if !$a_num_cust_svc && !$b_num_cust_svc;
+ return -1 if $a_num_cust_svc && !$b_num_cust_svc;
+ return 1 if !$a_num_cust_svc && $b_num_cust_svc;
+ my @a_cust_svc = $a->cust_svc;
+ my @b_cust_svc = $b->cust_svc;
+ $a_cust_svc[0]->svc_x->label cmp $b_cust_svc[0]->svc_x->label;
}
+
}
=item suspended_pkgs
@@ -1912,6 +2067,18 @@ sub unsuspended_pkgs {
grep { ! $_->susp } $self->ncancelled_pkgs;
}
+=item next_bill_date
+
+Returns the next date this customer will be billed, as a UNIX timestamp, or
+undef if no active package has a next bill date.
+
+=cut
+
+sub next_bill_date {
+ my $self = shift;
+ min( map $_->get('bill'), grep $_->get('bill'), $self->unsuspended_pkgs );
+}
+
=item num_cancelled_pkgs
Returns the number of cancelled packages (see L<FS::cust_pkg>) for this
@@ -2043,12 +2210,16 @@ Available options are:
=item ban - can be set true to ban this customer's credit card or ACH information, if present.
+=item nobill - can be set true to skip billing if it might otherwise be done.
+
=back
Always returns a list: an empty list on success or a list of errors.
=cut
+# nb that dates are not specified as valid options to this method
+
sub cancel {
my( $self, %opt ) = @_;
@@ -2074,6 +2245,13 @@ sub cancel {
my @pkgs = $self->ncancelled_pkgs;
+ if ( !$opt{nobill} && $conf->exists('bill_usage_on_cancel') ) {
+ $opt{nobill} = 1;
+ my $error = $self->bill( pkg_list => [ @pkgs ], cancel => 1 );
+ warn "Error billing during cancel, custnum ". $self->custnum. ": $error"
+ if $error;
+ }
+
warn "$me cancelling ". scalar($self->ncancelled_pkgs). "/".
scalar(@pkgs). " packages for customer ". $self->custnum. "\n"
if $DEBUG;
@@ -2162,23 +2340,45 @@ Debugging level. Default is 0 (no debugging), or can be set to 1 (passed-in opt
=back
+Options are passed to the B<bill> and B<collect> methods verbatim, so all
+options of those methods are also available.
+
=cut
sub bill_and_collect {
my( $self, %options ) = @_;
- ###
- # cancel packages
- ###
-
#$options{actual_time} not $options{time} because freeside-daily -d is for
#pre-printing invoices
- my @cancel_pkgs = grep { $_->expire && $_->expire <= $options{actual_time} }
- $self->ncancelled_pkgs;
+ $self->cancel_expired_pkgs( $options{actual_time} );
+ $self->suspend_adjourned_pkgs( $options{actual_time} );
+
+ my $error = $self->bill( %options );
+ warn "Error billing, custnum ". $self->custnum. ": $error" if $error;
+
+ $self->apply_payments_and_credits;
+
+ unless ( $conf->exists('cancelled_cust-noevents')
+ && ! $self->num_ncancelled_pkgs
+ ) {
+
+ $error = $self->collect( %options );
+ warn "Error collecting, custnum". $self->custnum. ": $error" if $error;
+
+ }
+
+}
+
+sub cancel_expired_pkgs {
+ my ( $self, $time ) = @_;
+
+ my @cancel_pkgs = $self->ncancelled_pkgs( {
+ 'extra_sql' => " AND expire IS NOT NULL AND expire > 0 AND expire <= $time "
+ } );
foreach my $cust_pkg ( @cancel_pkgs ) {
my $cpr = $cust_pkg->last_cust_pkg_reason('expire');
- my $error = $cust_pkg->cancel($cpr ? ( 'reason' => $cpr->reasonnum,
+ my $error = $cust_pkg->cancel($cpr ? ( 'reason' => $cpr->reasonnum,
'reason_otaker' => $cpr->otaker
)
: ()
@@ -2188,24 +2388,32 @@ sub bill_and_collect {
if $error;
}
- ###
- # suspend packages
- ###
+}
- #$options{actual_time} not $options{time} because freeside-daily -d is for
- #pre-printing invoices
- my @susp_pkgs =
- grep { ! $_->susp
- && ( ( $_->part_pkg->is_prepaid
- && $_->bill
- && $_->bill < $options{actual_time}
- )
- || ( $_->adjourn
- && $_->adjourn <= $options{actual_time}
- )
- )
+sub suspend_adjourned_pkgs {
+ my ( $self, $time ) = @_;
+
+ my @susp_pkgs = $self->ncancelled_pkgs( {
+ 'extra_sql' =>
+ " AND ( susp IS NULL OR susp = 0 )
+ AND ( ( bill IS NOT NULL AND bill != 0 AND bill < $time )
+ OR ( adjourn IS NOT NULL AND adjourn != 0 AND adjourn <= $time )
+ )
+ ",
+ } );
+
+ #only because there's no SQL test for is_prepaid :/
+ @susp_pkgs =
+ grep { ( $_->part_pkg->is_prepaid
+ && $_->bill
+ && $_->bill < $time
+ )
+ || ( $_->adjourn
+ && $_->adjourn <= $time
+ )
+
}
- $self->ncancelled_pkgs;
+ @susp_pkgs;
foreach my $cust_pkg ( @susp_pkgs ) {
my $cpr = $cust_pkg->last_cust_pkg_reason('adjourn')
@@ -2221,18 +2429,6 @@ sub bill_and_collect {
if $error;
}
- ###
- # bill and collect
- ###
-
- my $error = $self->bill( %options );
- warn "Error billing, custnum ". $self->custnum. ": $error" if $error;
-
- $self->apply_payments_and_credits;
-
- $error = $self->collect( %options );
- warn "Error collecting, custnum". $self->custnum. ": $error" if $error;
-
}
=item bill OPTIONS
@@ -2264,10 +2460,26 @@ An array ref of specific packages (objects) to attempt billing, instead trying a
$cust_main->bill( pkg_list => [$pkg1, $pkg2] );
+=item not_pkgpart
+
+A hashref of pkgparts to exclude from this billing run (can also be specified as a comma-separated scalar).
+
=item invoice_time
Used in conjunction with the I<time> option, this option specifies the date of for the generated invoices. Other calculations, such as whether or not to generate the invoice in the first place, are not affected.
+=item cancel
+
+This boolean value informs the us that the package is being cancelled. This
+typically might mean not charging the normal recurring fee but only usage
+fees since the last billing. Setup charges may be charged. Not all package
+plans support this feature (they tend to charge 0).
+
+=item invoice_terms
+
+Options terms to be printed on this invocice. Otherwise, customer-specific
+terms or the default terms are used.
+
=back
=cut
@@ -2281,7 +2493,12 @@ sub bill {
my $time = $options{'time'} || time;
my $invoice_time = $options{'invoice_time'} || $time;
- #put below somehow?
+ $options{'not_pkgpart'} ||= {};
+ $options{'not_pkgpart'} = { map { $_ => 1 }
+ split(/\s*,\s*/, $options{'not_pkgpart'})
+ }
+ unless ref($options{'not_pkgpart'});
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
@@ -2295,6 +2512,17 @@ sub bill {
$self->select_for_update; #mutex
+ my $error = $self->do_cust_event(
+ 'debug' => ( $options{'debug'} || 0 ),
+ 'time' => $invoice_time,
+ 'check_freq' => $options{'check_freq'},
+ 'stage' => 'pre-bill',
+ );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
my @cust_bill_pkg = ();
###
@@ -2306,11 +2534,10 @@ sub bill {
my %taxlisthash;
my @precommit_hooks = ();
- my @cust_pkgs = qsearch('cust_pkg', { 'custnum' => $self->custnum } );
- foreach my $cust_pkg (@cust_pkgs) {
+ $options{'pkg_list'} ||= [ $self->ncancelled_pkgs ]; #param checks?
+ foreach my $cust_pkg ( @{ $options{'pkg_list'} } ) {
- #NO!! next if $cust_pkg->cancel;
- next if $cust_pkg->getfield('cancel');
+ next if $options{'not_pkgpart'}->{$cust_pkg->pkgpart};
warn " bill package ". $cust_pkg->pkgnum. "\n" if $DEBUG > 1;
@@ -2336,6 +2563,7 @@ sub bill {
'recur' => \$total_recur,
'tax_matrix' => \%taxlisthash,
'time' => $time,
+ 'real_pkgpart' => $real_pkgpart,
'options' => \%options,
);
if ($error) {
@@ -2353,35 +2581,44 @@ sub bill {
return '';
}
- my $postal_pkg = $self->charge_postal_fee();
- if ( $postal_pkg && !ref( $postal_pkg ) ) {
- $dbh->rollback if $oldAutoCommit;
- return "can't charge postal invoice fee for customer ".
- $self->custnum. ": $postal_pkg";
- }
- if ( $postal_pkg &&
- ( scalar( grep { $_->recur && $_->recur > 0 } @cust_bill_pkg) ||
+ if ( scalar( grep { $_->recur && $_->recur > 0 } @cust_bill_pkg) ||
!$conf->exists('postal_invoice-recurring_only')
- )
)
{
- foreach my $part_pkg ( $postal_pkg->part_pkg->self_and_bill_linked ) {
- my $error =
- $self->_make_lines( 'part_pkg' => $part_pkg,
- 'cust_pkg' => $postal_pkg,
- 'precommit_hooks' => \@precommit_hooks,
- 'line_items' => \@cust_bill_pkg,
- 'setup' => \$total_setup,
- 'recur' => \$total_recur,
- 'tax_matrix' => \%taxlisthash,
- 'time' => $time,
- 'options' => \%options,
- );
- if ($error) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
+
+ my $postal_pkg = $self->charge_postal_fee();
+ if ( $postal_pkg && !ref( $postal_pkg ) ) {
+
+ $dbh->rollback if $oldAutoCommit;
+ return "can't charge postal invoice fee for customer ".
+ $self->custnum. ": $postal_pkg";
+
+ } elsif ( $postal_pkg ) {
+
+ my $real_pkgpart = $postal_pkg->pkgpart;
+ foreach my $part_pkg ( $postal_pkg->part_pkg->self_and_bill_linked ) {
+ my %postal_options = %options;
+ delete $postal_options{cancel};
+ my $error =
+ $self->_make_lines( 'part_pkg' => $part_pkg,
+ 'cust_pkg' => $postal_pkg,
+ 'precommit_hooks' => \@precommit_hooks,
+ 'line_items' => \@cust_bill_pkg,
+ 'setup' => \$total_setup,
+ 'recur' => \$total_recur,
+ 'tax_matrix' => \%taxlisthash,
+ 'time' => $time,
+ 'real_pkgpart' => $real_pkgpart,
+ 'options' => \%postal_options,
+ );
+ if ($error) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
}
+
}
+
}
warn "having a look at the taxes we found...\n" if $DEBUG > 2;
@@ -2398,9 +2635,14 @@ sub bill {
# values are listrefs of cust_bill_pkg_tax_location hashrefs
my %tax_location = ();
+ # keys are taxlisthash keys (internal identifiers)
+ # values are listrefs of cust_bill_pkg_tax_rate_location hashrefs
+ my %tax_rate_location = ();
+
foreach my $tax ( keys %taxlisthash ) {
my $tax_object = shift @{ $taxlisthash{$tax} };
warn "found ". $tax_object->taxname. " as $tax\n" if $DEBUG > 2;
+ warn " ". join('/', @{ $taxlisthash{$tax} } ). "\n" if $DEBUG > 2;
my $hashref_or_error =
$tax_object->taxline( $taxlisthash{$tax},
'custnum' => $self->custnum,
@@ -2433,72 +2675,40 @@ sub bill {
};
}
+ $tax_rate_location{ $tax } ||= [];
+ if ( ref($tax_object) eq 'FS::tax_rate' ) {
+ my $taxratelocationnum =
+ $tax_object->tax_rate_location->taxratelocationnum;
+ push @{ $tax_rate_location{ $tax } },
+ {
+ 'taxnum' => $tax_object->taxnum,
+ 'taxtype' => ref($tax_object),
+ 'amount' => sprintf('%.2f', $amount ),
+ 'locationtaxid' => $tax_object->location,
+ 'taxratelocationnum' => $taxratelocationnum,
+ };
+ }
+
}
#move the cust_tax_exempt_pkg records to the cust_bill_pkgs we will commit
my %packagemap = map { $_->pkgnum => $_ } @cust_bill_pkg;
foreach my $tax ( keys %taxlisthash ) {
foreach ( @{ $taxlisthash{$tax} }[1 ... scalar(@{ $taxlisthash{$tax} })] ) {
- next unless ref($_) eq 'FS::cust_bill_pkg'; # shouldn't happen
+ next unless ref($_) eq 'FS::cust_bill_pkg';
push @{ $packagemap{$_->pkgnum}->_cust_tax_exempt_pkg },
splice( @{ $_->_cust_tax_exempt_pkg } );
}
}
- #some taxes are taxed
- my %totlisthash;
-
- warn "finding taxed taxes...\n" if $DEBUG > 2;
- foreach my $tax ( keys %taxlisthash ) {
- my $tax_object = shift @{ $taxlisthash{$tax} };
- warn "found possible taxed tax ". $tax_object->taxname. " we call $tax\n"
- if $DEBUG > 2;
- next unless $tax_object->can('tax_on_tax');
-
- foreach my $tot ( $tax_object->tax_on_tax( $self ) ) {
- my $totname = ref( $tot ). ' '. $tot->taxnum;
-
- warn "checking $totname which we call ". $tot->taxname. " as applicable\n"
- if $DEBUG > 2;
- next unless exists( $taxlisthash{ $totname } ); # only increase
- # existing taxes
- warn "adding $totname to taxed taxes\n" if $DEBUG > 2;
- if ( exists( $totlisthash{ $totname } ) ) {
- push @{ $totlisthash{ $totname } }, $tax{ $tax };
- }else{
- $totlisthash{ $totname } = [ $tot, $tax{ $tax } ];
- }
- }
- }
-
- warn "having a look at taxed taxes...\n" if $DEBUG > 2;
- foreach my $tax ( keys %totlisthash ) {
- my $tax_object = shift @{ $totlisthash{$tax} };
- warn "found previously found taxed tax ". $tax_object->taxname. "\n"
- if $DEBUG > 2;
- my $listref_or_error =
- $tax_object->taxline( $totlisthash{$tax},
- 'custnum' => $self->custnum,
- 'invoice_time' => $invoice_time
- );
- unless (ref($listref_or_error)) {
- $dbh->rollback if $oldAutoCommit;
- return $listref_or_error;
- }
-
- warn "adding taxed tax amount ". $listref_or_error->[1].
- " as ". $tax_object->taxname. "\n"
- if $DEBUG;
- $tax{ $tax } += $listref_or_error->[1];
- }
-
#consolidate and create tax line items
warn "consolidating and generating...\n" if $DEBUG > 2;
foreach my $taxname ( keys %taxname ) {
my $tax = 0;
my %seen = ();
my @cust_bill_pkg_tax_location = ();
+ my @cust_bill_pkg_tax_rate_location = ();
warn "adding $taxname\n" if $DEBUG > 1;
foreach my $taxitem ( @{ $taxname{$taxname} } ) {
next if $seen{$taxitem}++;
@@ -2507,12 +2717,32 @@ sub bill {
push @cust_bill_pkg_tax_location,
map { new FS::cust_bill_pkg_tax_location $_ }
@{ $tax_location{ $taxitem } };
+ push @cust_bill_pkg_tax_rate_location,
+ map { new FS::cust_bill_pkg_tax_rate_location $_ }
+ @{ $tax_rate_location{ $taxitem } };
}
next unless $tax;
$tax = sprintf('%.2f', $tax );
$total_setup = sprintf('%.2f', $total_setup+$tax );
+ my $pkg_category = qsearchs( 'pkg_category', { 'categoryname' => $taxname,
+ 'disabled' => '',
+ },
+ );
+
+ my @display = ();
+ if ( $pkg_category and
+ $conf->config('invoice_latexsummary') ||
+ $conf->config('invoice_htmlsummary')
+ )
+ {
+
+ my %hash = ( 'section' => $pkg_category->categoryname );
+ push @display, new FS::cust_bill_pkg_display { type => 'S', %hash };
+
+ }
+
push @cust_bill_pkg, new FS::cust_bill_pkg {
'pkgnum' => 0,
'setup' => $tax,
@@ -2520,20 +2750,65 @@ sub bill {
'sdate' => '',
'edate' => '',
'itemdesc' => $taxname,
+ 'display' => \@display,
'cust_bill_pkg_tax_location' => \@cust_bill_pkg_tax_location,
+ 'cust_bill_pkg_tax_rate_location' => \@cust_bill_pkg_tax_rate_location,
+ };
+
+ }
+
+ #add tax adjustments
+ warn "adding tax adjustments...\n" if $DEBUG > 2;
+ foreach my $cust_tax_adjustment (
+ qsearch('cust_tax_adjustment', { 'custnum' => $self->custnum,
+ 'billpkgnum' => '',
+ }
+ )
+ ) {
+
+ my $tax = sprintf('%.2f', $cust_tax_adjustment->amount );
+ $total_setup = sprintf('%.2f', $total_setup+$tax );
+
+ my $itemdesc = $cust_tax_adjustment->taxname;
+ $itemdesc = '' if $itemdesc eq 'Tax';
+
+ push @cust_bill_pkg, new FS::cust_bill_pkg {
+ 'pkgnum' => 0,
+ 'setup' => $tax,
+ 'recur' => 0,
+ 'sdate' => '',
+ 'edate' => '',
+ 'itemdesc' => $itemdesc,
+ 'itemcomment' => $cust_tax_adjustment->comment,
+ 'cust_tax_adjustment' => $cust_tax_adjustment,
+ #'cust_bill_pkg_tax_location' => \@cust_bill_pkg_tax_location,
};
}
my $charged = sprintf('%.2f', $total_setup + $total_recur );
+ my @cust_bill = $self->cust_bill;
+ my $balance = $self->balance;
+ my $previous_balance = scalar(@cust_bill)
+ ? ( $cust_bill[$#cust_bill]->billing_balance || 0 )
+ : 0;
+
+ $previous_balance += $cust_bill[$#cust_bill]->charged
+ if scalar(@cust_bill);
+ #my $balance_adjustments =
+ # sprintf('%.2f', $balance - $prior_prior_balance - $prior_charged);
+
#create the new invoice
my $cust_bill = new FS::cust_bill ( {
- 'custnum' => $self->custnum,
- '_date' => ( $invoice_time ),
- 'charged' => $charged,
+ 'custnum' => $self->custnum,
+ '_date' => ( $invoice_time ),
+ 'charged' => $charged,
+ 'billing_balance' => $balance,
+ 'previous_balance' => $previous_balance,
+ 'invoice_terms' => $options{'invoice_terms'},
} );
- my $error = $cust_bill->insert;
+ $error = $cust_bill->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "can't create invoice for customer #". $self->custnum. ": $error";
@@ -2575,10 +2850,10 @@ sub _make_lines {
my $total_recur = $params{recur} or die "no recur accumulator specified";
my $taxlisthash = $params{tax_matrix} or die "no tax accumulator specified";
my $time = $params{'time'} or die "no time specified";
- my (%options) = %{$params{options}}; #hmmm only for 'resetup'
+ my (%options) = %{$params{options}};
my $dbh = dbh;
- my $real_pkgpart = $cust_pkg->pkgpart;
+ my $real_pkgpart = $params{real_pkgpart};
my %hash = $cust_pkg->hash;
my $old_cust_pkg = new FS::cust_pkg \%hash;
@@ -2594,14 +2869,19 @@ sub _make_lines {
my $setup = 0;
my $unitsetup = 0;
- if ( ! $cust_pkg->setup &&
- (
- ( $conf->exists('disable_setup_suspended_pkgs') &&
- ! $cust_pkg->getfield('susp')
- ) || ! $conf->exists('disable_setup_suspended_pkgs')
- )
- || $options{'resetup'}
- ) {
+ if ( $options{'resetup'}
+ || ( ! $cust_pkg->setup
+ && ( ! $cust_pkg->start_date
+ || $cust_pkg->start_date <= $time
+ )
+ && ( ! $conf->exists('disable_setup_suspended_pkgs')
+ || ( $conf->exists('disable_setup_suspended_pkgs') &&
+ ! $cust_pkg->getfield('susp')
+ )
+ )
+ )
+ )
+ {
warn " bill setup\n" if $DEBUG > 1;
$lineitems++;
@@ -2617,6 +2897,9 @@ sub _make_lines {
#do need it, but it won't get written to the db
#|| $cust_pkg->pkgpart != $real_pkgpart;
+ $cust_pkg->setfield('start_date', '')
+ if $cust_pkg->start_date;
+
}
###
@@ -2627,13 +2910,15 @@ sub _make_lines {
my $recur = 0;
my $unitrecur = 0;
my $sdate;
- if ( ! $cust_pkg->getfield('susp') and
- ( $part_pkg->getfield('freq') ne '0' &&
- ( $cust_pkg->getfield('bill') || 0 ) <= $time
+ if ( ! $cust_pkg->get('susp')
+ and ! $cust_pkg->get('start_date')
+ and ( $part_pkg->getfield('freq') ne '0'
+ && ( $cust_pkg->getfield('bill') || 0 ) <= $time
)
|| ( $part_pkg->plan eq 'voip_cdr'
&& $part_pkg->option('bill_every_call')
)
+ || ( $options{cancel} )
) {
# XXX should this be a package event? probably. events are called
@@ -2647,18 +2932,22 @@ sub _make_lines {
$lineitems++;
# XXX shared with $recur_prog
- $sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
+ $sdate = ( $options{cancel} ? $cust_pkg->last_bill : $cust_pkg->bill )
+ || $cust_pkg->setup
+ || $time;
#over two params! lets at least switch to a hashref for the rest...
my $increment_next_bill = ( $part_pkg->freq ne '0'
&& ( $cust_pkg->getfield('bill') || 0 ) <= $time
+ && !$options{cancel}
);
my %param = ( 'precommit_hooks' => $precommit_hooks,
'increment_next_bill' => $increment_next_bill,
);
- $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details, \%param ) };
- return "$@ running calc_recur for $cust_pkg\n"
+ my $method = $options{cancel} ? 'calc_cancel' : 'calc_recur';
+ $recur = eval { $cust_pkg->$method( \$sdate, \@details, \%param ) };
+ return "$@ running $method for $cust_pkg\n"
if ( $@ );
if ( $increment_next_bill ) {
@@ -2733,14 +3022,17 @@ sub _make_lines {
'unitrecur' => $unitrecur,
'quantity' => $cust_pkg->quantity,
'details' => \@details,
+ 'hidden' => $part_pkg->hidden,
};
if ( $part_pkg->option('recur_temporality', 1) eq 'preceding' ) {
$cust_bill_pkg->sdate( $hash{last_bill} );
$cust_bill_pkg->edate( $sdate - 86399 ); #60s*60m*24h-1
+ $cust_bill_pkg->edate( $time ) if $options{cancel};
} else { #if ( $part_pkg->option('recur_temporality', 1) eq 'upcoming' ) {
$cust_bill_pkg->sdate( $sdate );
$cust_bill_pkg->edate( $cust_pkg->bill );
+ #$cust_bill_pkg->edate( $time ) if $options{cancel};
}
$cust_bill_pkg->pkgpart_override($part_pkg->pkgpart)
@@ -2754,7 +3046,7 @@ sub _make_lines {
###
my $error =
- $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg);
+ $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg, $options{invoice_time}, $real_pkgpart, \%options);
return $error if $error;
push @$cust_bill_pkgs, $cust_bill_pkg;
@@ -2773,6 +3065,9 @@ sub _handle_taxes {
my $taxlisthash = shift;
my $cust_bill_pkg = shift;
my $cust_pkg = shift;
+ my $invoice_time = shift;
+ my $real_pkgpart = shift;
+ my $options = shift;
my %cust_bill_pkg = ();
my %taxes = ();
@@ -2780,8 +3075,8 @@ sub _handle_taxes {
my @classes;
#push @classes, $cust_bill_pkg->usage_classes if $cust_bill_pkg->type eq 'U';
push @classes, $cust_bill_pkg->usage_classes if $cust_bill_pkg->usage;
- push @classes, 'setup' if $cust_bill_pkg->setup;
- push @classes, 'recur' if $cust_bill_pkg->recur;
+ push @classes, 'setup' if ($cust_bill_pkg->setup && !$options->{cancel});
+ push @classes, 'recur' if ($cust_bill_pkg->recur && !$options->{cancel});
if ( $self->tax !~ /Y/i && $self->payby ne 'COMP' ) {
@@ -2835,6 +3130,10 @@ sub _handle_taxes {
@taxes = qsearch( 'cust_main_county', \%taxhash_elim );
}
+ @taxes = grep { ! $_->taxname or ! $self->tax_exemption($_->taxname) }
+ @taxes
+ if $self->cust_main_exemption; #just to be safe
+
if ( $conf->exists('tax-pkg_address') && $cust_pkg->locationnum ) {
foreach (@taxes) {
$_->set('pkgnum', $cust_pkg->pkgnum );
@@ -2847,32 +3146,53 @@ sub _handle_taxes {
$taxes{'recur'} = [ @taxes ];
$taxes{$_} = [ @taxes ] foreach (@classes);
- # maybe eliminate this entirely, along with all the 0% records
- unless ( @taxes ) {
- return
- "fatal: can't find tax rate for state/county/country/taxclass ".
- join('/', map $taxhash{$_}, qw(state county country taxclass) );
- }
+ # # maybe eliminate this entirely, along with all the 0% records
+ # unless ( @taxes ) {
+ # return
+ # "fatal: can't find tax rate for state/county/country/taxclass ".
+ # join('/', map $taxhash{$_}, qw(state county country taxclass) );
+ # }
} #if $conf->exists('enable_taxproducts') ...
}
my @display = ();
- if ( $conf->exists('separate_usage') ) {
+ my $separate = $conf->exists('separate_usage');
+ my $usage_mandate = $cust_pkg->part_pkg->option('usage_mandate', 'Hush!');
+ if ( $separate || $cust_bill_pkg->hidden || $usage_mandate ) {
+
+ my $temp_pkg = new FS::cust_pkg { pkgpart => $real_pkgpart };
+ my %hash = $cust_bill_pkg->hidden # maybe for all bill linked?
+ ? ( 'section' => $temp_pkg->part_pkg->categoryname )
+ : ();
+
my $section = $cust_pkg->part_pkg->option('usage_section', 'Hush!');
my $summary = $cust_pkg->part_pkg->option('summarize_usage', 'Hush!');
- push @display, new FS::cust_bill_pkg_display { type => 'S' };
- push @display, new FS::cust_bill_pkg_display { type => 'R' };
- push @display, new FS::cust_bill_pkg_display { type => 'U',
- section => $section
- };
- if ($section && $summary) {
- $display[2]->post_total('Y');
+ if ( $separate ) {
+ push @display, new FS::cust_bill_pkg_display { type => 'S', %hash };
+ push @display, new FS::cust_bill_pkg_display { type => 'R', %hash };
+ } else {
+ push @display, new FS::cust_bill_pkg_display
+ { type => '',
+ %hash,
+ ( ( $usage_mandate ) ? ( 'summary' => 'Y' ) : () ),
+ };
+ }
+
+ if ($separate && $section && $summary) {
push @display, new FS::cust_bill_pkg_display { type => 'U',
summary => 'Y',
- }
+ %hash,
+ };
+ }
+ if ($usage_mandate || $section && $summary) {
+ $hash{post_total} = 'Y';
}
+
+ $hash{section} = $section if ($separate || $usage_mandate);
+ push @display, new FS::cust_bill_pkg_display { type => 'U', %hash };
+
}
$cust_bill_pkg->set('display', \@display);
@@ -2881,19 +3201,51 @@ sub _handle_taxes {
my @taxes = @{ $taxes{$key} || [] };
my $tax_cust_bill_pkg = $tax_cust_bill_pkg{$key};
+ my %localtaxlisthash = ();
foreach my $tax ( @taxes ) {
- my $taxname = ref( $tax ). ' taxnum'. $tax->taxnum;
+ my $taxname = ref( $tax ). ' '. $tax->taxnum;
# $taxname .= ' pkgnum'. $cust_pkg->pkgnum.
# ' locationnum'. $cust_pkg->locationnum
# if $conf->exists('tax-pkg_address') && $cust_pkg->locationnum;
- if ( exists( $taxlisthash->{ $taxname } ) ) {
- push @{ $taxlisthash->{ $taxname } }, $tax_cust_bill_pkg;
- }else{
- $taxlisthash->{ $taxname } = [ $tax, $tax_cust_bill_pkg ];
+ $taxlisthash->{ $taxname } ||= [ $tax ];
+ push @{ $taxlisthash->{ $taxname } }, $tax_cust_bill_pkg;
+
+ $localtaxlisthash{ $taxname } ||= [ $tax ];
+ push @{ $localtaxlisthash{ $taxname } }, $tax_cust_bill_pkg;
+
+ }
+
+ warn "finding taxed taxes...\n" if $DEBUG > 2;
+ foreach my $tax ( keys %localtaxlisthash ) {
+ my $tax_object = shift @{ $localtaxlisthash{$tax} };
+ warn "found possible taxed tax ". $tax_object->taxname. " we call $tax\n"
+ if $DEBUG > 2;
+ next unless $tax_object->can('tax_on_tax');
+
+ foreach my $tot ( $tax_object->tax_on_tax( $self ) ) {
+ my $totname = ref( $tot ). ' '. $tot->taxnum;
+
+ warn "checking $totname which we call ". $tot->taxname. " as applicable\n"
+ if $DEBUG > 2;
+ next unless exists( $localtaxlisthash{ $totname } ); # only increase
+ # existing taxes
+ warn "adding $totname to taxed taxes\n" if $DEBUG > 2;
+ my $hashref_or_error =
+ $tax_object->taxline( $localtaxlisthash{$tax},
+ 'custnum' => $self->custnum,
+ 'invoice_time' => $invoice_time,
+ );
+ return $hashref_or_error
+ unless ref($hashref_or_error);
+
+ $taxlisthash->{ $totname } ||= [ $tot ];
+ push @{ $taxlisthash->{ $totname } }, $hashref_or_error->{amount};
+
}
}
+
}
'';
@@ -2912,6 +3264,7 @@ sub _gather_taxes {
unless (@taxclassnums) {
@taxclassnums = map { $_->taxclassnum }
+ grep { $_->taxable eq 'Y' }
$part_pkg->part_pkg_taxrate('cch', $geocode, $class);
}
warn "Found taxclassnum values of ". join(',', @taxclassnums)
@@ -2935,7 +3288,7 @@ sub _gather_taxes {
}
-=item collect OPTIONS
+=item collect [ HASHREF | OPTION => VALUE ... ]
(Attempt to) collect money for this customer's outstanding invoices (see
L<FS::cust_bill>). Usually used after the bill method.
@@ -2960,25 +3313,24 @@ Use this time when deciding when to print invoices and late notices on those inv
Retry card/echeck/LEC transactions even when not scheduled by invoice events.
-=item quiet
-
-set true to surpress email card/ACH decline notices.
-
=item check_freq
"1d" for the traditional, daily events (the default), or "1m" for the new monthly events (part_event.check_freq)
-=item payby
+=item quiet
-allows for one time override of normal customer billing method
+set true to surpress email card/ACH decline notices.
=item debug
Debugging level. Default is 0 (no debugging), or can be set to 1 (passed-in options), 2 (traces progress), 3 (more information), or 4 (include full search queries)
-
=back
+# =item payby
+#
+# allows for one time override of normal customer billing method
+
=cut
sub collect {
@@ -3016,12 +3368,107 @@ sub collect {
}
}
+ my $error = $self->do_cust_event(
+ 'debug' => ( $options{'debug'} || 0 ),
+ 'time' => $invoice_time,
+ 'check_freq' => $options{'check_freq'},
+ 'stage' => 'collect',
+ );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
+=item do_cust_event [ HASHREF | OPTION => VALUE ... ]
+
+Runs billing events; see L<FS::part_event> and the billing events web
+interface.
+
+If there is an error, returns the error, otherwise returns false.
+
+Options are passed as name-value pairs.
+
+Currently available options are:
+
+=over 4
+
+=item time
+
+Use this time when deciding when to print invoices and late notices on those invoices. The default is now. It is specified as a UNIX timestamp; see L<perlfunc/"time">). Also see L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=item check_freq
+
+"1d" for the traditional, daily events (the default), or "1m" for the new monthly events (part_event.check_freq)
+
+=item stage
+
+"collect" (the default) or "pre-bill"
+
+=item quiet
+
+set true to surpress email card/ACH decline notices.
+
+=item debug
+
+Debugging level. Default is 0 (no debugging), or can be set to 1 (passed-in options), 2 (traces progress), 3 (more information), or 4 (include full search queries)
+
+=cut
+
+# =item payby
+#
+# allows for one time override of normal customer billing method
+
+# =item retry
+#
+# Retry card/echeck/LEC transactions even when not scheduled by invoice events.
+
+sub do_cust_event {
+ my( $self, %options ) = @_;
+ my $time = $options{'time'} || time;
+
+ #put below somehow?
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ $self->select_for_update; #mutex
+
+ if ( $DEBUG ) {
+ my $balance = $self->balance;
+ warn "$me do_cust_event customer ". $self->custnum. ": balance $balance\n"
+ }
+
+# if ( exists($options{'retry_card'}) ) {
+# carp 'retry_card option passed to collect is deprecated; use retry';
+# $options{'retry'} ||= $options{'retry_card'};
+# }
+# if ( exists($options{'retry'}) && $options{'retry'} ) {
+# my $error = $self->retry_realtime;
+# if ( $error ) {
+# $dbh->rollback if $oldAutoCommit;
+# return $error;
+# }
+# }
+
# false laziness w/pay_batch::import_results
my $due_cust_event = $self->due_cust_event(
'debug' => ( $options{'debug'} || 0 ),
- 'time' => $invoice_time,
+ 'time' => $time,
'check_freq' => $options{'check_freq'},
+ 'stage' => ( $options{'stage'} || 'collect' ),
);
unless( ref($due_cust_event) ) {
$dbh->rollback if $oldAutoCommit;
@@ -3033,7 +3480,7 @@ sub collect {
#XXX lock event
#re-eval event conditions (a previous event could have changed things)
- unless ( $cust_event->test_conditions( 'time' => $invoice_time ) ) {
+ unless ( $cust_event->test_conditions( 'time' => $time ) ) {
#don't leave stray "new/locked" records around
my $error = $cust_event->delete;
if ( $error ) {
@@ -3086,6 +3533,10 @@ options are:
Search only for events of this check frequency (how often events of this type are checked); currently "1d" (daily, the default) and "1m" (monthly) are recognized.
+=item stage
+
+"collect" (the default) or "pre-bill"
+
=item time
"Current time" for the events.
@@ -3141,7 +3592,7 @@ sub due_cust_event {
unless $opt{testonly};
###
- # 1: find possible events (initial search)
+ # find possible events (initial search)
###
my @cust_event = ();
@@ -3232,8 +3683,20 @@ sub due_cust_event {
" total possible cust events found in initial search\n"
if $DEBUG; # > 1;
+
+ ##
+ # test stage
+ ##
+
+ $opt{stage} ||= 'collect';
+ @cust_event =
+ grep { my $stage = $_->part_event->event_stage;
+ $opt{stage} eq $stage or ( ! $stage && $opt{stage} eq 'collect' )
+ }
+ @cust_event;
+
##
- # 2: test conditions
+ # test conditions
##
my %unsat = ();
@@ -3250,7 +3713,7 @@ sub due_cust_event {
if $DEBUG; # > 1;
##
- # 3: insert
+ # insert
##
unless( $opt{testonly} ) {
@@ -3268,7 +3731,7 @@ sub due_cust_event {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
##
- # 4: return
+ # return
##
warn " returning events: ". Dumper(@cust_event). "\n"
@@ -3368,6 +3831,10 @@ sub retry_realtime {
}
+# some horrid false laziness here to avoid refactor fallout
+# eventually realtime realtime_bop and realtime_refund_bop should go
+# away and be replaced by _new_realtime_bop and _new_realtime_refund_bop
+
=item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ]
Runs a realtime credit card, ACH (electronic check) or phone bill transaction
@@ -3401,7 +3868,12 @@ I<payunique> is a unique identifier for this payment.
=cut
sub realtime_bop {
- my( $self, $method, $amount, %options ) = @_;
+ my $self = shift;
+
+ return $self->_new_realtime_bop(@_)
+ if $self->_new_bop_required();
+
+ my( $method, $amount, %options ) = @_;
if ( $DEBUG ) {
warn "$me realtime_bop: $method $amount\n";
warn " $_ => $options{$_}\n" foreach keys %options;
@@ -3435,24 +3907,35 @@ sub realtime_bop {
return "Banned credit card" if $ban;
###
- # select a gateway
+ # set taxclass and trans_is_recur based on invnum if there is one
###
my $taxclass = '';
+ my $trans_is_recur = 0;
if ( $options{'invnum'} ) {
+
my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{'invnum'} } );
die "invnum ". $options{'invnum'}. " not found" unless $cust_bill;
- my @taxclasses =
- map { $_->part_pkg->taxclass }
+
+ my @part_pkg =
+ map { $_->part_pkg }
grep { $_ }
map { $_->cust_pkg }
$cust_bill->cust_bill_pkg;
- unless ( grep { $taxclasses[0] ne $_ } @taxclasses ) { #unless there are
- #different taxclasses
- $taxclass = $taxclasses[0];
- }
+
+ my @taxclasses = map $_->taxclass, @part_pkg;
+ $taxclass = $taxclasses[0]
+ unless grep { $taxclasses[0] ne $_ } @taxclasses; #unless there are
+ #different taxclasses
+ $trans_is_recur = 1
+ if grep { $_->freq ne '0' } @part_pkg;
+
}
+ ###
+ # select a gateway
+ ###
+
#look for an agent gateway override first
my $cardtype;
if ( $method eq 'CC' ) {
@@ -3580,16 +4063,15 @@ sub realtime_bop {
: $self->payissue;
$content{issue_number} = $payissue if $payissue;
- $content{recurring_billing} = 'YES'
- if qsearch('cust_pay', { 'custnum' => $self->custnum,
- 'payby' => 'CARD',
- 'payinfo' => $payinfo,
- } )
- || qsearch('cust_pay', { 'custnum' => $self->custnum,
- 'payby' => 'CARD',
- 'paymask' => $self->mask_payinfo('CARD', $payinfo),
- } );
-
+ if ( $self->_bop_recurring_billing( 'payinfo' => $payinfo,
+ 'trans_is_recur' => $trans_is_recur,
+ )
+ )
+ {
+ $content{recurring_billing} = 'YES';
+ $content{acct_code} = 'rebill'
+ if $conf->exists('credit_card-recurring_billing_acct_code');
+ }
} elsif ( $method eq 'ECHECK' ) {
( $content{account_number}, $content{routing_code} ) =
@@ -3648,15 +4130,17 @@ sub realtime_bop {
#okay, good to go, if we're a duplicate, cust_pay_pending will kick us out
my $cust_pay_pending = new FS::cust_pay_pending {
- 'custnum' => $self->custnum,
- #'invnum' => $options{'invnum'},
- 'paid' => $amount,
- '_date' => '',
- 'payby' => $method2payby{$method},
- 'payinfo' => $payinfo,
- 'paydate' => $paydate,
- 'status' => 'new',
- 'gatewaynum' => ( $payment_gateway ? $payment_gateway->gatewaynum : '' ),
+ 'custnum' => $self->custnum,
+ #'invnum' => $options{'invnum'},
+ 'paid' => $amount,
+ '_date' => '',
+ 'payby' => $method2payby{$method},
+ 'payinfo' => $payinfo,
+ 'paydate' => $paydate,
+ 'recurring_billing' => $content{recurring_billing},
+ 'pkgnum' => $options{'pkgnum'},
+ 'status' => 'new',
+ 'gatewaynum' => ( $payment_gateway ? $payment_gateway->gatewaynum : '' ),
};
$cust_pay_pending->payunique( $options{payunique} )
if defined($options{payunique}) && length($options{payunique});
@@ -3810,6 +4294,7 @@ sub realtime_bop {
'payinfo' => $payinfo,
'paybatch' => $paybatch,
'paydate' => $paydate,
+ 'pkgnum' => $options{'pkgnum'},
} );
#doesn't hurt to know, even though the dup check is in cust_pay_pending now
$cust_pay->payunique( $options{payunique} )
@@ -3912,7 +4397,13 @@ sub realtime_bop {
$template->compile()
or return "($perror) can't compile template: $Text::Template::ERROR";
- my $templ_hash = { error => $transaction->error_message };
+ my $templ_hash = {
+ 'company_name' =>
+ scalar( $conf->config('company_name', $self->agentnum ) ),
+ 'company_address' =>
+ join("\n", $conf->config('company_address', $self->agentnum ) ),
+ 'error' => $transaction->error_message,
+ };
my $error = send_email(
'from' => $conf->config('invoice_from', $self->agentnum ),
@@ -3942,25 +4433,912 @@ sub realtime_bop {
}
-=item fake_bop
+sub _bop_recurring_billing {
+ my( $self, %opt ) = @_;
+
+ my $method = $conf->config('credit_card-recurring_billing_flag');
+
+ if ( $method eq 'transaction_is_recur' ) {
+
+ return 1 if $opt{'trans_is_recur'};
+
+ } else {
+
+ my %hash = ( 'custnum' => $self->custnum,
+ 'payby' => 'CARD',
+ );
+
+ return 1
+ if qsearch('cust_pay', { %hash, 'payinfo' => $opt{'payinfo'} } )
+ || qsearch('cust_pay', { %hash, 'paymask' => $self->mask_payinfo('CARD',
+ $opt{'payinfo'} )
+ } );
+
+ }
+
+ return 0;
+
+}
+
+
+=item realtime_refund_bop METHOD [ OPTION => VALUE ... ]
+
+Refunds a realtime credit card, ACH (electronic check) or phone bill transaction
+via a Business::OnlinePayment realtime gateway. See
+L<http://420.am/business-onlinepayment> for supported gateways.
+
+Available methods are: I<CC>, I<ECHECK> and I<LEC>
+
+Available options are: I<amount>, I<reason>, I<paynum>, I<paydate>
+
+Most gateways require a reference to an original payment transaction to refund,
+so you probably need to specify a I<paynum>.
+
+I<amount> defaults to the original amount of the payment if not specified.
+
+I<reason> specifies a reason for the refund.
+
+I<paydate> specifies the expiration date for a credit card overriding the
+value from the customer record or the payment record. Specified as yyyy-mm-dd
+
+Implementation note: If I<amount> is unspecified or equal to the amount of the
+orignal payment, first an attempt is made to "void" the transaction via
+the gateway (to cancel a not-yet settled transaction) and then if that fails,
+the normal attempt is made to "refund" ("credit") the transaction via the
+gateway is attempted.
+
+#The additional options I<payname>, I<address1>, I<address2>, I<city>, I<state>,
+#I<zip>, I<payinfo> and I<paydate> are also available. Any of these options,
+#if set, will override the value from the customer record.
+
+#If an I<invnum> is specified, this payment (if successful) is applied to the
+#specified invoice. If you don't specify an I<invnum> you might want to
+#call the B<apply_payments> method.
=cut
-sub fake_bop {
- my( $self, $method, $amount, %options ) = @_;
+#some false laziness w/realtime_bop, not enough to make it worth merging
+#but some useful small subs should be pulled out
+sub realtime_refund_bop {
+ my $self = shift;
- if ( $options{'fake_failure'} ) {
- return "Error: No error; test failure requested with fake_failure";
+ return $self->_new_realtime_refund_bop(@_)
+ if $self->_new_bop_required();
+
+ my( $method, %options ) = @_;
+ if ( $DEBUG ) {
+ warn "$me realtime_refund_bop: $method refund\n";
+ warn " $_ => $options{$_}\n" foreach keys %options;
}
+ eval "use Business::OnlinePayment";
+ die $@ if $@;
+
+ ###
+ # look up the original payment and optionally a gateway for that payment
+ ###
+
+ my $cust_pay = '';
+ my $amount = $options{'amount'};
+
+ my( $processor, $login, $password, @bop_options ) ;
+ my( $auth, $order_number ) = ( '', '', '' );
+
+ if ( $options{'paynum'} ) {
+
+ warn " paynum: $options{paynum}\n" if $DEBUG > 1;
+ $cust_pay = qsearchs('cust_pay', { paynum=>$options{'paynum'} } )
+ or return "Unknown paynum $options{'paynum'}";
+ $amount ||= $cust_pay->paid;
+
+ $cust_pay->paybatch =~ /^((\d+)\-)?(\w+):\s*([\w\-\/ ]*)(:([\w\-]+))?$/
+ or return "Can't parse paybatch for paynum $options{'paynum'}: ".
+ $cust_pay->paybatch;
+ my $gatewaynum = '';
+ ( $gatewaynum, $processor, $auth, $order_number ) = ( $2, $3, $4, $6 );
+
+ if ( $gatewaynum ) { #gateway for the payment to be refunded
+
+ my $payment_gateway =
+ qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } );
+ die "payment gateway $gatewaynum not found"
+ unless $payment_gateway;
+
+ $processor = $payment_gateway->gateway_module;
+ $login = $payment_gateway->gateway_username;
+ $password = $payment_gateway->gateway_password;
+ @bop_options = $payment_gateway->options;
+
+ } else { #try the default gateway
+
+ my( $conf_processor, $unused_action );
+ ( $conf_processor, $login, $password, $unused_action, @bop_options ) =
+ $self->default_payment_gateway($method);
+
+ return "processor of payment $options{'paynum'} $processor does not".
+ " match default processor $conf_processor"
+ unless $processor eq $conf_processor;
+
+ }
+
+
+ } else { # didn't specify a paynum, so look for agent gateway overrides
+ # like a normal transaction
+
+ my $cardtype;
+ if ( $method eq 'CC' ) {
+ $cardtype = cardtype($self->payinfo);
+ } elsif ( $method eq 'ECHECK' ) {
+ $cardtype = 'ACH';
+ } else {
+ $cardtype = $method;
+ }
+ my $override =
+ qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => $cardtype,
+ taxclass => '', } )
+ || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
+ cardtype => '',
+ taxclass => '', } );
+
+ if ( $override ) { #use a payment gateway override
+
+ my $payment_gateway = $override->payment_gateway;
+
+ $processor = $payment_gateway->gateway_module;
+ $login = $payment_gateway->gateway_username;
+ $password = $payment_gateway->gateway_password;
+ #$action = $payment_gateway->gateway_action;
+ @bop_options = $payment_gateway->options;
+
+ } else { #use the standard settings from the config
+
+ my $unused_action;
+ ( $processor, $login, $password, $unused_action, @bop_options ) =
+ $self->default_payment_gateway($method);
+
+ }
+
+ }
+ return "neither amount nor paynum specified" unless $amount;
+
+ my %content = (
+ 'type' => $method,
+ 'login' => $login,
+ 'password' => $password,
+ 'order_number' => $order_number,
+ 'amount' => $amount,
+ 'referer' => 'http://cleanwhisker.420.am/', #XXX fix referer :/
+ );
+ $content{authorization} = $auth
+ if length($auth); #echeck/ACH transactions have an order # but no auth
+ #(at least with authorize.net)
+
+ my $disable_void_after;
+ if ($conf->exists('disable_void_after')
+ && $conf->config('disable_void_after') =~ /^(\d+)$/) {
+ $disable_void_after = $1;
+ }
+
+ #first try void if applicable
+ if ( $cust_pay && $cust_pay->paid == $amount
+ && (
+ ( not defined($disable_void_after) )
+ || ( time < ($cust_pay->_date + $disable_void_after ) )
+ )
+ ) {
+ warn " attempting void\n" if $DEBUG > 1;
+ my $void = new Business::OnlinePayment( $processor, @bop_options );
+ $void->content( 'action' => 'void', %content );
+ $void->submit();
+ if ( $void->is_success ) {
+ my $error = $cust_pay->void($options{'reason'});
+ if ( $error ) {
+ # gah, even with transactions.
+ my $e = 'WARNING: Card/ACH voided but database not updated - '.
+ "error voiding payment: $error";
+ warn $e;
+ return $e;
+ }
+ warn " void successful\n" if $DEBUG > 1;
+ return '';
+ }
+ }
+
+ warn " void unsuccessful, trying refund\n"
+ if $DEBUG > 1;
+
+ #massage data
+ my $address = $self->address1;
+ $address .= ", ". $self->address2 if $self->address2;
+
+ my($payname, $payfirst, $paylast);
+ if ( $self->payname && $method ne 'ECHECK' ) {
+ $payname = $self->payname;
+ $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/
+ or return "Illegal payname $payname";
+ ($payfirst, $paylast) = ($1, $2);
+ } else {
+ $payfirst = $self->getfield('first');
+ $paylast = $self->getfield('last');
+ $payname = "$payfirst $paylast";
+ }
+
+ my @invoicing_list = $self->invoicing_list_emailonly;
+ if ( $conf->exists('emailinvoiceautoalways')
+ || $conf->exists('emailinvoiceauto') && ! @invoicing_list
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $self->all_emails;
+ }
+
+ my $email = ($conf->exists('business-onlinepayment-email-override'))
+ ? $conf->config('business-onlinepayment-email-override')
+ : $invoicing_list[0];
+
+ my $payip = exists($options{'payip'})
+ ? $options{'payip'}
+ : $self->payip;
+ $content{customer_ip} = $payip
+ if length($payip);
+
+ my $payinfo = '';
+ if ( $method eq 'CC' ) {
+
+ if ( $cust_pay ) {
+ $content{card_number} = $payinfo = $cust_pay->payinfo;
+ (exists($options{'paydate'}) ? $options{'paydate'} : $cust_pay->paydate)
+ =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/ &&
+ ($content{expiration} = "$2/$1"); # where available
+ } else {
+ $content{card_number} = $payinfo = $self->payinfo;
+ (exists($options{'paydate'}) ? $options{'paydate'} : $self->paydate)
+ =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ $content{expiration} = "$2/$1";
+ }
+
+ } elsif ( $method eq 'ECHECK' ) {
+
+ if ( $cust_pay ) {
+ $payinfo = $cust_pay->payinfo;
+ } else {
+ $payinfo = $self->payinfo;
+ }
+ ( $content{account_number}, $content{routing_code} )= split('@', $payinfo );
+ $content{bank_name} = $self->payname;
+ $content{account_type} = 'CHECKING';
+ $content{account_name} = $payname;
+ $content{customer_org} = $self->company ? 'B' : 'I';
+ $content{customer_ssn} = $self->ss;
+ } elsif ( $method eq 'LEC' ) {
+ $content{phone} = $payinfo = $self->payinfo;
+ }
+
+ #then try refund
+ my $refund = new Business::OnlinePayment( $processor, @bop_options );
+ my %sub_content = $refund->content(
+ 'action' => 'credit',
+ 'customer_id' => $self->custnum,
+ 'last_name' => $paylast,
+ 'first_name' => $payfirst,
+ 'name' => $payname,
+ 'address' => $address,
+ 'city' => $self->city,
+ 'state' => $self->state,
+ 'zip' => $self->zip,
+ 'country' => $self->country,
+ 'email' => $email,
+ 'phone' => $self->daytime || $self->night,
+ %content, #after
+ );
+ warn join('', map { " $_ => $sub_content{$_}\n" } keys %sub_content )
+ if $DEBUG > 1;
+ $refund->submit();
+
+ return "$processor error: ". $refund->error_message
+ unless $refund->is_success();
+
my %method2payby = (
'CC' => 'CARD',
'ECHECK' => 'CHEK',
'LEC' => 'LECB',
);
+ my $paybatch = "$processor:". $refund->authorization;
+ $paybatch .= ':'. $refund->order_number
+ if $refund->can('order_number') && $refund->order_number;
+
+ while ( $cust_pay && $cust_pay->unapplied < $amount ) {
+ my @cust_bill_pay = $cust_pay->cust_bill_pay;
+ last unless @cust_bill_pay;
+ my $cust_bill_pay = pop @cust_bill_pay;
+ my $error = $cust_bill_pay->delete;
+ last if $error;
+ }
+
+ my $cust_refund = new FS::cust_refund ( {
+ 'custnum' => $self->custnum,
+ 'paynum' => $options{'paynum'},
+ 'refund' => $amount,
+ '_date' => '',
+ 'payby' => $method2payby{$method},
+ 'payinfo' => $payinfo,
+ 'paybatch' => $paybatch,
+ 'reason' => $options{'reason'} || 'card or ACH refund',
+ } );
+ my $error = $cust_refund->insert;
+ if ( $error ) {
+ $cust_refund->paynum(''); #try again with no specific paynum
+ my $error2 = $cust_refund->insert;
+ if ( $error2 ) {
+ # gah, even with transactions.
+ my $e = 'WARNING: Card/ACH refunded but database not updated - '.
+ "error inserting refund ($processor): $error2".
+ " (previously tried insert with paynum #$options{'paynum'}" .
+ ": $error )";
+ warn $e;
+ return $e;
+ }
+ }
+
+ ''; #no error
+
+}
+
+# does the configuration indicate the new bop routines are required?
+
+sub _new_bop_required {
+ my $self = shift;
+
+ my $botpp = 'Business::OnlineThirdPartyPayment';
+
+ return 1
+ if ( $conf->config('business-onlinepayment-namespace') eq $botpp ||
+ scalar( grep { $_->gateway_namespace eq $botpp }
+ qsearch( 'payment_gateway', { 'disabled' => '' } )
+ )
+ )
+ ;
+
+ '';
+}
+
+
+=item realtime_collect [ OPTION => VALUE ... ]
+
+Runs a realtime credit card, ACH (electronic check) or phone bill transaction
+via a Business::OnlinePayment or Business::OnlineThirdPartyPayment realtime
+gateway. See L<http://420.am/business-onlinepayment> and
+L<http://420.am/business-onlinethirdpartypayment> for supported gateways.
+
+On failure returns an error message.
+
+Returns false or a hashref upon success. The hashref contains keys popup_url reference, and collectitems. The first is a URL to which a browser should be redirected for completion of collection. The second is a reference id for the transaction suitable for the end user. The collectitems is a reference to a list of name value pairs suitable for assigning to a html form and posted to popup_url.
+
+Available options are: I<method>, I<amount>, I<description>, I<invnum>, I<quiet>, I<paynum_ref>, I<payunique>, I<session_id>, I<pkgnum>
+
+I<method> is one of: I<CC>, I<ECHECK> and I<LEC>. If none is specified
+then it is deduced from the customer record.
+
+If no I<amount> is specified, then the customer balance is used.
+
+The additional options I<payname>, I<address1>, I<address2>, I<city>, I<state>,
+I<zip>, I<payinfo> and I<paydate> are also available. Any of these options,
+if set, will override the value from the customer record.
+
+I<description> is a free-text field passed to the gateway. It defaults to
+"Internet services".
+
+If an I<invnum> is specified, this payment (if successful) is applied to the
+specified invoice. If you don't specify an I<invnum> you might want to
+call the B<apply_payments> method.
+
+I<quiet> can be set true to surpress email decline notices.
+
+I<paynum_ref> can be set to a scalar reference. It will be filled in with the
+resulting paynum, if any.
+
+I<payunique> is a unique identifier for this payment.
+
+I<session_id> is a session identifier associated with this payment.
+
+I<depend_jobnum> allows payment capture to unlock export jobs
+
+=cut
+
+sub realtime_collect {
+ my( $self, %options ) = @_;
+
+ if ( $DEBUG ) {
+ warn "$me realtime_collect:\n";
+ warn " $_ => $options{$_}\n" foreach keys %options;
+ }
+
+ $options{amount} = $self->balance unless exists( $options{amount} );
+ $options{method} = FS::payby->payby2bop($self->payby)
+ unless exists( $options{method} );
+
+ return $self->realtime_bop({%options});
+
+}
+
+=item _realtime_bop { [ ARG => VALUE ... ] }
+
+Runs a realtime credit card, ACH (electronic check) or phone bill transaction
+via a Business::OnlinePayment realtime gateway. See
+L<http://420.am/business-onlinepayment> for supported gateways.
+
+Required arguments in the hashref are I<method>, and I<amount>
+
+Available methods are: I<CC>, I<ECHECK> and I<LEC>
+
+Available optional arguments are: I<description>, I<invnum>, I<quiet>, I<paynum_ref>, I<payunique>, I<session_id>
+
+The additional options I<payname>, I<address1>, I<address2>, I<city>, I<state>,
+I<zip>, I<payinfo> and I<paydate> are also available. Any of these options,
+if set, will override the value from the customer record.
+
+I<description> is a free-text field passed to the gateway. It defaults to
+"Internet services".
+
+If an I<invnum> is specified, this payment (if successful) is applied to the
+specified invoice. If you don't specify an I<invnum> you might want to
+call the B<apply_payments> method.
+
+I<quiet> can be set true to surpress email decline notices.
+
+I<paynum_ref> can be set to a scalar reference. It will be filled in with the
+resulting paynum, if any.
+
+I<payunique> is a unique identifier for this payment.
+
+I<session_id> is a session identifier associated with this payment.
+
+I<depend_jobnum> allows payment capture to unlock export jobs
+
+(moved from cust_bill) (probably should get realtime_{card,ach,lec} here too)
+
+=cut
+
+# some helper routines
+sub _payment_gateway {
+ my ($self, $options) = @_;
+
+ $options->{payment_gateway} = $self->agent->payment_gateway( %$options )
+ unless exists($options->{payment_gateway});
+
+ $options->{payment_gateway};
+}
+
+sub _bop_auth {
+ my ($self, $options) = @_;
+
+ (
+ 'login' => $options->{payment_gateway}->gateway_username,
+ 'password' => $options->{payment_gateway}->gateway_password,
+ );
+}
+
+sub _bop_options {
+ my ($self, $options) = @_;
+
+ $options->{payment_gateway}->gatewaynum
+ ? $options->{payment_gateway}->options
+ : @{ $options->{payment_gateway}->get('options') };
+}
+
+sub _bop_defaults {
+ my ($self, $options) = @_;
+
+ $options->{description} ||= 'Internet services';
+ $options->{payinfo} = $self->payinfo unless exists( $options->{payinfo} );
+ $options->{invnum} ||= '';
+ $options->{payname} = $self->payname unless exists( $options->{payname} );
+}
+
+sub _bop_content {
+ my ($self, $options) = @_;
+ my %content = ();
+
+ $content{address} = exists($options->{'address1'})
+ ? $options->{'address1'}
+ : $self->address1;
+ my $address2 = exists($options->{'address2'})
+ ? $options->{'address2'}
+ : $self->address2;
+ $content{address} .= ", ". $address2 if length($address2);
+
+ my $payip = exists($options->{'payip'}) ? $options->{'payip'} : $self->payip;
+ $content{customer_ip} = $payip if length($payip);
+
+ $content{invoice_number} = $options->{'invnum'}
+ if exists($options->{'invnum'}) && length($options->{'invnum'});
+
+ $content{email_customer} =
+ ( $conf->exists('business-onlinepayment-email_customer')
+ || $conf->exists('business-onlinepayment-email-override') );
+
+ $content{payfirst} = $self->getfield('first');
+ $content{paylast} = $self->getfield('last');
+
+ $content{account_name} = "$content{payfirst} $content{paylast}"
+ if $options->{method} eq 'ECHECK';
+
+ $content{name} = $options->{payname};
+ $content{name} = $content{account_name} if exists($content{account_name});
+
+ $content{city} = exists($options->{city})
+ ? $options->{city}
+ : $self->city;
+ $content{state} = exists($options->{state})
+ ? $options->{state}
+ : $self->state;
+ $content{zip} = exists($options->{zip})
+ ? $options->{'zip'}
+ : $self->zip;
+ $content{country} = exists($options->{country})
+ ? $options->{country}
+ : $self->country;
+ $content{referer} = 'http://cleanwhisker.420.am/'; #XXX fix referer :/
+ $content{phone} = $self->daytime || $self->night;
+
+ (%content);
+}
+
+my %bop_method2payby = (
+ 'CC' => 'CARD',
+ 'ECHECK' => 'CHEK',
+ 'LEC' => 'LECB',
+);
+
+sub _new_realtime_bop {
+ my $self = shift;
+
+ my %options = ();
+ if (ref($_[0]) eq 'HASH') {
+ %options = %{$_[0]};
+ } else {
+ my ( $method, $amount ) = ( shift, shift );
+ %options = @_;
+ $options{method} = $method;
+ $options{amount} = $amount;
+ }
+
+ if ( $DEBUG ) {
+ warn "$me realtime_bop (new): $options{method} $options{amount}\n";
+ warn " $_ => $options{$_}\n" foreach keys %options;
+ }
+
+ return $self->fake_bop(%options) if $options{'fake'};
+
+ $self->_bop_defaults(\%options);
+
+ ###
+ # set trans_is_recur based on invnum if there is one
+ ###
+
+ my $trans_is_recur = 0;
+ if ( $options{'invnum'} ) {
+
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{'invnum'} } );
+ die "invnum ". $options{'invnum'}. " not found" unless $cust_bill;
+
+ my @part_pkg =
+ map { $_->part_pkg }
+ grep { $_ }
+ map { $_->cust_pkg }
+ $cust_bill->cust_bill_pkg;
+
+ $trans_is_recur = 1
+ if grep { $_->freq ne '0' } @part_pkg;
+
+ }
+
+ ###
+ # select a gateway
+ ###
+
+ my $payment_gateway = $self->_payment_gateway( \%options );
+ my $namespace = $payment_gateway->gateway_namespace;
+
+ eval "use $namespace";
+ die $@ if $@;
+
+ ###
+ # check for banned credit card/ACH
+ ###
+
+ my $ban = qsearchs('banned_pay', {
+ 'payby' => $bop_method2payby{$options{method}},
+ 'payinfo' => md5_base64($options{payinfo}),
+ } );
+ return "Banned credit card" if $ban;
+
+ ###
+ # massage data
+ ###
+
+ my (%bop_content) = $self->_bop_content(\%options);
+
+ if ( $options{method} ne 'ECHECK' ) {
+ $options{payname} =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/
+ or return "Illegal payname $options{payname}";
+ ($bop_content{payfirst}, $bop_content{paylast}) = ($1, $2);
+ }
+
+ my @invoicing_list = $self->invoicing_list_emailonly;
+ if ( $conf->exists('emailinvoiceautoalways')
+ || $conf->exists('emailinvoiceauto') && ! @invoicing_list
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $self->all_emails;
+ }
+
+ my $email = ($conf->exists('business-onlinepayment-email-override'))
+ ? $conf->config('business-onlinepayment-email-override')
+ : $invoicing_list[0];
+
+ my $paydate = '';
+ my %content = ();
+ if ( $namespace eq 'Business::OnlinePayment' && $options{method} eq 'CC' ) {
+
+ $content{card_number} = $options{payinfo};
+ $paydate = exists($options{'paydate'})
+ ? $options{'paydate'}
+ : $self->paydate;
+ $paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ $content{expiration} = "$2/$1";
+
+ my $paycvv = exists($options{'paycvv'})
+ ? $options{'paycvv'}
+ : $self->paycvv;
+ $content{cvv2} = $paycvv
+ if length($paycvv);
+
+ my $paystart_month = exists($options{'paystart_month'})
+ ? $options{'paystart_month'}
+ : $self->paystart_month;
+
+ my $paystart_year = exists($options{'paystart_year'})
+ ? $options{'paystart_year'}
+ : $self->paystart_year;
+
+ $content{card_start} = "$paystart_month/$paystart_year"
+ if $paystart_month && $paystart_year;
+
+ my $payissue = exists($options{'payissue'})
+ ? $options{'payissue'}
+ : $self->payissue;
+ $content{issue_number} = $payissue if $payissue;
+
+ if ( $self->_bop_recurring_billing( 'payinfo' => $options{'payinfo'},
+ 'trans_is_recur' => $trans_is_recur,
+ )
+ )
+ {
+ $content{recurring_billing} = 'YES';
+ $content{acct_code} = 'rebill'
+ if $conf->exists('credit_card-recurring_billing_acct_code');
+ }
+
+ } elsif ( $namespace eq 'Business::OnlinePayment' && $options{method} eq 'ECHECK' ){
+ ( $content{account_number}, $content{routing_code} ) =
+ split('@', $options{payinfo});
+ $content{bank_name} = $options{payname};
+ $content{bank_state} = exists($options{'paystate'})
+ ? $options{'paystate'}
+ : $self->getfield('paystate');
+ $content{account_type} = exists($options{'paytype'})
+ ? uc($options{'paytype'}) || 'CHECKING'
+ : uc($self->getfield('paytype')) || 'CHECKING';
+ $content{customer_org} = $self->company ? 'B' : 'I';
+ $content{state_id} = exists($options{'stateid'})
+ ? $options{'stateid'}
+ : $self->getfield('stateid');
+ $content{state_id_state} = exists($options{'stateid_state'})
+ ? $options{'stateid_state'}
+ : $self->getfield('stateid_state');
+ $content{customer_ssn} = exists($options{'ss'})
+ ? $options{'ss'}
+ : $self->ss;
+ } elsif ( $namespace eq 'Business::OnlinePayment' && $options{method} eq 'LEC' ) {
+ $content{phone} = $options{payinfo};
+ } elsif ( $namespace eq 'Business::OnlineThirdPartyPayment' ) {
+ #move along
+ } else {
+ #die an evil death
+ }
+
+ ###
+ # run transaction(s)
+ ###
+
+ my $balance = exists( $options{'balance'} )
+ ? $options{'balance'}
+ : $self->balance;
+
+ $self->select_for_update; #mutex ... just until we get our pending record in
+
+ #the checks here are intended to catch concurrent payments
+ #double-form-submission prevention is taken care of in cust_pay_pending::check
+
+ #check the balance
+ return "The customer's balance has changed; $options{method} transaction aborted."
+ if $self->balance < $balance;
+ #&& $self->balance < $options{amount}; #might as well anyway?
+
+ #also check and make sure there aren't *other* pending payments for this cust
+
+ my @pending = qsearch('cust_pay_pending', {
+ 'custnum' => $self->custnum,
+ 'status' => { op=>'!=', value=>'done' }
+ });
+ return "A payment is already being processed for this customer (".
+ join(', ', map 'paypendingnum '. $_->paypendingnum, @pending ).
+ "); $options{method} transaction aborted."
+ if scalar(@pending);
+
+ #okay, good to go, if we're a duplicate, cust_pay_pending will kick us out
+
+ my $cust_pay_pending = new FS::cust_pay_pending {
+ 'custnum' => $self->custnum,
+ #'invnum' => $options{'invnum'},
+ 'paid' => $options{amount},
+ '_date' => '',
+ 'payby' => $bop_method2payby{$options{method}},
+ 'payinfo' => $options{payinfo},
+ 'paydate' => $paydate,
+ 'recurring_billing' => $content{recurring_billing},
+ 'pkgnum' => $options{'pkgnum'},
+ 'status' => 'new',
+ 'gatewaynum' => $payment_gateway->gatewaynum || '',
+ 'session_id' => $options{session_id} || '',
+ 'jobnum' => $options{depend_jobnum} || '',
+ };
+ $cust_pay_pending->payunique( $options{payunique} )
+ if defined($options{payunique}) && length($options{payunique});
+ my $cpp_new_err = $cust_pay_pending->insert; #mutex lost when this is inserted
+ return $cpp_new_err if $cpp_new_err;
+
+ my( $action1, $action2 ) =
+ split( /\s*\,\s*/, $payment_gateway->gateway_action );
+
+ my $transaction = new $namespace( $payment_gateway->gateway_module,
+ $self->_bop_options(\%options),
+ );
+
+ $transaction->content(
+ 'type' => $options{method},
+ $self->_bop_auth(\%options),
+ 'action' => $action1,
+ 'description' => $options{'description'},
+ 'amount' => $options{amount},
+ #'invoice_number' => $options{'invnum'},
+ 'customer_id' => $self->custnum,
+ %bop_content,
+ 'reference' => $cust_pay_pending->paypendingnum, #for now
+ 'email' => $email,
+ %content, #after
+ );
+
+ $cust_pay_pending->status('pending');
+ my $cpp_pending_err = $cust_pay_pending->replace;
+ return $cpp_pending_err if $cpp_pending_err;
+
+ #config?
+ my $BOP_TESTING = 0;
+ my $BOP_TESTING_SUCCESS = 1;
+
+ unless ( $BOP_TESTING ) {
+ $transaction->submit();
+ } else {
+ if ( $BOP_TESTING_SUCCESS ) {
+ $transaction->is_success(1);
+ $transaction->authorization('fake auth');
+ } else {
+ $transaction->is_success(0);
+ $transaction->error_message('fake failure');
+ }
+ }
+
+ if ( $transaction->is_success() && $namespace eq 'Business::OnlineThirdPartyPayment' ) {
+
+ return { reference => $cust_pay_pending->paypendingnum,
+ map { $_ => $transaction->$_ } qw ( popup_url collectitems ) };
+
+ } elsif ( $transaction->is_success() && $action2 ) {
+
+ $cust_pay_pending->status('authorized');
+ my $cpp_authorized_err = $cust_pay_pending->replace;
+ return $cpp_authorized_err if $cpp_authorized_err;
+
+ my $auth = $transaction->authorization;
+ my $ordernum = $transaction->can('order_number')
+ ? $transaction->order_number
+ : '';
+
+ my $capture =
+ new Business::OnlinePayment( $payment_gateway->gateway_module,
+ $self->_bop_options(\%options),
+ );
+
+ my %capture = (
+ %content,
+ type => $options{method},
+ action => $action2,
+ $self->_bop_auth(\%options),
+ order_number => $ordernum,
+ amount => $options{amount},
+ authorization => $auth,
+ description => $options{'description'},
+ );
+
+ foreach my $field (qw( authorization_source_code returned_ACI
+ transaction_identifier validation_code
+ transaction_sequence_num local_transaction_date
+ local_transaction_time AVS_result_code )) {
+ $capture{$field} = $transaction->$field() if $transaction->can($field);
+ }
+
+ $capture->content( %capture );
+
+ $capture->submit();
+
+ unless ( $capture->is_success ) {
+ my $e = "Authorization successful but capture failed, custnum #".
+ $self->custnum. ': '. $capture->result_code.
+ ": ". $capture->error_message;
+ warn $e;
+ return $e;
+ }
+
+ }
+
+ ###
+ # remove paycvv after initial transaction
+ ###
+
+ #false laziness w/misc/process/payment.cgi - check both to make sure working
+ # correctly
+ if ( defined $self->dbdef_table->column('paycvv')
+ && length($self->paycvv)
+ && ! grep { $_ eq cardtype($options{payinfo}) } $conf->config('cvv-save')
+ ) {
+ my $error = $self->remove_cvv;
+ if ( $error ) {
+ warn "WARNING: error removing cvv: $error\n";
+ }
+ }
+
+ ###
+ # result handling
+ ###
+
+ $self->_realtime_bop_result( $cust_pay_pending, $transaction, %options );
+
+}
+
+=item fake_bop
+
+=cut
+
+sub fake_bop {
+ my $self = shift;
+
+ my %options = ();
+ if (ref($_[0]) eq 'HASH') {
+ %options = %{$_[0]};
+ } else {
+ my ( $method, $amount ) = ( shift, shift );
+ %options = @_;
+ $options{method} = $method;
+ $options{amount} = $amount;
+ }
+
+ if ( $options{'fake_failure'} ) {
+ return "Error: No error; test failure requested with fake_failure";
+ }
+
#my $paybatch = '';
- #if ( $payment_gateway ) { # agent override
+ #if ( $payment_gateway->gatewaynum ) { # agent override
# $paybatch = $payment_gateway->gatewaynum. '-';
#}
#
@@ -3975,9 +5353,9 @@ sub fake_bop {
my $cust_pay = new FS::cust_pay ( {
'custnum' => $self->custnum,
'invnum' => $options{'invnum'},
- 'paid' => $amount,
+ 'paid' => $options{amount},
'_date' => '',
- 'payby' => $method2payby{$method},
+ 'payby' => $bop_method2payby{$options{method}},
#'payinfo' => $payinfo,
'payinfo' => '4111111111111111',
'paybatch' => $paybatch,
@@ -4012,7 +5390,355 @@ sub fake_bop {
}
-=item default_payment_gateway
+
+# item _realtime_bop_result CUST_PAY_PENDING, BOP_OBJECT [ OPTION => VALUE ... ]
+#
+# Wraps up processing of a realtime credit card, ACH (electronic check) or
+# phone bill transaction.
+
+sub _realtime_bop_result {
+ my( $self, $cust_pay_pending, $transaction, %options ) = @_;
+ if ( $DEBUG ) {
+ warn "$me _realtime_bop_result: pending transaction ".
+ $cust_pay_pending->paypendingnum. "\n";
+ warn " $_ => $options{$_}\n" foreach keys %options;
+ }
+
+ my $payment_gateway = $options{payment_gateway}
+ or return "no payment gateway in arguments to _realtime_bop_result";
+
+ $cust_pay_pending->status($transaction->is_success() ? 'captured' : 'declined');
+ my $cpp_captured_err = $cust_pay_pending->replace;
+ return $cpp_captured_err if $cpp_captured_err;
+
+ if ( $transaction->is_success() ) {
+
+ my $paybatch = '';
+ if ( $payment_gateway->gatewaynum ) { # agent override
+ $paybatch = $payment_gateway->gatewaynum. '-';
+ }
+
+ $paybatch .= $payment_gateway->gateway_module. ":".
+ $transaction->authorization;
+
+ $paybatch .= ':'. $transaction->order_number
+ if $transaction->can('order_number')
+ && length($transaction->order_number);
+
+ my $cust_pay = new FS::cust_pay ( {
+ 'custnum' => $self->custnum,
+ 'invnum' => $options{'invnum'},
+ 'paid' => $cust_pay_pending->paid,
+ '_date' => '',
+ 'payby' => $cust_pay_pending->payby,
+ #'payinfo' => $payinfo,
+ 'paybatch' => $paybatch,
+ 'paydate' => $cust_pay_pending->paydate,
+ 'pkgnum' => $cust_pay_pending->pkgnum,
+ } );
+ #doesn't hurt to know, even though the dup check is in cust_pay_pending now
+ $cust_pay->payunique( $options{payunique} )
+ if defined($options{payunique}) && length($options{payunique});
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ #start a transaction, insert the cust_pay and set cust_pay_pending.status to done in a single transction
+
+ my $error = $cust_pay->insert($options{'manual'} ? ( 'manual' => 1 ) : () );
+
+ if ( $error ) {
+ $cust_pay->invnum(''); #try again with no specific invnum
+ my $error2 = $cust_pay->insert( $options{'manual'} ?
+ ( 'manual' => 1 ) : ()
+ );
+ if ( $error2 ) {
+ # gah. but at least we have a record of the state we had to abort in
+ # from cust_pay_pending now.
+ my $e = "WARNING: $options{method} captured but payment not recorded -".
+ " error inserting payment (". $payment_gateway->gateway_module.
+ "): $error2".
+ " (previously tried insert with invnum #$options{'invnum'}" .
+ ": $error ) - pending payment saved as paypendingnum ".
+ $cust_pay_pending->paypendingnum. "\n";
+ warn $e;
+ return $e;
+ }
+ }
+
+ my $jobnum = $cust_pay_pending->jobnum;
+ if ( $jobnum ) {
+ my $placeholder = qsearchs( 'queue', { 'jobnum' => $jobnum } );
+
+ unless ( $placeholder ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ my $e = "WARNING: $options{method} captured but job $jobnum not ".
+ "found for paypendingnum ". $cust_pay_pending->paypendingnum. "\n";
+ warn $e;
+ return $e;
+ }
+
+ $error = $placeholder->delete;
+
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ my $e = "WARNING: $options{method} captured but could not delete ".
+ "job $jobnum for paypendingnum ".
+ $cust_pay_pending->paypendingnum. ": $error\n";
+ warn $e;
+ return $e;
+ }
+
+ }
+
+ if ( $options{'paynum_ref'} ) {
+ ${ $options{'paynum_ref'} } = $cust_pay->paynum;
+ }
+
+ $cust_pay_pending->status('done');
+ $cust_pay_pending->statustext('captured');
+ $cust_pay_pending->paynum($cust_pay->paynum);
+ my $cpp_done_err = $cust_pay_pending->replace;
+
+ if ( $cpp_done_err ) {
+
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ my $e = "WARNING: $options{method} captured but payment not recorded - ".
+ "error updating status for paypendingnum ".
+ $cust_pay_pending->paypendingnum. ": $cpp_done_err \n";
+ warn $e;
+ return $e;
+
+ } else {
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return ''; #no error
+
+ }
+
+ } else {
+
+ my $perror = $payment_gateway->gateway_module. " error: ".
+ $transaction->error_message;
+
+ my $jobnum = $cust_pay_pending->jobnum;
+ if ( $jobnum ) {
+ my $placeholder = qsearchs( 'queue', { 'jobnum' => $jobnum } );
+
+ if ( $placeholder ) {
+ my $error = $placeholder->depended_delete;
+ $error ||= $placeholder->delete;
+ warn "error removing provisioning jobs after declined paypendingnum ".
+ $cust_pay_pending->paypendingnum. "\n";
+ } else {
+ my $e = "error finding job $jobnum for declined paypendingnum ".
+ $cust_pay_pending->paypendingnum. "\n";
+ warn $e;
+ }
+
+ }
+
+ unless ( $transaction->error_message ) {
+
+ my $t_response;
+ if ( $transaction->can('response_page') ) {
+ $t_response = {
+ 'page' => ( $transaction->can('response_page')
+ ? $transaction->response_page
+ : ''
+ ),
+ 'code' => ( $transaction->can('response_code')
+ ? $transaction->response_code
+ : ''
+ ),
+ 'headers' => ( $transaction->can('response_headers')
+ ? $transaction->response_headers
+ : ''
+ ),
+ };
+ } else {
+ $t_response .=
+ "No additional debugging information available for ".
+ $payment_gateway->gateway_module;
+ }
+
+ $perror .= "No error_message returned from ".
+ $payment_gateway->gateway_module. " -- ".
+ ( ref($t_response) ? Dumper($t_response) : $t_response );
+
+ }
+
+ if ( !$options{'quiet'} && !$realtime_bop_decline_quiet
+ && $conf->exists('emaildecline')
+ && grep { $_ ne 'POST' } $self->invoicing_list
+ && ! grep { $transaction->error_message =~ /$_/ }
+ $conf->config('emaildecline-exclude')
+ ) {
+ my @templ = $conf->config('declinetemplate');
+ my $template = new Text::Template (
+ TYPE => 'ARRAY',
+ SOURCE => [ map "$_\n", @templ ],
+ ) or return "($perror) can't create template: $Text::Template::ERROR";
+ $template->compile()
+ or return "($perror) can't compile template: $Text::Template::ERROR";
+
+ my $templ_hash = {
+ 'company_name' =>
+ scalar( $conf->config('company_name', $self->agentnum ) ),
+ 'company_address' =>
+ join("\n", $conf->config('company_address', $self->agentnum ) ),
+ 'error' => $transaction->error_message,
+ };
+
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from', $self->agentnum ),
+ 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ],
+ 'subject' => 'Your payment could not be processed',
+ 'body' => [ $template->fill_in(HASH => $templ_hash) ],
+ );
+
+ $perror .= " (also received error sending decline notification: $error)"
+ if $error;
+
+ }
+
+ $cust_pay_pending->status('done');
+ $cust_pay_pending->statustext("declined: $perror");
+ my $cpp_done_err = $cust_pay_pending->replace;
+ if ( $cpp_done_err ) {
+ my $e = "WARNING: $options{method} declined but pending payment not ".
+ "resolved - error updating status for paypendingnum ".
+ $cust_pay_pending->paypendingnum. ": $cpp_done_err \n";
+ warn $e;
+ $perror = "$e ($perror)";
+ }
+
+ return $perror;
+ }
+
+}
+
+=item realtime_botpp_capture CUST_PAY_PENDING [ OPTION => VALUE ... ]
+
+Verifies successful third party processing of a realtime credit card,
+ACH (electronic check) or phone bill transaction via a
+Business::OnlineThirdPartyPayment realtime gateway. See
+L<http://420.am/business-onlinethirdpartypayment> for supported gateways.
+
+Available options are: I<description>, I<invnum>, I<quiet>, I<paynum_ref>, I<payunique>
+
+The additional options I<payname>, I<city>, I<state>,
+I<zip>, I<payinfo> and I<paydate> are also available. Any of these options,
+if set, will override the value from the customer record.
+
+I<description> is a free-text field passed to the gateway. It defaults to
+"Internet services".
+
+If an I<invnum> is specified, this payment (if successful) is applied to the
+specified invoice. If you don't specify an I<invnum> you might want to
+call the B<apply_payments> method.
+
+I<quiet> can be set true to surpress email decline notices.
+
+I<paynum_ref> can be set to a scalar reference. It will be filled in with the
+resulting paynum, if any.
+
+I<payunique> is a unique identifier for this payment.
+
+Returns a hashref containing elements bill_error (which will be undefined
+upon success) and session_id of any associated session.
+
+=cut
+
+sub realtime_botpp_capture {
+ my( $self, $cust_pay_pending, %options ) = @_;
+ if ( $DEBUG ) {
+ warn "$me realtime_botpp_capture: pending transaction $cust_pay_pending\n";
+ warn " $_ => $options{$_}\n" foreach keys %options;
+ }
+
+ eval "use Business::OnlineThirdPartyPayment";
+ die $@ if $@;
+
+ ###
+ # select the gateway
+ ###
+
+ my $method = FS::payby->payby2bop($cust_pay_pending->payby);
+
+ my $payment_gateway = $cust_pay_pending->gatewaynum
+ ? qsearchs( 'payment_gateway',
+ { gatewaynum => $cust_pay_pending->gatewaynum }
+ )
+ : $self->agent->payment_gateway( 'method' => $method,
+ # 'invnum' => $cust_pay_pending->invnum,
+ # 'payinfo' => $cust_pay_pending->payinfo,
+ );
+
+ $options{payment_gateway} = $payment_gateway; # for the helper subs
+
+ ###
+ # massage data
+ ###
+
+ my @invoicing_list = $self->invoicing_list_emailonly;
+ if ( $conf->exists('emailinvoiceautoalways')
+ || $conf->exists('emailinvoiceauto') && ! @invoicing_list
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $self->all_emails;
+ }
+
+ my $email = ($conf->exists('business-onlinepayment-email-override'))
+ ? $conf->config('business-onlinepayment-email-override')
+ : $invoicing_list[0];
+
+ my %content = ();
+
+ $content{email_customer} =
+ ( $conf->exists('business-onlinepayment-email_customer')
+ || $conf->exists('business-onlinepayment-email-override') );
+
+ ###
+ # run transaction(s)
+ ###
+
+ my $transaction =
+ new Business::OnlineThirdPartyPayment( $payment_gateway->gateway_module,
+ $self->_bop_options(\%options),
+ );
+
+ $transaction->reference({ %options });
+
+ $transaction->content(
+ 'type' => $method,
+ $self->_bop_auth(\%options),
+ 'action' => 'Post Authorization',
+ 'description' => $options{'description'},
+ 'amount' => $cust_pay_pending->paid,
+ #'invoice_number' => $options{'invnum'},
+ 'customer_id' => $self->custnum,
+ 'referer' => 'http://cleanwhisker.420.am/',
+ 'reference' => $cust_pay_pending->paypendingnum,
+ 'email' => $email,
+ 'phone' => $self->daytime || $self->night,
+ %content, #after
+ # plus whatever is required for bogus capture avoidance
+ );
+
+ $transaction->submit();
+
+ my $error =
+ $self->_realtime_bop_result( $cust_pay_pending, $transaction, %options );
+
+ {
+ bill_error => $error,
+ session_id => $cust_pay_pending->session_id,
+ }
+
+}
+
+=item default_payment_gateway DEPRECATED -- use agent->payment_gateway
=cut
@@ -4022,6 +5748,8 @@ sub default_payment_gateway {
die "Real-time processing not enabled\n"
unless $conf->exists('business-onlinepayment');
+ #warn "default_payment_gateway deprecated -- use agent->payment_gateway\n";
+
#load up config
my $bop_config = 'business-onlinepayment';
$bop_config .= '-ach'
@@ -4055,7 +5783,7 @@ sub remove_cvv {
'';
}
-=item realtime_refund_bop METHOD [ OPTION => VALUE ... ]
+=item _new_realtime_refund_bop METHOD [ OPTION => VALUE ... ]
Refunds a realtime credit card, ACH (electronic check) or phone bill transaction
via a Business::OnlinePayment realtime gateway. See
@@ -4093,16 +5821,23 @@ gateway is attempted.
#some false laziness w/realtime_bop, not enough to make it worth merging
#but some useful small subs should be pulled out
-sub realtime_refund_bop {
- my( $self, $method, %options ) = @_;
+sub _new_realtime_refund_bop {
+ my $self = shift;
+
+ my %options = ();
+ if (ref($_[0]) ne 'HASH') {
+ %options = %{$_[0]};
+ } else {
+ my $method = shift;
+ %options = @_;
+ $options{method} = $method;
+ }
+
if ( $DEBUG ) {
- warn "$me realtime_refund_bop: $method refund\n";
+ warn "$me realtime_refund_bop (new): $options{method} refund\n";
warn " $_ => $options{$_}\n" foreach keys %options;
}
- eval "use Business::OnlinePayment";
- die $@ if $@;
-
###
# look up the original payment and optionally a gateway for that payment
###
@@ -4110,7 +5845,7 @@ sub realtime_refund_bop {
my $cust_pay = '';
my $amount = $options{'amount'};
- my( $processor, $login, $password, @bop_options ) ;
+ my( $processor, $login, $password, @bop_options, $namespace ) ;
my( $auth, $order_number ) = ( '', '', '' );
if ( $options{'paynum'} ) {
@@ -4136,13 +5871,22 @@ sub realtime_refund_bop {
$processor = $payment_gateway->gateway_module;
$login = $payment_gateway->gateway_username;
$password = $payment_gateway->gateway_password;
+ $namespace = $payment_gateway->gateway_namespace;
@bop_options = $payment_gateway->options;
} else { #try the default gateway
- my( $conf_processor, $unused_action );
- ( $conf_processor, $login, $password, $unused_action, @bop_options ) =
- $self->default_payment_gateway($method);
+ my $conf_processor;
+ my $payment_gateway =
+ $self->agent->payment_gateway('method' => $options{method});
+
+ ( $conf_processor, $login, $password, $namespace ) =
+ map { my $method = "gateway_$_"; $payment_gateway->$method }
+ qw( module username password namespace );
+
+ @bop_options = $payment_gateway->gatewaynum
+ ? $payment_gateway->options
+ : @{ $payment_gateway->get('options') };
return "processor of payment $options{'paynum'} $processor does not".
" match default processor $conf_processor"
@@ -4153,46 +5897,27 @@ sub realtime_refund_bop {
} else { # didn't specify a paynum, so look for agent gateway overrides
# like a normal transaction
-
- my $cardtype;
- if ( $method eq 'CC' ) {
- $cardtype = cardtype($self->payinfo);
- } elsif ( $method eq 'ECHECK' ) {
- $cardtype = 'ACH';
- } else {
- $cardtype = $method;
- }
- my $override =
- qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => $cardtype,
- taxclass => '', } )
- || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => '',
- taxclass => '', } );
-
- if ( $override ) { #use a payment gateway override
- my $payment_gateway = $override->payment_gateway;
-
- $processor = $payment_gateway->gateway_module;
- $login = $payment_gateway->gateway_username;
- $password = $payment_gateway->gateway_password;
- #$action = $payment_gateway->gateway_action;
- @bop_options = $payment_gateway->options;
+ my $payment_gateway =
+ $self->agent->payment_gateway( 'method' => $options{method},
+ #'payinfo' => $payinfo,
+ );
+ my( $processor, $login, $password, $namespace ) =
+ map { my $method = "gateway_$_"; $payment_gateway->$method }
+ qw( module username password namespace );
- } else { #use the standard settings from the config
-
- my $unused_action;
- ( $processor, $login, $password, $unused_action, @bop_options ) =
- $self->default_payment_gateway($method);
-
- }
+ my @bop_options = $payment_gateway->gatewaynum
+ ? $payment_gateway->options
+ : @{ $payment_gateway->get('options') };
}
return "neither amount nor paynum specified" unless $amount;
+ eval "use $namespace";
+ die $@ if $@;
+
my %content = (
- 'type' => $method,
+ 'type' => $options{method},
'login' => $login,
'password' => $password,
'order_number' => $order_number,
@@ -4242,7 +5967,7 @@ sub realtime_refund_bop {
$address .= ", ". $self->address2 if $self->address2;
my($payname, $payfirst, $paylast);
- if ( $self->payname && $method ne 'ECHECK' ) {
+ if ( $self->payname && $options{method} ne 'ECHECK' ) {
$payname = $self->payname;
$payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/
or return "Illegal payname $payname";
@@ -4271,7 +5996,7 @@ sub realtime_refund_bop {
if length($payip);
my $payinfo = '';
- if ( $method eq 'CC' ) {
+ if ( $options{method} eq 'CC' ) {
if ( $cust_pay ) {
$content{card_number} = $payinfo = $cust_pay->payinfo;
@@ -4285,7 +6010,7 @@ sub realtime_refund_bop {
$content{expiration} = "$2/$1";
}
- } elsif ( $method eq 'ECHECK' ) {
+ } elsif ( $options{method} eq 'ECHECK' ) {
if ( $cust_pay ) {
$payinfo = $cust_pay->payinfo;
@@ -4298,7 +6023,7 @@ sub realtime_refund_bop {
$content{account_name} = $payname;
$content{customer_org} = $self->company ? 'B' : 'I';
$content{customer_ssn} = $self->ss;
- } elsif ( $method eq 'LEC' ) {
+ } elsif ( $options{method} eq 'LEC' ) {
$content{phone} = $payinfo = $self->payinfo;
}
@@ -4326,12 +6051,6 @@ sub realtime_refund_bop {
return "$processor error: ". $refund->error_message
unless $refund->is_success();
- my %method2payby = (
- 'CC' => 'CARD',
- 'ECHECK' => 'CHEK',
- 'LEC' => 'LECB',
- );
-
my $paybatch = "$processor:". $refund->authorization;
$paybatch .= ':'. $refund->order_number
if $refund->can('order_number') && $refund->order_number;
@@ -4349,7 +6068,7 @@ sub realtime_refund_bop {
'paynum' => $options{'paynum'},
'refund' => $amount,
'_date' => '',
- 'payby' => $method2payby{$method},
+ 'payby' => $bop_method2payby{$options{method}},
'payinfo' => $payinfo,
'paybatch' => $paybatch,
'reason' => $options{'reason'} || 'card or ACH refund',
@@ -4503,19 +6222,23 @@ sub batch_card {
'';
}
-=item apply_payments_and_credits
+=item apply_payments_and_credits [ OPTION => VALUE ... ]
Applies unapplied payments and credits.
In most cases, this new method should be used in place of sequential
apply_payments and apply_credits methods.
+A hash of optional arguments may be passed. Currently "manual" is supported.
+If true, a payment receipt is sent instead of a statement when
+'payment_receipt_email' configuration option is set.
+
If there is an error, returns the error, otherwise returns false.
=cut
sub apply_payments_and_credits {
- my $self = shift;
+ my( $self, %options ) = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -4531,7 +6254,7 @@ sub apply_payments_and_credits {
$self->select_for_update; #mutex
foreach my $cust_bill ( $self->open_cust_bill ) {
- my $error = $cust_bill->apply_payments_and_credits;
+ my $error = $cust_bill->apply_payments_and_credits(%options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "Error applying: $error";
@@ -4584,32 +6307,52 @@ sub apply_credits {
@invoices = sort { $b->_date <=> $a->_date } @invoices
if defined($opt{'order'}) && $opt{'order'} eq 'newest';
+ if ( $conf->exists('pkg-balances') ) {
+ # limit @credits to those w/ a pkgnum grepped from $self
+ my %pkgnums = ();
+ foreach my $i (@invoices) {
+ foreach my $li ( $i->cust_bill_pkg ) {
+ $pkgnums{$li->pkgnum} = 1;
+ }
+ }
+ @credits = grep { ! $_->pkgnum || $pkgnums{$_->pkgnum} } @credits;
+ }
+
my $credit;
+
foreach my $cust_bill ( @invoices ) {
- my $amount;
if ( !defined($credit) || $credit->credited == 0) {
$credit = pop @credits or last;
}
- if ($cust_bill->owed >= $credit->credited) {
- $amount=$credit->credited;
- }else{
- $amount=$cust_bill->owed;
+ my $owed;
+ if ( $conf->exists('pkg-balances') && $credit->pkgnum ) {
+ $owed = $cust_bill->owed_pkgnum($credit->pkgnum);
+ } else {
+ $owed = $cust_bill->owed;
}
+ unless ( $owed > 0 ) {
+ push @credits, $credit;
+ next;
+ }
+
+ my $amount = min( $credit->credited, $owed );
my $cust_credit_bill = new FS::cust_credit_bill ( {
'crednum' => $credit->crednum,
'invnum' => $cust_bill->invnum,
'amount' => $amount,
} );
+ $cust_credit_bill->pkgnum( $credit->pkgnum )
+ if $conf->exists('pkg-balances') && $credit->pkgnum;
my $error = $cust_credit_bill->insert;
if ( $error ) {
$dbh->rollback or die $dbh->errstr if $oldAutoCommit;
die $error;
}
- redo if ($cust_bill->owed > 0);
+ redo if ($cust_bill->owed > 0) && ! $conf->exists('pkg-balances');
}
@@ -4620,19 +6363,24 @@ sub apply_credits {
return $total_unapplied_credits;
}
-=item apply_payments
+=item apply_payments [ OPTION => VALUE ... ]
Applies (see L<FS::cust_bill_pay>) unapplied payments (see L<FS::cust_pay>)
to outstanding invoice balances in chronological order.
#and returns the value of any remaining unapplied payments.
+A hash of optional arguments may be passed. Currently "manual" is supported.
+If true, a payment receipt is sent instead of a statement when
+'payment_receipt_email' configuration option is set.
+
+
Dies if there is an error.
=cut
sub apply_payments {
- my $self = shift;
+ my( $self, %options ) = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -4657,33 +6405,52 @@ sub apply_payments {
grep { $_->owed > 0 }
$self->cust_bill;
+ if ( $conf->exists('pkg-balances') ) {
+ # limit @payments to those w/ a pkgnum grepped from $self
+ my %pkgnums = ();
+ foreach my $i (@invoices) {
+ foreach my $li ( $i->cust_bill_pkg ) {
+ $pkgnums{$li->pkgnum} = 1;
+ }
+ }
+ @payments = grep { ! $_->pkgnum || $pkgnums{$_->pkgnum} } @payments;
+ }
+
my $payment;
foreach my $cust_bill ( @invoices ) {
- my $amount;
if ( !defined($payment) || $payment->unapplied == 0 ) {
$payment = pop @payments or last;
}
- if ( $cust_bill->owed >= $payment->unapplied ) {
- $amount = $payment->unapplied;
+ my $owed;
+ if ( $conf->exists('pkg-balances') && $payment->pkgnum ) {
+ $owed = $cust_bill->owed_pkgnum($payment->pkgnum);
} else {
- $amount = $cust_bill->owed;
+ $owed = $cust_bill->owed;
+ }
+ unless ( $owed > 0 ) {
+ push @payments, $payment;
+ next;
}
+ my $amount = min( $payment->unapplied, $owed );
+
my $cust_bill_pay = new FS::cust_bill_pay ( {
'paynum' => $payment->paynum,
'invnum' => $cust_bill->invnum,
'amount' => $amount,
} );
- my $error = $cust_bill_pay->insert;
+ $cust_bill_pay->pkgnum( $payment->pkgnum )
+ if $conf->exists('pkg-balances') && $payment->pkgnum;
+ my $error = $cust_bill_pay->insert(%options);
if ( $error ) {
$dbh->rollback or die $dbh->errstr if $oldAutoCommit;
die $error;
}
- redo if ( $cust_bill->owed > 0);
+ redo if ( $cust_bill->owed > 0) && ! $conf->exists('pkg-balances');
}
@@ -4717,6 +6484,22 @@ see L<Time::Local> and L<Date::Parse> for conversion functions.
sub total_owed_date {
my $self = shift;
my $time = shift;
+
+# my $custnum = $self->custnum;
+#
+# my $owed_sql = FS::cust_bill->owed_sql;
+#
+# my $sql = "
+# SELECT SUM($owed_sql) FROM cust_bill
+# WHERE custnum = $custnum
+# AND _date <= $time
+# ";
+#
+# my $sth = dbh->prepare($sql) or die dbh->errstr;
+# $sth->execute() or die $sth->errstr;
+#
+# return sprintf( '%.2f', $sth->fetchrow_arrayref->[0] );
+
my $total_bill = 0;
foreach my $cust_bill (
grep { $_->_date <= $time }
@@ -4725,6 +6508,42 @@ sub total_owed_date {
$total_bill += $cust_bill->owed;
}
sprintf( "%.2f", $total_bill );
+
+}
+
+=item total_owed_pkgnum PKGNUM
+
+Returns the total owed on all invoices for this customer's specific package
+when using experimental package balances (see L<FS::cust_bill/owed_pkgnum>).
+
+=cut
+
+sub total_owed_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ $self->total_owed_date_pkgnum(2145859200, $pkgnum); #12/31/2037
+}
+
+=item total_owed_date_pkgnum TIME PKGNUM
+
+Returns the total owed for this customer's specific package when using
+experimental package balances on all invoices with date earlier than
+TIME. TIME is specified as a UNIX timestamp; see L<perlfunc/"time">). Also
+see L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=cut
+
+sub total_owed_date_pkgnum {
+ my( $self, $time, $pkgnum ) = @_;
+
+ my $total_bill = 0;
+ foreach my $cust_bill (
+ grep { $_->_date <= $time }
+ qsearch('cust_bill', { 'custnum' => $self->custnum, } )
+ ) {
+ $total_bill += $cust_bill->owed_pkgnum($pkgnum);
+ }
+ sprintf( "%.2f", $total_bill );
+
}
=item total_paid
@@ -4763,6 +6582,21 @@ sub total_unapplied_credits {
sprintf( "%.2f", $total_credit );
}
+=item total_unapplied_credits_pkgnum PKGNUM
+
+Returns the total outstanding credit (see L<FS::cust_credit>) for this
+customer. See L<FS::cust_credit/credited>.
+
+=cut
+
+sub total_unapplied_credits_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ my $total_credit = 0;
+ $total_credit += $_->credited foreach $self->cust_credit_pkgnum($pkgnum);
+ sprintf( "%.2f", $total_credit );
+}
+
+
=item total_unapplied_payments
Returns the total unapplied payments (see L<FS::cust_pay>) for this customer.
@@ -4777,6 +6611,22 @@ sub total_unapplied_payments {
sprintf( "%.2f", $total_unapplied );
}
+=item total_unapplied_payments_pkgnum PKGNUM
+
+Returns the total unapplied payments (see L<FS::cust_pay>) for this customer's
+specific package when using experimental package balances. See
+L<FS::cust_pay/unapplied>.
+
+=cut
+
+sub total_unapplied_payments_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ my $total_unapplied = 0;
+ $total_unapplied += $_->unapplied foreach $self->cust_pay_pkgnum($pkgnum);
+ sprintf( "%.2f", $total_unapplied );
+}
+
+
=item total_unapplied_refunds
Returns the total unrefunded refunds (see L<FS::cust_refund>) for this
@@ -4829,6 +6679,26 @@ sub balance_date {
);
}
+=item balance_pkgnum PKGNUM
+
+Returns the balance for this customer's specific package when using
+experimental package balances (total_owed plus total_unrefunded, minus
+total_unapplied_credits minus total_unapplied_payments)
+
+=cut
+
+sub balance_pkgnum {
+ my( $self, $pkgnum ) = @_;
+
+ sprintf( "%.2f",
+ $self->total_owed_pkgnum($pkgnum)
+# n/a - refunds aren't part of pkg-balances since they don't apply to invoices
+# + $self->total_unapplied_refunds_pkgnum($pkgnum)
+ - $self->total_unapplied_credits_pkgnum($pkgnum)
+ - $self->total_unapplied_payments_pkgnum($pkgnum)
+ );
+}
+
=item in_transit_payments
Returns the total of requests for payments for this customer pending in
@@ -4852,6 +6722,86 @@ sub in_transit_payments {
sprintf( "%.2f", $in_transit_payments );
}
+=item payment_info
+
+Returns a hash of useful information for making a payment.
+
+=over 4
+
+=item balance
+
+Current balance.
+
+=item payby
+
+'CARD' (credit card - automatic), 'DCRD' (credit card - on-demand),
+'CHEK' (electronic check - automatic), 'DCHK' (electronic check - on-demand),
+'LECB' (Phone bill billing), 'BILL' (billing), or 'COMP' (free).
+
+=back
+
+For credit card transactions:
+
+=over 4
+
+=item card_type 1
+
+=item payname
+
+Exact name on card
+
+=back
+
+For electronic check transactions:
+
+=over 4
+
+=item stateid_state
+
+=back
+
+=cut
+
+sub payment_info {
+ my $self = shift;
+
+ my %return = ();
+
+ $return{balance} = $self->balance;
+
+ $return{payname} = $self->payname
+ || ( $self->first. ' '. $self->get('last') );
+
+ $return{$_} = $self->get($_) for qw(address1 address2 city state zip);
+
+ $return{payby} = $self->payby;
+ $return{stateid_state} = $self->stateid_state;
+
+ if ( $self->payby =~ /^(CARD|DCRD)$/ ) {
+ $return{card_type} = cardtype($self->payinfo);
+ $return{payinfo} = $self->paymask;
+
+ @return{'month', 'year'} = $self->paydate_monthyear;
+
+ }
+
+ if ( $self->payby =~ /^(CHEK|DCHK)$/ ) {
+ my ($payinfo1, $payinfo2) = split '@', $self->paymask;
+ $return{payinfo1} = $payinfo1;
+ $return{payinfo2} = $payinfo2;
+ $return{paytype} = $self->paytype;
+ $return{paystate} = $self->paystate;
+
+ }
+
+ #doubleclick protection
+ my $_date = time;
+ $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32;
+
+ %return;
+
+}
+
=item paydate_monthyear
Returns a two-element list consisting of the month and year of this customer's
@@ -4870,6 +6820,28 @@ sub paydate_monthyear {
}
}
+=item tax_exemption TAXNAME
+
+=cut
+
+sub tax_exemption {
+ my( $self, $taxname ) = @_;
+
+ qsearchs( 'cust_main_exemption', { 'custnum' => $self->custnum,
+ 'taxname' => $taxname,
+ },
+ );
+}
+
+=item cust_main_exemption
+
+=cut
+
+sub cust_main_exemption {
+ my $self = shift;
+ qsearch( 'cust_main_exemption', { 'custnum' => $self->custnum } );
+}
+
=item invoicing_list [ ARRAYREF ]
If an arguement is given, sets these email addresses as invoice recipients
@@ -5042,6 +7014,24 @@ sub invoicing_list_emailonly_scalar {
join(', ', $self->invoicing_list_emailonly);
}
+=item referral_custnum_cust_main
+
+Returns the customer who referred this customer (or the empty string, if
+this customer was not referred).
+
+Note the difference with referral_cust_main method: This method,
+referral_custnum_cust_main returns the single customer (if any) who referred
+this customer, while referral_cust_main returns an array of customers referred
+BY this customer.
+
+=cut
+
+sub referral_custnum_cust_main {
+ my $self = shift;
+ return '' unless $self->referral_custnum;
+ qsearchs('cust_main', { 'custnum' => $self->referral_custnum } );
+}
+
=item referral_cust_main [ DEPTH [ EXCLUDE_HASHREF ] ]
Returns an array of customers referred by this customer (referral_custnum set
@@ -5049,6 +7039,11 @@ to this custnum). If DEPTH is given, recurses up to the given depth, returning
customers referred by customers referred by this customer and so on, inclusive.
The default behavior is DEPTH 1 (no recursion).
+Note the difference with referral_custnum_cust_main method: This method,
+referral_cust_main, returns an array of customers referred BY this customer,
+while referral_custnum_cust_main returns the single customer (if any) who
+referred this customer.
+
=cut
sub referral_cust_main {
@@ -5155,33 +7150,75 @@ sub credit {
}
-=item charge AMOUNT [ PKG [ COMMENT [ TAXCLASS ] ] ]
+=item charge HASHREF || AMOUNT [ PKG [ COMMENT [ TAXCLASS ] ] ]
Creates a one-time charge for this customer. If there is an error, returns
the error, otherwise returns false.
+New-style, with a hashref of options:
+
+ my $error = $cust_main->charge(
+ {
+ 'amount' => 54.32,
+ 'quantity' => 1,
+ 'start_date' => str2time('7/4/2009'),
+ 'pkg' => 'Description',
+ 'comment' => 'Comment',
+ 'additional' => [], #extra invoice detail
+ 'classnum' => 1, #pkg_class
+
+ 'setuptax' => '', # or 'Y' for tax exempt
+
+ #internal taxation
+ 'taxclass' => 'Tax class',
+
+ #vendor taxation
+ 'taxproduct' => 2, #part_pkg_taxproduct
+ 'override' => {}, #XXX describe
+
+ #will be filled in with the new object
+ 'cust_pkg_ref' => \$cust_pkg,
+
+ #generate an invoice immediately
+ 'bill_now' => 0,
+ 'invoice_terms' => '', #with these terms
+ }
+ );
+
+Old-style:
+
+ my $error = $cust_main->charge( 54.32, 'Description', 'Comment', 'Tax class' );
+
=cut
sub charge {
my $self = shift;
- my ( $amount, $quantity, $pkg, $comment, $classnum, $additional );
+ my ( $amount, $quantity, $start_date, $classnum );
+ my ( $pkg, $comment, $additional );
my ( $setuptax, $taxclass ); #internal taxes
my ( $taxproduct, $override ); #vendor (CCH) taxes
+ my $cust_pkg_ref = '';
+ my ( $bill_now, $invoice_terms ) = ( 0, '' );
if ( ref( $_[0] ) ) {
$amount = $_[0]->{amount};
$quantity = exists($_[0]->{quantity}) ? $_[0]->{quantity} : 1;
+ $start_date = exists($_[0]->{start_date}) ? $_[0]->{start_date} : '';
$pkg = exists($_[0]->{pkg}) ? $_[0]->{pkg} : 'One-time charge';
$comment = exists($_[0]->{comment}) ? $_[0]->{comment}
: '$'. sprintf("%.2f",$amount);
$setuptax = exists($_[0]->{setuptax}) ? $_[0]->{setuptax} : '';
$taxclass = exists($_[0]->{taxclass}) ? $_[0]->{taxclass} : '';
$classnum = exists($_[0]->{classnum}) ? $_[0]->{classnum} : '';
- $additional = $_[0]->{additional};
+ $additional = $_[0]->{additional} || [];
$taxproduct = $_[0]->{taxproductnum};
$override = { '' => $_[0]->{tax_override} };
- }else{
+ $cust_pkg_ref = exists($_[0]->{cust_pkg_ref}) ? $_[0]->{cust_pkg_ref} : '';
+ $bill_now = exists($_[0]->{bill_now}) ? $_[0]->{bill_now} : '';
+ $invoice_terms = exists($_[0]->{invoice_terms}) ? $_[0]->{invoice_terms} : '';
+ } else {
$amount = shift;
$quantity = 1;
+ $start_date = '';
$pkg = @_ ? shift : 'One-time charge';
$comment = @_ ? shift : '$'. sprintf("%.2f",$amount);
$setuptax = '';
@@ -5239,19 +7276,32 @@ sub charge {
}
my $cust_pkg = new FS::cust_pkg ( {
- 'custnum' => $self->custnum,
- 'pkgpart' => $pkgpart,
- 'quantity' => $quantity,
+ 'custnum' => $self->custnum,
+ 'pkgpart' => $pkgpart,
+ 'quantity' => $quantity,
+ 'start_date' => $start_date,
} );
$error = $cust_pkg->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
+ } elsif ( $cust_pkg_ref ) {
+ ${$cust_pkg_ref} = $cust_pkg;
+ }
+
+ if ( $bill_now ) {
+ my $error = $self->bill( 'invoice_terms' => $invoice_terms,
+ 'pkg_list' => [ $cust_pkg ],
+ );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
+ return '';
}
@@ -5290,6 +7340,7 @@ Returns all the invoices (see L<FS::cust_bill>) for this customer.
sub cust_bill {
my $self = shift;
+ map { $_ } #return $self->num_cust_bill unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch('cust_bill', { 'custnum' => $self->custnum, } )
}
@@ -5303,7 +7354,27 @@ customer.
sub open_cust_bill {
my $self = shift;
- grep { $_->owed > 0 } $self->cust_bill;
+
+ qsearch({
+ 'table' => 'cust_bill',
+ 'hashref' => { 'custnum' => $self->custnum, },
+ 'extra_sql' => ' AND '. FS::cust_bill->owed_sql. ' > 0',
+ 'order_by' => 'ORDER BY _date ASC',
+ });
+
+}
+
+=item cust_statements
+
+Returns all the statements (see L<FS::cust_statement>) for this customer.
+
+=cut
+
+sub cust_statement {
+ my $self = shift;
+ map { $_ } #return $self->num_cust_statement unless wantarray;
+ sort { $a->_date <=> $b->_date }
+ qsearch('cust_statement', { 'custnum' => $self->custnum, } )
}
=item cust_credit
@@ -5314,10 +7385,28 @@ Returns all the credits (see L<FS::cust_credit>) for this customer.
sub cust_credit {
my $self = shift;
+ map { $_ } #return $self->num_cust_credit unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_credit', { 'custnum' => $self->custnum } )
}
+=item cust_credit_pkgnum
+
+Returns all the credits (see L<FS::cust_credit>) for this customer's specific
+package when using experimental package balances.
+
+=cut
+
+sub cust_credit_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ map { $_ } #return $self->num_cust_credit_pkgnum($pkgnum) unless wantarray;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_credit', { 'custnum' => $self->custnum,
+ 'pkgnum' => $pkgnum,
+ }
+ );
+}
+
=item cust_pay
Returns all the payments (see L<FS::cust_pay>) for this customer.
@@ -5326,10 +7415,43 @@ Returns all the payments (see L<FS::cust_pay>) for this customer.
sub cust_pay {
my $self = shift;
+ return $self->num_cust_pay unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_pay', { 'custnum' => $self->custnum } )
}
+=item num_cust_pay
+
+Returns the number of payments (see L<FS::cust_pay>) for this customer. Also
+called automatically when the cust_pay method is used in a scalar context.
+
+=cut
+
+sub num_cust_pay {
+ my $self = shift;
+ my $sql = "SELECT COUNT(*) FROM cust_pay WHERE custnum = ?";
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute($self->custnum) or die $sth->errstr;
+ $sth->fetchrow_arrayref->[0];
+}
+
+=item cust_pay_pkgnum
+
+Returns all the payments (see L<FS::cust_pay>) for this customer's specific
+package when using experimental package balances.
+
+=cut
+
+sub cust_pay_pkgnum {
+ my( $self, $pkgnum ) = @_;
+ map { $_ } #return $self->num_cust_pay_pkgnum($pkgnum) unless wantarray;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_pay', { 'custnum' => $self->custnum,
+ 'pkgnum' => $pkgnum,
+ }
+ );
+}
+
=item cust_pay_void
Returns all voided payments (see L<FS::cust_pay_void>) for this customer.
@@ -5338,6 +7460,7 @@ Returns all voided payments (see L<FS::cust_pay_void>) for this customer.
sub cust_pay_void {
my $self = shift;
+ map { $_ } #return $self->num_cust_pay_void unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_pay_void', { 'custnum' => $self->custnum } )
}
@@ -5350,7 +7473,8 @@ Returns all batched payments (see L<FS::cust_pay_void>) for this customer.
sub cust_pay_batch {
my $self = shift;
- sort { $a->_date <=> $b->_date }
+ map { $_ } #return $self->num_cust_pay_batch unless wantarray;
+ sort { $a->paybatchnum <=> $b->paybatchnum }
qsearch( 'cust_pay_batch', { 'custnum' => $self->custnum } )
}
@@ -5397,6 +7521,7 @@ Returns all the refunds (see L<FS::cust_refund>) for this customer.
sub cust_refund {
my $self = shift;
+ map { $_ } #return $self->num_cust_refund unless wantarray;
sort { $a->_date <=> $b->_date }
qsearch( 'cust_refund', { 'custnum' => $self->custnum } )
}
@@ -5695,6 +7820,19 @@ sub support_services {
}
+# Return a list of latitude/longitude for one of the services (if any)
+sub service_coordinates {
+ my $self = shift;
+
+ my @svc_X =
+ grep { $_->latitude && $_->longitude }
+ map { $_->svc_x }
+ map { $_->cust_svc }
+ $self->ncancelled_pkgs;
+
+ scalar(@svc_X) ? ( $svc_X[0]->latitude, $svc_X[0]->longitude ) : ()
+}
+
=back
=head1 CLASS METHODS
@@ -5896,6 +8034,32 @@ sub balance_date_sql {
}
+=item unapplied_payments_date_sql START_TIME [ END_TIME ]
+
+Returns an SQL fragment to retreive the total unapplied payments for this
+customer, only considering invoices with date earlier than START_TIME, and
+optionally not later than END_TIME.
+
+Times are specified as SQL fragments or numeric
+UNIX timestamps; see L<perlfunc/"time">). Also see L<Time::Local> and
+L<Date::Parse> for conversion functions. The empty string can be passed
+to disable that time constraint completely.
+
+Available options are:
+
+=cut
+
+sub unapplied_payments_date_sql {
+ my( $class, $start, $end, ) = @_;
+
+ my $unapp_pay = FS::cust_pay->unapplied_sql;
+
+ my $pay_where = $class->_money_table_where( 'cust_pay', $start, $end,
+ 'unapplied_date'=>1 );
+
+ " ( SELECT COALESCE(SUM($unapp_pay), 0) FROM cust_pay $pay_where ) ";
+}
+
=item _money_table_where TABLE START_TIME [ END_TIME [ OPTION => VALUE ... ] ]
Helper method for balance_date_sql; name (and usage) subject to change
@@ -6003,6 +8167,13 @@ sub search_sql {
unless $params->{'cancelled_pkgs'};
##
+ # parse without census tract checkbox
+ ##
+
+ push @where, "(censustract = '' or censustract is null)"
+ if $params->{'no_censustract'};
+
+ ##
# dates
##
@@ -6166,6 +8337,9 @@ sub email_search_sql {
my $job = delete $params->{'job'};
+ $params->{'payby'} = [ split(/\0/, $params->{'payby'}) ]
+ unless ref($params->{'payby'});
+
my $sql_query = $class->search_sql($params);
my $count_query = delete($sql_query->{'count_query'});
@@ -6227,6 +8401,9 @@ sub process_email_search_sql {
$param->{'job'} = $job;
+ $param->{'payby'} = [ split(/\0/, $param->{'payby'}) ]
+ unless ref($param->{'payby'});
+
my $error = FS::cust_main->email_search_sql( $param );
die $error if $error;
@@ -6540,12 +8717,12 @@ sub smart_search {
}
- #eliminate duplicates
- my %saw = ();
- @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
-
}
+ #eliminate duplicates
+ my %saw = ();
+ @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
+
@cust_main;
}
@@ -7113,6 +9290,15 @@ sub queued_bill {
);
}
+sub _upgrade_data { #class method
+ my ($class, %opts) = @_;
+
+ my $sql = 'UPDATE h_cust_main SET paycvv = NULL WHERE paycvv IS NOT NULL';
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm
index ced0a1f..86751b1 100644
--- a/FS/FS/cust_main_Mixin.pm
+++ b/FS/FS/cust_main_Mixin.pm
@@ -26,7 +26,12 @@ for example, from a JOINed search. See httemplate/search/ for examples.
=over 4
-=item name
+=cut
+
+sub cust_unlinked_msg { '(unlinked)'; }
+sub cust_linked { $_[0]->custnum; }
+
+=item display_custnum
Given an object that contains fields from cust_main (say, from a JOINed
search; see httemplate/search/ for examples), returns the equivalent of the
@@ -35,8 +40,21 @@ a customer.
=cut
-sub cust_unlinked_msg { '(unlinked)'; }
-sub cust_linked { $_[0]->custnum; }
+sub display_custnum {
+ my $self = shift;
+ $self->cust_linked
+ ? FS::cust_main::display_custnum($self)
+ : $self->cust_unlinked_msg;
+}
+
+=item name
+
+Given an object that contains fields from cust_main (say, from a JOINed
+search; see httemplate/search/ for examples), returns the equivalent of the
+FS::cust_main I<name> method, or "(unlinked)" if this object is not linked to
+a customer.
+
+=cut
sub name {
my $self = shift;
diff --git a/FS/FS/cust_main_exemption.pm b/FS/FS/cust_main_exemption.pm
new file mode 100644
index 0000000..06d22b7
--- /dev/null
+++ b/FS/FS/cust_main_exemption.pm
@@ -0,0 +1,128 @@
+package FS::cust_main_exemption;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+use FS::cust_main;
+
+=head1 NAME
+
+FS::cust_main_exemption - Object methods for cust_main_exemption records
+
+=head1 SYNOPSIS
+
+ use FS::cust_main_exemption;
+
+ $record = new FS::cust_main_exemption \%hash;
+ $record = new FS::cust_main_exemption { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_main_exemption object represents a customer tax exemption from a
+specific tax name (prefix). FS::cust_main_exemption inherits from
+FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item exemptionnum
+
+Primary key
+
+=item custnum
+
+Customer (see L<FS::cust_main>)
+
+=item taxname
+
+taxname
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cust_main_exemption'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('exemptionnum')
+ || $self->ut_foreign_key('custnum', 'cust_main', 'custnum')
+ || $self->ut_text('taxname')
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_main>, L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index 583a724..69bcd87 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -17,6 +17,7 @@ use FS::cust_bill;
use FS::cust_bill_pay;
use FS::cust_pay_refund;
use FS::cust_main;
+use FS::cust_pkg;
use FS::cust_pay_void;
@ISA = qw( FS::payinfo_transaction_Mixin FS::cust_main_Mixin FS::Record );
@@ -62,28 +63,54 @@ currently supported:
=over 4
-=item paynum - primary key (assigned automatically for new payments)
+=item paynum
-=item custnum - customer (see L<FS::cust_main>)
+primary key (assigned automatically for new payments)
-=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+=item custnum
+
+customer (see L<FS::cust_main>)
+
+=item _date
+
+specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
-=item paid - Amount of this payment
+=item paid
+
+Amount of this payment
+
+=item otaker
+
+order taker (assigned automatically, see L<FS::UID>)
+
+=item payby
+
+Payment Type (See L<FS::payinfo_Mixin> for valid payby values)
+
+=item payinfo
+
+Payment Information (See L<FS::payinfo_Mixin> for data format)
-=item otaker - order taker (assigned automatically, see L<FS::UID>)
+=item paymask
-=item payby - Payment Type (See L<FS::payinfo_Mixin> for valid payby values)
+Masked payinfo (See L<FS::payinfo_Mixin> for how this works)
-=item payinfo - Payment Information (See L<FS::payinfo_Mixin> for data format)
+=item paybatch
-=item paymask - Masked payinfo (See L<FS::payinfo_Mixin> for how this works)
+text field for tracking card processing or other batch grouping
-=item paybatch - text field for tracking card processing or other batch grouping
+=item payunique
-=item payunique - Optional unique identifer to prevent duplicate transactions.
+Optional unique identifer to prevent duplicate transactions.
-=item closed - books closed flag, empty or `Y'
+=item closed
+
+books closed flag, empty or `Y'
+
+=item pkgnum
+
+Desired pkgnum when using experimental package balances.
=back
@@ -105,21 +132,22 @@ sub cust_unlinked_msg {
' (cust_pay.paynum '. $self->paynum. ')';
}
-=item insert
+=item insert [ OPTION => VALUE ... ]
Adds this payment to the database.
For backwards-compatibility and convenience, if the additional field invnum
is defined, an FS::cust_bill_pay record for the full amount of the payment
-will be created. In this case, custnum is optional. An hash of optional
-arguments may be passed. Currently "manual" is supported. If true, a
-payment receipt is sent instead of a statement when 'payment_receipt_email'
-configuration option is set.
+will be created. In this case, custnum is optional.
+
+A hash of optional arguments may be passed. Currently "manual" is supported.
+If true, a payment receipt is sent instead of a statement when
+'payment_receipt_email' configuration option is set.
=cut
sub insert {
- my ($self, %options) = @_;
+ my($self, %options) = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -142,7 +170,6 @@ sub insert {
$self->custnum($cust_bill->custnum );
}
-
my $error = $self->check;
return $error if $error;
@@ -162,7 +189,7 @@ sub insert {
'amount' => $self->paid,
'_date' => $self->_date,
};
- $error = $cust_bill_pay->insert;
+ $error = $cust_bill_pay->insert(%options);
if ( $error ) {
if ( $ignore_noapply ) {
warn "warning: error inserting $cust_bill_pay: $error ".
@@ -189,69 +216,15 @@ sub insert {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- #my $cust_main = $self->cust_main;
- if ( $conf->exists('payment_receipt_email')
- && grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list
- ) {
-
- $cust_bill ||= ($cust_main->cust_bill)[-1]; #rather inefficient though?
-
- my $error;
- if ( ( exists($options{'manual'}) && $options{'manual'} )
- || ! $conf->exists('invoice_html_statement')
- || ! $cust_bill
- ) {
-
- my $receipt_template = new Text::Template (
- TYPE => 'ARRAY',
- SOURCE => [ map "$_\n", $conf->config('payment_receipt_email') ],
- ) or do {
- warn "can't create payment receipt template: $Text::Template::ERROR";
- return '';
- };
-
- my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ }
- $cust_main->invoicing_list;
-
- my $payby = $self->payby;
- my $payinfo = $self->payinfo;
- $payby =~ s/^BILL$/Check/ if $payinfo;
- $payinfo = $self->paymask if $payby eq 'CARD' || $payby eq 'CHEK';
- $payby =~ s/^CHEK$/Electronic check/;
-
- $error = send_email(
- 'from' => $conf->config('invoice_from', $self->cust_main->agentnum),
- #invoice_from??? well as good as any
- 'to' => \@invoicing_list,
- 'subject' => 'Payment receipt',
- 'body' => [ $receipt_template->fill_in( HASH => {
- 'date' => time2str("%a %B %o, %Y", $self->_date),
- 'name' => $cust_main->name,
- 'paynum' => $self->paynum,
- 'paid' => sprintf("%.2f", $self->paid),
- 'payby' => ucfirst(lc($payby)),
- 'payinfo' => $payinfo,
- 'balance' => $cust_main->balance,
- } ) ],
- );
-
- } else {
-
- my $queue = new FS::queue {
- 'paynum' => $self->paynum,
- 'job' => 'FS::cust_bill::queueable_email',
- };
- $error = $queue->insert(
- 'invnum' => $cust_bill->invnum,
- 'template' => 'statement',
- );
-
- }
-
- if ( $error ) {
- warn "can't send payment receipt/statement: $error";
- }
-
+ #payment receipt
+ my $trigger = $conf->config('payment_receipt-trigger') || 'cust_pay';
+ if ( $trigger eq 'cust_pay' ) {
+ my $error = $self->send_receipt(
+ 'manual' => $options{'manual'},
+ 'cust_bill' => $cust_bill,
+ 'cust_main' => $cust_main,
+ );
+ warn "can't send payment receipt/statement: $error" if $error;
}
'';
@@ -340,7 +313,8 @@ sub delete {
return $error;
}
- if ( $conf->config('deletepayments') ne '' ) {
+ if ( $conf->exists('deletepayments')
+ && $conf->config('deletepayments') ne '' ) {
my $cust_main = $self->cust_main;
@@ -411,6 +385,7 @@ sub check {
|| $self->ut_textn('paybatch')
|| $self->ut_textn('payunique')
|| $self->ut_enum('closed', [ '', 'Y' ])
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
|| $self->payinfo_check()
;
return $error if $error;
@@ -437,58 +412,109 @@ sub check {
$self->SUPER::check;
}
-=item batch_insert CUST_PAY_OBJECT, ...
+=item send_receipt HASHREF | OPTION => VALUE ...
-Class method which inserts multiple payments. Takes a list of FS::cust_pay
-objects. Returns a list, each element representing the status of inserting the
-corresponding payment - empty. If there is an error inserting any payment, the
-entire transaction is rolled back, i.e. all payments are inserted or none are.
+Sends a payment receipt for this payment..
-For example:
+Available options:
- my @errors = FS::cust_pay->batch_insert(@cust_pay);
- my $num_errors = scalar(grep $_, @errors);
- if ( $num_errors == 0 ) {
- #success; all payments were inserted
- } else {
- #failure; no payments were inserted.
- }
+=over 4
+
+=item manual
+
+Flag indicating the payment is being made manually.
+
+=item cust_bill
+
+Invoice (FS::cust_bill) object. If not specified, the most recent invoice
+will be assumed.
+
+=item cust_main
+
+Customer (FS::cust_main) object (for efficiency).
+
+=back
=cut
-sub batch_insert {
- my $self = shift; #class method
+sub send_receipt {
+ my $self = shift;
+ my $opt = ref($_[0]) ? shift : { @_ };
- local $SIG{HUP} = 'IGNORE';
- local $SIG{INT} = 'IGNORE';
- local $SIG{QUIT} = 'IGNORE';
- local $SIG{TERM} = 'IGNORE';
- local $SIG{TSTP} = 'IGNORE';
- local $SIG{PIPE} = 'IGNORE';
+ my $cust_bill = $opt->{'cust_bill'};
+ my $cust_main = $opt->{'cust_main'} || $self->cust_main;
- my $oldAutoCommit = $FS::UID::AutoCommit;
- local $FS::UID::AutoCommit = 0;
- my $dbh = dbh;
+ my $conf = new FS::Conf;
- my $errors = 0;
-
- my @errors = map {
- my $error = $_->insert( 'manual' => 1 );
- if ( $error ) {
- $errors++;
+ return ''
+ unless $conf->exists('payment_receipt_email')
+ && grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;
+
+ $cust_bill ||= ($cust_main->cust_bill)[-1]; #rather inefficient though?
+
+ if ( ( exists($opt->{'manual'}) && $opt->{'manual'} )
+ || ! $conf->exists('invoice_html_statement')
+ || ! $cust_bill
+ ) {
+
+ my $receipt_template = new Text::Template (
+ TYPE => 'ARRAY',
+ SOURCE => [ map "$_\n", $conf->config('payment_receipt_email') ],
+ ) or do {
+ warn "can't create payment receipt template: $Text::Template::ERROR";
+ return '';
+ };
+
+ my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ }
+ $cust_main->invoicing_list;
+
+ my $payby = $self->payby;
+ my $payinfo = $self->payinfo;
+ $payby =~ s/^BILL$/Check/ if $payinfo;
+ if ( $payby eq 'CARD' || $payby eq 'CHEK' ) {
+ $payinfo = $self->paymask
} else {
- $_->cust_main->apply_payments;
+ $payinfo = $self->decrypt($payinfo);
}
- $error;
- } @_;
+ $payby =~ s/^CHEK$/Electronic check/;
+
+ my %fill_in = (
+ 'date' => time2str("%a %B %o, %Y", $self->_date),
+ 'name' => $cust_main->name,
+ 'paynum' => $self->paynum,
+ 'paid' => sprintf("%.2f", $self->paid),
+ 'payby' => ucfirst(lc($payby)),
+ 'payinfo' => $payinfo,
+ 'balance' => $cust_main->balance,
+ 'company_name' => $conf->config('company_name', $cust_main->agentnum),
+ );
+
+ if ( $opt->{'cust_pkg'} ) {
+ $fill_in{'pkg'} = $opt->{'cust_pkg'}->part_pkg->pkg;
+ #setup date, other things?
+ }
+
+ send_email(
+ 'from' => $conf->config('invoice_from', $cust_main->agentnum),
+ #invoice_from??? well as good as any
+ 'to' => \@invoicing_list,
+ 'subject' => 'Payment receipt',
+ 'body' => [ $receipt_template->fill_in( HASH => \%fill_in ) ],
+ );
- if ( $errors ) {
- $dbh->rollback if $oldAutoCommit;
} else {
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- }
- @errors;
+ my $queue = new FS::queue {
+ 'paynum' => $self->paynum,
+ 'job' => 'FS::cust_bill::queueable_email',
+ };
+
+ $queue->insert(
+ 'invnum' => $cust_bill->invnum,
+ 'template' => 'statement',
+ );
+
+ }
}
@@ -569,6 +595,61 @@ sub amount {
=over 4
+=item batch_insert CUST_PAY_OBJECT, ...
+
+Class method which inserts multiple payments. Takes a list of FS::cust_pay
+objects. Returns a list, each element representing the status of inserting the
+corresponding payment - empty. If there is an error inserting any payment, the
+entire transaction is rolled back, i.e. all payments are inserted or none are.
+
+For example:
+
+ my @errors = FS::cust_pay->batch_insert(@cust_pay);
+ my $num_errors = scalar(grep $_, @errors);
+ if ( $num_errors == 0 ) {
+ #success; all payments were inserted
+ } else {
+ #failure; no payments were inserted.
+ }
+
+=cut
+
+sub batch_insert {
+ my $self = shift; #class method
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $errors = 0;
+
+ my @errors = map {
+ my $error = $_->insert( 'manual' => 1 );
+ if ( $error ) {
+ $errors++;
+ } else {
+ $_->cust_main->apply_payments;
+ }
+ $error;
+ } @_;
+
+ if ( $errors ) {
+ $dbh->rollback if $oldAutoCommit;
+ } else {
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ }
+
+ @errors;
+
+}
+
=item unapplied_sql
Returns an SQL fragment to retreive the unapplied amount.
diff --git a/FS/FS/cust_pay_pending.pm b/FS/FS/cust_pay_pending.pm
index bbabd24..f48e1a8 100644
--- a/FS/FS/cust_pay_pending.pm
+++ b/FS/FS/cust_pay_pending.pm
@@ -6,6 +6,7 @@ use FS::Record qw( qsearch qsearchs dbh ); #dbh for _upgrade_data
use FS::payinfo_transaction_Mixin;
use FS::cust_main_Mixin;
use FS::cust_main;
+use FS::cust_pkg;
use FS::cust_pay;
@ISA = qw( FS::payinfo_transaction_Mixin FS::cust_main_Mixin FS::Record );
@@ -77,6 +78,10 @@ Expiration date
Unique identifer to prevent duplicate transactions.
+=item pkgnum
+
+Desired pkgnum when using experimental package balances.
+
=item status
Pending transaction status, one of the following:
@@ -191,7 +196,9 @@ sub check {
#|| $self->ut_textn('statustext')
|| $self->ut_anything('statustext')
#|| $self->ut_money('cust_balance')
+ || $self->ut_hexn('session_id')
|| $self->ut_foreign_keyn('paynum', 'cust_pay', 'paynum' )
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
|| $self->payinfo_check() #payby/payinfo/paymask/paydate
;
return $error if $error;
@@ -215,6 +222,18 @@ sub check {
$self->SUPER::check;
}
+=item cust_main
+
+Returns the associated L<FS::cust_main> record if any. Otherwise returns false.
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs('cust_main', { custnum => $self->custnum } );
+}
+
+
#these two are kind-of false laziness w/cust_main::realtime_bop
#(currently only used when resolving pending payments manually)
diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm
index de05f71..86fbbe5 100644
--- a/FS/FS/cust_pay_void.pm
+++ b/FS/FS/cust_pay_void.pm
@@ -9,6 +9,7 @@ use FS::cust_pay;
#use FS::cust_bill_pay;
#use FS::cust_pay_refund;
#use FS::cust_main;
+use FS::cust_pkg;
@ISA = qw( FS::Record FS::payinfo_Mixin );
@@ -40,24 +41,44 @@ are currently supported:
=over 4
-=item paynum - primary key (assigned automatically for new payments)
+=item paynum
-=item custnum - customer (see L<FS::cust_main>)
+primary key (assigned automatically for new payments)
-=item paid - Amount of this payment
+=item custnum
-=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+customer (see L<FS::cust_main>)
+
+=item paid
+
+Amount of this payment
+
+=item _date
+
+specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
L<Time::Local> and L<Date::Parse> for conversion functions.
-=item payby - `CARD' (credit cards), `CHEK' (electronic check/ACH),
+=item payby
+
+`CARD' (credit cards), `CHEK' (electronic check/ACH),
`LECB' (phone bill billing), `BILL' (billing), `CASH' (cash),
`WEST' (Western Union), `MCRD' (Manual credit card), or `COMP' (free)
-=item payinfo - card number, check #, or comp issuer (4-8 lowercase alphanumerics; think username), respectively
+=item payinfo
+
+card number, check #, or comp issuer (4-8 lowercase alphanumerics; think username), respectively
+
+=item paybatch
+
+text field for tracking card processing
+
+=item closed
+
+books closed flag, empty or `Y'
-=item paybatch - text field for tracking card processing
+=item pkgnum
-=item closed - books closed flag, empty or `Y'
+Desired pkgnum when using experimental package balances.
=item void_date
@@ -156,6 +177,7 @@ sub check {
|| $self->ut_number('_date')
|| $self->ut_textn('paybatch')
|| $self->ut_enum('closed', [ '', 'Y' ])
+ || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
|| $self->ut_numbern('void_date')
|| $self->ut_textn('reason')
;
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index dd6db1b..e839eb9 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -2,9 +2,11 @@ package FS::cust_pkg;
use strict;
use vars qw(@ISA $disable_agentcheck $DEBUG);
+use Carp qw(cluck);
use Scalar::Util qw( blessed );
use List::Util qw(max);
use Tie::IxHash;
+use MIME::Entity;
use FS::UID qw( getotaker dbh );
use FS::Misc qw( send_email );
use FS::Record qw( qsearch qsearchs );
@@ -120,6 +122,10 @@ Billing item definition (see L<FS::part_pkg>)
Optional link to package location (see L<FS::location>)
+=item start_date
+
+date
+
=item setup
date
@@ -228,6 +234,14 @@ If set true, supresses any referral credit to a referring customer.
cust_pkg_option records will be created
+=item ticket_subject
+
+a ticket will be added to this customer with this subject
+
+=item ticket_queue
+
+an optional queue name for ticket additions
+
=back
=cut
@@ -270,6 +284,29 @@ sub insert {
my $conf = new FS::Conf;
+ if ( $conf->config('ticket_system') && $options{ticket_subject} ) {
+ eval '
+ use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" );
+ use RT;
+ ';
+ die $@ if $@;
+
+ RT::LoadConfig();
+ RT::Init();
+ my $q = new RT::Queue($RT::SystemUser);
+ $q->Load($options{ticket_queue}) if $options{ticket_queue};
+ my $t = new RT::Ticket($RT::SystemUser);
+ my $mime = new MIME::Entity;
+ $mime->build( Type => 'text/plain', Data => $options{ticket_subject} );
+ $t->Create( $options{ticket_queue} ? (Queue => $q) : (),
+ Subject => $options{ticket_subject},
+ MIMEObj => $mime,
+ );
+ $t->AddLink( Type => 'MemberOf',
+ Target => 'freeside://freeside/cust_main/'. $self->custnum,
+ );
+ }
+
if ($conf->config('welcome_letter') && $self->cust_main->num_pkgs == 1) {
my $queue = new FS::queue {
'job' => 'FS::cust_main::queueable_print',
@@ -439,15 +476,14 @@ replace methods.
sub check {
my $self = shift;
- $self->locationnum('')
- if defined($self->locationnum) && length($self->locationnum)
- && ( $self->locationnum == 0 || $self->locationnum == -1 );
+ $self->locationnum('') if !$self->locationnum || $self->locationnum == -1;
my $error =
$self->ut_numbern('pkgnum')
|| $self->ut_foreign_key('custnum', 'cust_main', 'custnum')
|| $self->ut_numbern('pkgpart')
|| $self->ut_foreign_keyn('locationnum', 'cust_location', 'locationnum')
+ || $self->ut_numbern('start_date')
|| $self->ut_numbern('setup')
|| $self->ut_numbern('bill')
|| $self->ut_numbern('susp')
@@ -481,10 +517,10 @@ sub check {
unless ( $disable_agentcheck ) {
my $agent =
qsearchs( 'agent', { 'agentnum' => $self->cust_main->agentnum } );
- my $pkgpart_href = $agent->pkgpart_hashref;
- return "agent ". $agent->agentnum.
+ return "agent ". $agent->agentnum. ':'. $agent->agent.
" can't purchase pkgpart ". $self->pkgpart
- unless $pkgpart_href->{ $self->pkgpart };
+ unless $agent->pkgpart_hashref->{ $self->pkgpart }
+ || $agent->agentnum == $self->part_pkg->agentnum;
}
$error = $self->ut_foreign_key('pkgpart', 'part_pkg', 'pkgpart' );
@@ -524,6 +560,8 @@ Available options are:
=item date - can be set to a unix style timestamp to specify when to cancel (expire)
+=item nobill - can be set true to skip billing if it might otherwise be done.
+
=back
If there is an error, returns the error, otherwise returns false.
@@ -534,6 +572,8 @@ sub cancel {
my( $self, %options ) = @_;
my $error;
+ my $conf = new FS::Conf;
+
warn "cust_pkg::cancel called with options".
join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
if $DEBUG;
@@ -559,6 +599,20 @@ sub cancel {
my $date = $options{date} if $options{date}; # expire/cancel later
$date = '' if ($date && $date <= time); # complain instead?
+ #race condition: usage could be ongoing until unprovisioned
+ #resolved by performing a change package instead (which unprovisions) and
+ #later cancelling
+ if ( !$options{nobill} && !$date && $conf->exists('bill_usage_on_cancel') ) {
+ my $copy = $self->new({$self->hash});
+ my $error =
+ $copy->cust_main->bill( pkg_list => [ $copy ], cancel => 1 );
+ warn "Error billing during cancel, custnum ".
+ #$self->cust_main->custnum. ": $error"
+ ": $error"
+ if $error;
+ }
+
+
my $cancel_time = $options{'time'} || time;
if ( $options{'reason'} ) {
@@ -594,7 +648,6 @@ sub cancel {
# Add a credit for remaining service
my $remaining_value = $self->calc_remain(time=>$cancel_time);
if ( $remaining_value > 0 && !$options{'no_credit'} ) {
- my $conf = new FS::Conf;
my $error = $self->cust_main->credit(
$remaining_value,
'Credit for unused time on '. $self->part_pkg->pkg,
@@ -620,10 +673,8 @@ sub cancel {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
return '' if $date; #no errors
- my $conf = new FS::Conf;
my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $self->cust_main->invoicing_list;
if ( !$options{'quiet'} && $conf->exists('emailcancel') && @invoicing_list ) {
- my $conf = new FS::Conf;
my $error = send_email(
'from' => $conf->config('invoice_from', $self->cust_main->agentnum),
'to' => \@invoicing_list,
@@ -1137,6 +1188,22 @@ sub change {
return "Unable to transfer all services from package ". $self->pkgnum;
}
+ #reset usage if changing pkgpart
+ # AND usage rollover is off (otherwise adds twice, now and at package bill)
+ if ($self->pkgpart != $cust_pkg->pkgpart) {
+ my $part_pkg = $cust_pkg->part_pkg;
+ $error = $part_pkg->reset_usage($cust_pkg, $part_pkg->is_prepaid
+ ? ()
+ : ( 'null' => 1 )
+ )
+ if $part_pkg->can('reset_usage') && ! $part_pkg->option('usage_rollover');
+
+ if ($error) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error setting usage values: $error";
+ }
+ }
+
#Good to go, cancel old package.
$error = $self->cancel( quiet=>1 );
if ($error) {
@@ -1209,10 +1276,9 @@ L<FS::part_pkg>).
sub part_pkg {
my $self = shift;
- #exists( $self->{'_pkgpart'} )
- $self->{'_pkgpart'}
- ? $self->{'_pkgpart'}
- : qsearchs( 'part_pkg', { 'pkgpart' => $self->pkgpart } );
+ return $self->{'_pkgpart'} if $self->{'_pkgpart'};
+ cluck "cust_pkg->part_pkg called" if $DEBUG > 1;
+ qsearchs( 'part_pkg', { 'pkgpart' => $self->pkgpart } );
}
=item old_cust_pkg
@@ -1402,11 +1468,15 @@ services.
sub cust_svc {
my $self = shift;
+ return () unless $self->num_cust_svc(@_);
+
if ( @_ ) {
return qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum,
'svcpart' => shift, } );
}
+ cluck "cust_pkg->cust_svc called" if $DEBUG > 2;
+
#if ( $self->{'_svcnum'} ) {
# values %{ $self->{'_svcnum'}->cache };
#} else {
@@ -1427,7 +1497,8 @@ is specified, return only the matching services.
sub overlimit {
my $self = shift;
- grep { $_->overlimit } $self->cust_svc;
+ return () unless $self->num_cust_svc(@_);
+ grep { $_->overlimit } $self->cust_svc(@_);
}
=item h_cust_svc END_TIMESTAMP [ START_TIMESTAMP ]
@@ -1476,9 +1547,19 @@ specified, counts only the matching services.
sub num_cust_svc {
my $self = shift;
+
+ return $self->{'_num_cust_svc'}
+ if !scalar(@_)
+ && exists($self->{'_num_cust_svc'})
+ && $self->{'_num_cust_svc'} =~ /\d/;
+
+ cluck "cust_pkg->num_cust_svc called, _num_cust_svc:".$self->{'_num_cust_svc'}
+ if $DEBUG > 2;
+
my $sql = 'SELECT COUNT(*) FROM cust_svc WHERE pkgnum = ?';
$sql .= ' AND svcpart = ?' if @_;
- my $sth = dbh->prepare($sql) or die dbh->errstr;
+
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute($self->pkgnum, @_) or die $sth->errstr;
$sth->fetchrow_arrayref->[0];
}
@@ -1535,7 +1616,8 @@ sub part_svc {
$part_svc->{'Hash'}{'num_cust_svc'} = $num_cust_svc; #more evil
$part_svc->{'Hash'}{'num_avail'} =
max( 0, $pkg_svc->quantity - $num_cust_svc );
- $part_svc->{'Hash'}{'cust_pkg_svc'} = [ $self->cust_svc($part_svc->svcpart) ];
+ $part_svc->{'Hash'}{'cust_pkg_svc'} =
+ $num_cust_svc ? [ $self->cust_svc($part_svc->svcpart) ] : [];
$part_svc;
} $self->part_pkg->pkg_svc;
@@ -1545,7 +1627,8 @@ sub part_svc {
my $num_cust_svc = $self->num_cust_svc($part_svc->svcpart);
$part_svc->{'Hash'}{'num_cust_svc'} = $num_cust_svc; #speak no evail
$part_svc->{'Hash'}{'num_avail'} = 0; #0-$num_cust_svc ?
- $part_svc->{'Hash'}{'cust_pkg_svc'} = [ $self->cust_svc($part_svc->svcpart) ];
+ $part_svc->{'Hash'}{'cust_pkg_svc'} =
+ $num_cust_svc ? [ $self->cust_svc($part_svc->svcpart) ] : [];
$part_svc;
} $self->extra_part_svc;
@@ -1567,20 +1650,38 @@ sub extra_part_svc {
my $pkgnum = $self->pkgnum;
my $pkgpart = $self->pkgpart;
+# qsearch( {
+# 'table' => 'part_svc',
+# 'hashref' => {},
+# 'extra_sql' =>
+# "WHERE 0 = ( SELECT COUNT(*) FROM pkg_svc
+# WHERE pkg_svc.svcpart = part_svc.svcpart
+# AND pkg_svc.pkgpart = ?
+# AND quantity > 0
+# )
+# AND 0 < ( SELECT COUNT(*) FROM cust_svc
+# LEFT JOIN cust_pkg USING ( pkgnum )
+# WHERE cust_svc.svcpart = part_svc.svcpart
+# AND pkgnum = ?
+# )",
+# 'extra_param' => [ [$self->pkgpart=>'int'], [$self->pkgnum=>'int'] ],
+# } );
+
+#seems to benchmark slightly faster...
qsearch( {
- 'table' => 'part_svc',
- 'hashref' => {},
- 'extra_sql' => "WHERE 0 = ( SELECT COUNT(*) FROM pkg_svc
- WHERE pkg_svc.svcpart = part_svc.svcpart
- AND pkg_svc.pkgpart = $pkgpart
- AND quantity > 0
- )
- AND 0 < ( SELECT count(*)
- FROM cust_svc
- LEFT JOIN cust_pkg using ( pkgnum )
- WHERE cust_svc.svcpart = part_svc.svcpart
- AND pkgnum = $pkgnum
- )",
+ 'select' => 'DISTINCT ON (svcpart) part_svc.*',
+ 'table' => 'part_svc',
+ 'addl_from' =>
+ 'LEFT JOIN pkg_svc ON ( pkg_svc.svcpart = part_svc.svcpart
+ AND pkg_svc.pkgpart = ?
+ AND quantity > 0
+ )
+ LEFT JOIN cust_svc ON ( cust_svc.svcpart = part_svc.svcpart )
+ LEFT JOIN cust_pkg USING ( pkgnum )
+ ',
+ 'hashref' => {},
+ 'extra_sql' => "WHERE pkgsvcnum IS NULL AND cust_pkg.pkgnum = ? ",
+ 'extra_param' => [ [$self->pkgpart=>'int'], [$self->pkgnum=>'int'] ],
} );
}
@@ -1635,8 +1736,8 @@ tie my %statuscolor, 'Tie::IxHash',
sub statuses {
my $self = shift; #could be class...
- grep { $_ !~ /^(not yet billed)$/ } #this is a dumb status anyway
- # mayble split btw one-time vs. recur
+ #grep { $_ !~ /^(not yet billed)$/ } #this is a dumb status anyway
+ # # mayble split btw one-time vs. recur
keys %statuscolor;
}
@@ -1651,6 +1752,63 @@ sub statuscolor {
$statuscolor{$self->status};
}
+=item pkg_label
+
+Returns a label for this package. (Currently "pkgnum: pkg - comment" or
+"pkg-comment" depending on user preference).
+
+=cut
+
+sub pkg_label {
+ my $self = shift;
+ my $label = $self->part_pkg->pkg_comment( 'nopkgpart' => 1 );
+ $label = $self->pkgnum. ": $label"
+ if $FS::CurrentUser::CurrentUser->option('show_pkgnum');
+ $label;
+}
+
+=item pkg_label_long
+
+Returns a long label for this package, adding the primary service's label to
+pkg_label.
+
+=cut
+
+sub pkg_label_long {
+ my $self = shift;
+ my $label = $self->pkg_label;
+ my $cust_svc = $self->primary_cust_svc;
+ $label .= ' ('. ($cust_svc->label)[1]. ')' if $cust_svc;
+ $label;
+}
+
+=item primary_cust_svc
+
+Returns a primary service (as FS::cust_svc object) if one can be identified.
+
+=cut
+
+#for labeling purposes - might not 100% match up with part_pkg->svcpart's idea
+
+sub primary_cust_svc {
+ my $self = shift;
+
+ my @cust_svc = $self->cust_svc;
+
+ return '' unless @cust_svc; #no serivces - irrelevant then
+
+ return $cust_svc[0] if scalar(@cust_svc) == 1; #always return a single service
+
+ # primary service as specified in the package definition
+ # or exactly one service definition with quantity one
+ my $svcpart = $self->part_pkg->svcpart;
+ @cust_svc = grep { $_->svcpart == $svcpart } @cust_svc;
+ return $cust_svc[0] if scalar(@cust_svc) == 1;
+
+ #couldn't identify one thing..
+ return '';
+}
+
=item labels
Returns a list of lists, calling the label method for all services
@@ -1679,6 +1837,19 @@ sub h_labels {
map { [ $_->label(@_) ] } $self->h_cust_svc(@_);
}
+=item labels_short
+
+Like labels, except returns a simple flat list, and shortens long
+(currently >5 or the cust_bill-max_same_services configuration value) lists of
+identical services to one line that lists the service label and the number of
+individual services rather than individual items.
+
+=cut
+
+sub labels_short {
+ shift->_labels_short( 'labels', @_ );
+}
+
=item h_labels_short END_TIMESTAMP [ START_TIMESTAMP ]
Like h_labels, except returns a simple flat list, and shortens long
@@ -1689,7 +1860,11 @@ individual services rather than individual items.
=cut
sub h_labels_short {
- my $self = shift;
+ shift->_labels_short( 'h_labels', @_ );
+}
+
+sub _labels_short {
+ my( $self, $method ) = ( shift, shift );
my $conf = new FS::Conf;
my $max_same_services = $conf->config('cust_bill-max_same_services') || 5;
@@ -2039,6 +2214,18 @@ sub active_sql { "
AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
"; }
+=item not_yet_billed_sql
+
+Returns an SQL expression identifying packages which have not yet been billed.
+
+=cut
+
+sub not_yet_billed_sql { "
+ ( cust_pkg.setup IS NULL OR cust_pkg.setup = 0 )
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
+"; }
+
=item inactive_sql
Returns an SQL expression identifying inactive packages (one-time packages
@@ -2048,6 +2235,7 @@ that are otherwise unsuspended/uncancelled).
sub inactive_sql { "
". $_[0]->onetime_sql(). "
+ AND cust_pkg.setup IS NOT NULL AND cust_pkg.setup != 0
AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
"; }
@@ -2100,11 +2288,15 @@ active, inactive, suspended, cancel (or cancelled)
active, inactive, suspended, one-time charge, inactive, cancel (or cancelled)
+=item custom
+
+ boolean selects custom packages
+
=item classnum
=item pkgpart
-list specified how?
+pkgpart or arrayref or hashref of pkgparts
=item setup
@@ -2172,8 +2364,13 @@ sub search_sql {
push @where, FS::cust_pkg->active_sql();
- } elsif ( $params->{'magic'} eq 'inactive'
- || $params->{'status'} eq 'inactive' ) {
+ } elsif ( $params->{'magic'} eq 'not yet billed'
+ || $params->{'status'} eq 'not yet billed' ) {
+
+ push @where, FS::cust_pkg->not_yet_billed_sql();
+
+ } elsif ( $params->{'magic'} =~ /^(one-time charge|inactive)/
+ || $params->{'status'} =~ /^(one-time charge|inactive)/ ) {
push @where, FS::cust_pkg->inactive_sql();
@@ -2187,10 +2384,6 @@ sub search_sql {
push @where, FS::cust_pkg->cancelled_sql();
- } elsif ( $params->{'status'} =~ /^(one-time charge|inactive)$/ ) {
-
- push @where, FS::cust_pkg->inactive_sql();
-
}
###
@@ -2227,12 +2420,68 @@ sub search_sql {
#eslaf
###
+ # parse package report options
+ ###
+
+ my @report_option = ();
+ if ( exists($params->{'report_option'})
+ && $params->{'report_option'} =~ /^([,\d]*)$/
+ )
+ {
+ @report_option = split(',', $1);
+ }
+
+ if (@report_option) {
+ # this will result in the empty set for the dangling comma case as it should
+ push @where,
+ map{ "0 < ( SELECT count(*) FROM part_pkg_option
+ WHERE part_pkg_option.pkgpart = part_pkg.pkgpart
+ AND optionname = 'report_option_$_'
+ AND optionvalue = '1' )"
+ } @report_option;
+ }
+
+ #eslaf
+
+ ###
+ # parse custom
+ ###
+
+ push @where, "part_pkg.custom = 'Y'" if $params->{custom};
+
+ ###
+ # parse censustract
+ ###
+
+ if ( exists($params->{'censustract'}) ) {
+ $params->{'censustract'} =~ /^([.\d]*)$/;
+ my $censustract = "cust_main.censustract = '$1'";
+ $censustract .= ' OR cust_main.censustract is NULL' unless $1;
+ push @where, "( $censustract )";
+ }
+
+ ###
# parse part_pkg
###
- my $pkgpart = join (' OR pkgpart=',
- grep {$_} map { /^(\d+)$/; } ($params->{'pkgpart'}));
- push @where, '(pkgpart=' . $pkgpart . ')' if $pkgpart;
+ if ( ref($params->{'pkgpart'}) ) {
+
+ my @pkgpart = ();
+ if ( ref($params->{'pkgpart'}) eq 'HASH' ) {
+ @pkgpart = grep $params->{'pkgpart'}{$_}, keys %{ $params->{'pkgpart'} };
+ } elsif ( ref($params->{'pkgpart'}) eq 'ARRAY' ) {
+ @pkgpart = @{ $params->{'pkgpart'} };
+ } else {
+ die 'unhandled pkgpart ref '. $params->{'pkgpart'};
+ }
+
+ @pkgpart = grep /^(\d+)$/, @pkgpart;
+
+ push @where, 'pkgpart IN ('. join(',', @pkgpart). ')' if scalar(@pkgpart);
+
+ } elsif ( $params->{'pkgpart'} =~ /^(\d+)$/ ) {
+ push @where, "pkgpart = $1";
+ }
###
# parse dates
@@ -2714,11 +2963,11 @@ All svc_accts which are part of this package have their values reset.
=cut
sub set_usage {
- my ($self, $valueref) = @_;
+ my ($self, $valueref, %opt) = @_;
foreach my $cust_svc ($self->cust_svc){
my $svc_x = $cust_svc->svc_x;
- $svc_x->set_usage($valueref)
+ $svc_x->set_usage($valueref, %opt)
if $svc_x->can("set_usage");
}
}
diff --git a/FS/FS/cust_pkg_reason.pm b/FS/FS/cust_pkg_reason.pm
index 4037513..bb0542b 100644
--- a/FS/FS/cust_pkg_reason.pm
+++ b/FS/FS/cust_pkg_reason.pm
@@ -136,12 +136,15 @@ sub reasontext {
use FS::h_cust_pkg;
use FS::h_cust_pkg_reason;
+use FS::Schema qw(dbdef);
sub _upgrade_data { # class method
my ($class, %opts) = @_;
- my $test_cust_pkg_reason = new FS::cust_pkg_reason;
- return '' unless $test_cust_pkg_reason->dbdef_table->column('action');
+ return '' unless dbdef->table('cust_pkg_reason')->column('action');
+
+ my $action_replace =
+ " AND ( history_action = 'replace_old' OR history_action = 'replace_new' )";
my $count = 0;
my @unmigrated = qsearch('cust_pkg_reason', { 'action' => '' } );
@@ -151,27 +154,24 @@ sub _upgrade_data { # class method
next unless scalar(@history_cust_pkg_reason) == 1;
- my %action_value = ( op => 'LIKE',
- value => 'replace_%',
- );
my $hashref = { pkgnum => $_->pkgnum,
history_date => $history_cust_pkg_reason[0]->history_date,
- history_action => { %action_value },
};
- my @history = qsearch({ table => 'h_cust_pkg',
- hashref => $hashref,
- order_by => 'ORDER BY history_action',
+ my @history = qsearch({ table => 'h_cust_pkg',
+ hashref => $hashref,
+ extra_sql => $action_replace,
+ order_by => 'ORDER BY history_action',
});
my $fuzz = 0;
while (scalar(@history) < 2 && $fuzz < 3) {
$hashref->{history_date}++;
- $hashref->{history_action} = { %action_value }; # qsearch distorts this!
$fuzz++;
- push @history, qsearch({ table => 'h_cust_pkg',
- hashref => $hashref,
- order_by => 'ORDER BY history_action',
+ push @history, qsearch({ table => 'h_cust_pkg',
+ hashref => $hashref,
+ extra_sql => $action_replace,
+ order_by => 'ORDER BY history_action',
});
}
@@ -226,26 +226,23 @@ sub _upgrade_data { # class method
});
foreach ( @unmigrated ) {
- my %action_value = ( op => 'LIKE',
- value => 'replace_%',
- );
my $hashref = { pkgnum => $_->pkgnum,
history_date => $_->date,
- history_action => { %action_value },
};
- my @history = qsearch({ table => 'h_cust_pkg',
- hashref => $hashref,
- order_by => 'ORDER BY history_action',
+ my @history = qsearch({ table => 'h_cust_pkg',
+ hashref => $hashref,
+ extra_sql => $action_replace,
+ order_by => 'ORDER BY history_action',
});
my $fuzz = 0;
while (scalar(@history) < 2 && $fuzz < 3) {
$hashref->{history_date}++;
- $hashref->{history_action} = { %action_value }; # qsearch distorts this!
$fuzz++;
push @history, qsearch({ table => 'h_cust_pkg',
hashref => $hashref,
+ extra_sql => $action_replace,
order_by => 'ORDER BY history_action',
});
}
diff --git a/FS/FS/cust_recon.pm b/FS/FS/cust_recon.pm
new file mode 100644
index 0000000..0a1ca3a
--- /dev/null
+++ b/FS/FS/cust_recon.pm
@@ -0,0 +1,193 @@
+package FS::cust_recon;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::cust_recon - Object methods for cust_recon records
+
+=head1 SYNOPSIS
+
+ use FS::cust_recon;
+
+ $record = new FS::cust_recon \%hash;
+ $record = new FS::cust_recon { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_recon object represents a customer reconcilation. FS::cust_recon
+inherits from FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item reconid
+
+primary key
+
+=item recondate
+
+recondate
+
+=item custnum
+
+custnum
+
+=item agentnum
+
+agentnum
+
+=item last
+
+last
+
+=item first
+
+first
+
+=item address1
+
+address1
+
+=item address2
+
+address2
+
+=item city
+
+city
+
+=item state
+
+state
+
+=item zip
+
+zip
+
+=item pkg
+
+pkg
+
+=item adjourn
+
+adjourn
+
+=item status
+
+status
+
+=item agent_custid
+
+agent_custid
+
+=item agent_pkg
+
+agent_pkg
+
+=item agent_adjourn
+
+agent_adjourn
+
+=item comments
+
+comments
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new customer reconcilation. To add the reconcilation to the database,
+see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'cust_recon'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+=item check
+
+Checks all fields to make sure this is a valid reconcilation. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('reconid')
+ || $self->ut_numbern('recondate')
+ || $self->ut_number('custnum')
+ || $self->ut_number('agentnum')
+ || $self->ut_text('last')
+ || $self->ut_text('first')
+ || $self->ut_text('address1')
+ || $self->ut_textn('address2')
+ || $self->ut_text('city')
+ || $self->ut_textn('state')
+ || $self->ut_textn('zip')
+ || $self->ut_textn('pkg')
+ || $self->ut_numbern('adjourn')
+ || $self->ut_textn('status')
+ || $self->ut_text('agent_custid')
+ || $self->ut_textn('agent_pkg')
+ || $self->ut_numbern('agent_adjourn')
+ || $self->ut_textn('comments')
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+Possibly the existance of this module.
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_statement.pm b/FS/FS/cust_statement.pm
new file mode 100644
index 0000000..83dd5c1
--- /dev/null
+++ b/FS/FS/cust_statement.pm
@@ -0,0 +1,272 @@
+package FS::cust_statement;
+
+use strict;
+use base qw( FS::cust_bill );
+use FS::Record qw( dbh qsearch ); #qsearchs );
+use FS::cust_main;
+use FS::cust_bill;
+
+=head1 NAME
+
+FS::cust_statement - Object methods for cust_statement records
+
+=head1 SYNOPSIS
+
+ use FS::cust_statement;
+
+ $record = new FS::cust_statement \%hash;
+ $record = new FS::cust_statement { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_statement object represents an informational statement which
+aggregates one or more invoices. FS::cust_statement inherits from
+FS::cust_bill.
+
+The following fields are currently supported:
+
+=over 4
+
+=item statementnum
+
+primary key
+
+=item custnum
+
+customer
+
+=item _date
+
+date
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub new { FS::Record::new(@_); }
+
+sub table { 'cust_statement'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ FS::Record::insert($self);
+
+ foreach my $cust_bill (
+ qsearch({
+ 'table' => 'cust_bill',
+ 'hashref' => { 'custnum' => $self->custnum,
+ 'statementnum' => '',
+ },
+ 'extra_sql' => 'FOR UPDATE' ,
+ })
+ )
+ {
+ $cust_bill->statementnum( $self->statementnum );
+ my $error = $cust_bill->replace;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error associating invoice: $error";
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ ''; #no error
+
+}
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete { FS::Record::delete(@_); }
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+sub replace { FS::Record::replace(@_); }
+
+sub replace_check { ''; }
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('statementnum')
+ || $self->ut_foreign_key('custnum', 'cust_main', 'custnum' )
+ || $self->ut_numbern('_date')
+ ;
+ return $error if $error;
+
+ $self->_date(time) unless $self->_date;
+
+ #don't want to call cust_bill, and Record just checks virtual fields
+ #$self->SUPER::check;
+ '';
+
+}
+
+=item cust_bill
+
+Returns the associated invoices (cust_bill records) for this statement.
+
+=cut
+
+sub cust_bill {
+ my $self = shift;
+ qsearch('cust_bill', { 'statementnum' => $self->statementnum } );
+}
+
+sub _aggregate {
+ my( $self, $method ) = ( shift, shift );
+
+ my @agg = ();
+
+ foreach my $cust_bill ( $self->cust_bill ) {
+ push @agg, $cust_bill->$method( @_ );
+ }
+
+ @agg;
+}
+
+sub _total {
+ my( $self, $method ) = ( shift, shift );
+
+ my $total = 0;
+
+ foreach my $cust_bill ( $self->cust_bill ) {
+ $total += $cust_bill->$method( @_ );
+ }
+
+ $total;
+}
+
+=item cust_bill_pkg
+
+Returns the line items (see L<FS::cust_bill_pkg>) for all associated invoices.
+
+=item cust_bill_pkg_pkgnum PKGNUM
+
+Returns the line items (see L<FS::cust_bill_pkg>) for all associated invoices
+and specified pkgnum.
+
+=item cust_bill_pay
+
+Returns all payment applications (see L<FS::cust_bill_pay>) for all associated
+invoices.
+
+=item cust_credited
+
+Returns all applied credits (see L<FS::cust_credit_bill>) for all associated
+invoices.
+
+=item cust_bill_pay_pkgnum PKGNUM
+
+Returns all payment applications (see L<FS::cust_bill_pay>) for all associated
+invoices with matching pkgnum.
+
+=item cust_credited_pkgnum PKGNUM
+
+Returns all applied credits (see L<FS::cust_credit_bill>) for all associated
+invoices with matching pkgnum.
+
+=cut
+
+sub cust_bill_pay { shift->_aggregate('cust_bill_pay', @_); }
+sub cust_credited { shift->_aggregate('cust_credited', @_); }
+sub cust_bill_pay_pkgnum { shift->_aggregate('cust_bill_pay_pkgnum', @_); }
+sub cust_credited_pkgnum { shift->_aggregate('cust_credited_pkgnum', @_); }
+
+sub cust_bill_pkg { shift->_aggregate('cust_bill_pkg', @_); }
+sub cust_bill_pkg_pkgnum { shift->_aggregate('cust_bill_pkg_pkgnum', @_); }
+
+=item tax
+
+Returns the total tax amount for all assoicated invoices.0
+
+=cut
+
+=item charged
+
+Returns the total amount charged for all associated invoices.
+
+=cut
+
+=item owed
+
+Returns the total amount owed for all associated invoices.
+
+=cut
+
+sub tax { shift->_total('tax', @_); }
+sub charged { shift->_total('charged', @_); }
+sub owed { shift->_total('owed', @_); }
+
+#don't show previous info
+sub previous {
+ ( 0 ); # 0, empty list
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_bill>, L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
index 30b2390..3c28204 100644
--- a/FS/FS/cust_svc.pm
+++ b/FS/FS/cust_svc.pm
@@ -375,23 +375,34 @@ Usage example:
my($label, $value, $svcdb) = $cust_svc->label;
+=item label_long
+
+Like the B<label> method, except the second item in the list ("meaningful
+identifier") may be longer - typically, a full name is included.
+
=cut
-sub label {
+sub label { shift->_label('svc_label', @_); }
+sub label_long { shift->_label('svc_label_long', @_); }
+
+sub _label {
my $self = shift;
- carp "FS::cust_svc::label called on $self" if $DEBUG;
+ my $method = shift;
my $svc_x = $self->svc_x
or return "can't find ". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
- $self->_svc_label($svc_x);
+ $self->$method($svc_x);
}
+sub svc_label { shift->_svc_label('label', @_); }
+sub svc_label_long { shift->_svc_label('label_long', @_); }
+
sub _svc_label {
- my( $self, $svc_x ) = ( shift, shift );
+ my( $self, $method, $svc_x ) = ( shift, shift, shift );
(
$self->part_svc->svc,
- $svc_x->label(@_),
+ $svc_x->$method(@_),
$self->part_svc->svcdb,
$self->svcnum
);
@@ -629,7 +640,8 @@ sub attribute_since_sqlradacct {
) or die $dbh->errstr;
$sth->execute($username, $start, $end) or die $sth->errstr;
- $sum += $sth->fetchrow_arrayref->[0];
+ my $row = $sth->fetchrow_arrayref;
+ $sum += $row->[0] if defined($row->[0]);
warn "$mes done SUMing sessions\n"
if $DEBUG;
@@ -680,32 +692,57 @@ CDRs are associated with svc_phone services via svc_phone.phonenum
=cut
sub get_cdrs_for_update {
+ my $self = shift;
+ $self->get_cdrs( 'freesidestatus' => '',
+ 'for_update' => 1,
+ @_,
+ );
+}
+
+sub get_cdrs {
my($self, %options) = @_;
my @fields = ( 'charged_party' );
push @fields, 'src' unless $options{'disable_src'};
- #CDRs are now associated with svc_phone services via svc_phone.phonenum
+ my $for_update = $options{'for_update'} ? 'FOR UPDATE' : '';
+
+ my %hash = ();
+ $hash{'freesidestatus'} = $options{'freesidestatus'}
+ if exists($options{'freesidestatus'});
+
+ #CDRs are associated with svc_phone services via svc_phone.phonenum
+
#return () unless $self->svc_x->isa('FS::svc_phone');
return () unless $self->part_svc->svcdb eq 'svc_phone';
my $number = $self->svc_x->phonenum;
my $prefix = $options{'default_prefix'};
- my @where = map " $_ = '$number' ", @fields;
- push @where, map " $_ = '$prefix$number' ", @fields
+ my @orwhere = map " $_ = '$number' ", @fields;
+ push @orwhere, map " $_ = '$prefix$number' ", @fields
if length($prefix);
if ( $prefix =~ /^\+(\d+)$/ ) {
- push @where, map " $_ = '$1$number' ", @fields
+ push @orwhere, map " $_ = '$1$number' ", @fields
+ }
+
+ my @where = ( ' ( '. join(' OR ', @orwhere ). ' ) ' );
+
+ if ( $options{'begin'} ) {
+ push @where, 'startdate >= '. $options{'begin'};
+ }
+ if ( $options{'end'} ) {
+ push @where, 'startdate < '. $options{'end'};
}
- my $extra_sql = ' AND ( '. join(' OR ', @where ). ' ) ';
+ my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where );
my @cdrs =
qsearch( {
'table' => 'cdr',
- 'hashref' => { 'freesidestatus' => '', },
- 'extra_sql' => "$extra_sql FOR UPDATE",
+ 'hashref' => \%hash,
+ 'extra_sql' => $extra_sql,
+ 'order_by' => "ORDER BY startdate $for_update",
} );
@cdrs;
diff --git a/FS/FS/cust_svc_option.pm b/FS/FS/cust_svc_option.pm
index 0a242d5..07fec90 100644
--- a/FS/FS/cust_svc_option.pm
+++ b/FS/FS/cust_svc_option.pm
@@ -124,8 +124,6 @@ sub check {
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
diff --git a/FS/FS/cdr_upstream_rate.pm b/FS/FS/cust_tax_adjustment.pm
index 2fd9782..5891368 100644
--- a/FS/FS/cdr_upstream_rate.pm
+++ b/FS/FS/cust_tax_adjustment.pm
@@ -1,22 +1,21 @@
-package FS::cdr_upstream_rate;
+package FS::cust_tax_adjustment;
use strict;
-use vars qw( @ISA );
+use base qw( FS::Record );
use FS::Record qw( qsearch qsearchs );
-use FS::rate_detail;
-
-@ISA = qw(FS::Record);
+use FS::cust_main;
+use FS::cust_bill_pkg;
=head1 NAME
-FS::cdr_upstream_rate - Object methods for cdr_upstream_rate records
+FS::cust_tax_adjustment - Object methods for cust_tax_adjustment records
=head1 SYNOPSIS
- use FS::cdr_upstream_rate;
+ use FS::cust_tax_adjustment;
- $record = new FS::cdr_upstream_rate \%hash;
- $record = new FS::cdr_upstream_rate { 'column' => 'value' };
+ $record = new FS::cust_tax_adjustment \%hash;
+ $record = new FS::cust_tax_adjustment { 'column' => 'value' };
$error = $record->insert;
@@ -28,17 +27,36 @@ FS::cdr_upstream_rate - Object methods for cdr_upstream_rate records
=head1 DESCRIPTION
-An FS::cdr_upstream_rate object represents an upstream rate mapping to
-internal rate detail (see L<FS::rate_detail>). FS::cdr_upstream_rate inherits
-from FS::Record. The following fields are currently supported:
+An FS::cust_tax_adjustment object represents an taxation adjustment.
+FS::cust_tax_adjustment inherits from FS::Record. The following fields are
+currently supported:
=over 4
-=item upstreamratenum - primary key
+=item adjustmentnum
+
+primary key
+
+=item custnum
+
+custnum
+
+=item taxname
+
+taxname
+
+=item amount
+
+amount
-=item upstream_rateid - CDR upstream Rate ID (cdr.upstream_rateid - see L<FS::cdr>)
+=item comment
+
+comment
+
+=item billpkgnum
+
+billpkgnum
-=item ratedetailnum - Rate detail - see L<FS::rate_detail>
=back
@@ -48,8 +66,7 @@ from FS::Record. The following fields are currently supported:
=item new HASHREF
-Creates a new upstream rate mapping. To add the upstream rate to the database,
-see L<"insert">.
+Creates a new record. To add the record to the database, see L<"insert">.
Note that this stores the hash reference, not a distinct copy of the hash it
points to. You can ask the object for a copy with the I<hash> method.
@@ -58,7 +75,7 @@ points to. You can ask the object for a copy with the I<hash> method.
# the new method can be inherited from FS::Record, if a table method is defined
-sub table { 'cdr_upstream_rate'; }
+sub table { 'cust_tax_adjustment'; }
=item insert
@@ -88,7 +105,7 @@ returns the error, otherwise returns false.
=item check
-Checks all fields to make sure this is a valid upstream rate. If there is
+Checks all fields to make sure this is a valid record. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
@@ -101,27 +118,21 @@ sub check {
my $self = shift;
my $error =
- $self->ut_numbern('upstreamratenum')
- #|| $self->ut_number('upstream_rateid')
- || $self->ut_alpha('upstream_rateid')
- #|| $self->ut_text('upstream_rateid')
- || $self->ut_foreign_key('ratedetailnum', 'rate_detail', 'ratedetailnum' )
+ $self->ut_numbern('adjustmentnum')
+ || $self->ut_foreign_key('custnum', 'cust_main', 'custnum' )
+ || $self->ut_text('taxname')
+ || $self->ut_money('amount')
+ || $self->ut_textn('comment')
+ || $self->ut_foreign_keyn('billpkgnum', 'cust_bill_pkg', 'billpkgnum' )
;
return $error if $error;
$self->SUPER::check;
}
-=item rate_detail
-
-Returns the internal rate detail object for this upstream rate (see
-L<FS::rate_detail>).
-
-=cut
-
-sub rate_detail {
+sub cust_bill_pkg {
my $self = shift;
- qsearchs('rate_detail', { 'ratedetailnum' => $self->ratedetailnum } );
+ qsearchs('cust_bill_pkg', { 'billpkgnum' => $self->billpkgnum } );
}
=back
diff --git a/FS/FS/cust_tax_location.pm b/FS/FS/cust_tax_location.pm
index b7437a0..161a654 100644
--- a/FS/FS/cust_tax_location.pm
+++ b/FS/FS/cust_tax_location.pm
@@ -119,25 +119,31 @@ sub check {
|| $self->ut_text('state')
|| $self->ut_numbern('plus4hi')
|| $self->ut_numbern('plus4lo')
- || $self->ut_enum('default', [ '', ' ', 'Y' ] ) # wtf?
+ || $self->ut_enum('default_location', [ '', 'Y' ] )
|| $self->ut_enum('cityflag', [ '', 'I', 'O', 'B' ] )
|| $self->ut_alpha('geocode')
;
return $error if $error;
- #ugh! cch canada weirdness
- if ($self->state eq 'CN') {
+ #ugh! cch canada weirdness and more
+ if ($self->state eq 'CN' && $self->data_vendor eq 'cch-zip' ) {
$error = "Illegal cch canadian zip"
unless $self->zip =~ /^[A-Z]$/;
+ } elsif ($self->state =~ /^E([B-DFGILNPR-UW])$/ && $self->data_vendor eq 'cch-zip' ) {
+ $error = "Illegal cch european zip"
+ unless $self->zip =~ /^E$1$/;
} else {
$error = $self->ut_number('zip', $self->state eq 'CN' ? 'CA' : 'US');
}
return $error if $error;
- #ugh! cch canada weirdness
+ #ugh! cch canada weirdness and more
return "must specify either city/county or plus4lo/plus4hi"
unless ( $self->plus4lo && $self->plus4hi ||
- ($self->city || $self->state eq 'CN') && $self->county
+ ( $self->city ||
+ $self->state eq 'CN' ||
+ $self->state =~ /^E([B-DFGILNPR-UW])$/
+ ) && $self->county
);
$self->SUPER::check;
@@ -179,7 +185,7 @@ sub batch_import {
}
if ( $format eq 'cch' || $format eq 'cch-update' ) {
- @fields = qw( zip state plus4lo plus4hi geocode default );
+ @fields = qw( zip state plus4lo plus4hi geocode default_location );
push @fields, 'actionflag' if $format eq 'cch-update';
$imported++ if $format eq 'cch-update'; #empty file ok
@@ -188,6 +194,7 @@ sub batch_import {
my $hash = shift;
$hash->{'data_vendor'} = 'cch';
+ $hash->{'default_location'} =~ s/ //g;
if (exists($hash->{actionflag}) && $hash->{actionflag} eq 'D') {
delete($hash->{actionflag});
@@ -210,7 +217,7 @@ sub batch_import {
};
} elsif ( $format eq 'cch-zip' || $format eq 'cch-update-zip' ) {
- @fields = qw( zip city county state postalcity countyfips countydef default geocode cityflag unique );
+ @fields = qw( zip city county state postalcity countyfips countydef default_location geocode cityflag unique );
push @fields, 'actionflag' if $format eq 'cch-update-zip';
$imported++ if $format eq 'cch-update'; #empty file ok
@@ -222,6 +229,7 @@ sub batch_import {
delete($hash->{$_}) foreach qw( countyfips countydef unique );
$hash->{'cityflag'} =~ s/ //g;
+ $hash->{'default_location'} =~ s/ //g;
if (exists($hash->{actionflag}) && $hash->{actionflag} eq 'D') {
delete($hash->{actionflag});
@@ -275,7 +283,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing locations"
);
die $error if $error;
$last = time;
diff --git a/FS/FS/h_cust_svc.pm b/FS/FS/h_cust_svc.pm
index e030436..d280d53 100644
--- a/FS/FS/h_cust_svc.pm
+++ b/FS/FS/h_cust_svc.pm
@@ -52,9 +52,15 @@ If a service is found, returns a list consisting of:
=cut
-sub label {
+sub label { shift->_label('svc_label', @_); }
+sub label_long { shift->_label('svc_label_long', @_); }
+
+sub _label {
my $self = shift;
- carp "FS::h_cust_svc::label called on $self" if $DEBUG;
+ my $method = shift;
+
+ #carp "FS::h_cust_svc::_label called on $self" if $DEBUG;
+ warn "FS::h_cust_svc::_label called on $self for $method" if $DEBUG;
my $svc_x = $self->h_svc_x(@_);
return () unless $svc_x;
my $part_svc = $self->part_svc;
@@ -65,7 +71,7 @@ sub label {
}
my @label;
- eval { @label = $self->_svc_label($svc_x, @_); };
+ eval { @label = $self->$method($svc_x, @_); };
if ($@) {
carp 'while resolving history record for svcdb/svcnum ' .
diff --git a/FS/FS/part_device.pm b/FS/FS/part_device.pm
new file mode 100644
index 0000000..79a534a
--- /dev/null
+++ b/FS/FS/part_device.pm
@@ -0,0 +1,134 @@
+package FS::part_device;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record; # qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::part_device - Object methods for part_device records
+
+=head1 SYNOPSIS
+
+ use FS::part_device;
+
+ $record = new FS::part_device \%hash;
+ $record = new FS::part_device { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::part_device object represents a phone device definition. FS::part_device
+inherits from FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item devicepart
+
+primary key
+
+=item devicename
+
+devicename
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'part_device'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('devicepart')
+ || $self->ut_text('devicename')
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+sub process_batch_import {
+ my $job = shift;
+
+ my $opt = { 'table' => 'part_device',
+ 'params' => [],
+ 'formats' => { 'default' => [ 'devicename' ] },
+ 'default_csv' => 1,
+ };
+
+ FS::Record::process_batch_import( $job, $opt, @_ );
+
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_event.pm b/FS/FS/part_event.pm
index 6f2c536..c98c3f8 100644
--- a/FS/FS/part_event.pm
+++ b/FS/FS/part_event.pm
@@ -52,7 +52,7 @@ following fields are currently supported:
=item event - event name
-=item eventtable - table name against which this event is triggered; currently "cust_bill" (the traditional invoice events), "cust_main" (customer events) or "cust_pkg (package events)
+=item eventtable - table name against which this event is triggered; currently "cust_bill" (the traditional invoice events), "cust_main" (customer events) or "cust_pkg (package events) (or "cust_statement")
=item check_freq - how often events of this type are checked; currently "1d" (daily) and "1m" (monthly) are recognized. Note that the apprioriate freeside-daily and/or freeside-monthly cron job needs to be in place.
@@ -133,7 +133,7 @@ sub check {
my $error =
$self->ut_numbern('eventpart')
|| $self->ut_text('event')
- || $self->ut_enum('eventtable', [ 'cust_bill', 'cust_main', 'cust_pkg' ] )
+ || $self->ut_enum('eventtable', [ $self->eventtables ] )
|| $self->ut_enum('check_freq', [ '1d', '1m' ])
|| $self->ut_number('weight')
|| $self->ut_alpha('action')
@@ -273,6 +273,7 @@ sub eventtable_labels {
'cust_bill' => 'Invoice',
'cust_main' => 'Customer',
'cust_pay_batch' => 'Batch payment',
+ 'cust_statement' => 'Statement', #too general a name here? "Invoice group"?
;
\%hash
@@ -310,6 +311,7 @@ sub eventtable_pkey {
'cust_bill' => 'invnum',
'cust_pkg' => 'pkgnum',
'cust_pay_batch' => 'paybatchnum',
+ 'cust_statement' => 'statementnum',
};
}
diff --git a/FS/FS/part_event/Action.pm b/FS/FS/part_event/Action.pm
index 57239d7..45219a3 100644
--- a/FS/FS/part_event/Action.pm
+++ b/FS/FS/part_event/Action.pm
@@ -54,6 +54,19 @@ sub eventtable_hashref {
};
}
+=item event_stage
+
+Action classes may define an event_stage method to indicate a preference
+for being run at a non-standard stage of the billing and collection process.
+
+This method may currently return "collect" (the default) or "pre-bill".
+
+=cut
+
+sub event_stage {
+ 'collect';
+}
+
=item option_fields
Action classes may define an option_fields method to indicate that they
diff --git a/FS/FS/part_event/Action/cust_bill_email.pm b/FS/FS/part_event/Action/cust_bill_email.pm
new file mode 100644
index 0000000..a5cd861
--- /dev/null
+++ b/FS/FS/part_event/Action/cust_bill_email.pm
@@ -0,0 +1,23 @@
+package FS::part_event::Action::cust_bill_email;
+
+use strict;
+use base qw( FS::part_event::Action );
+
+sub description { 'Send invoice (email only)'; }
+
+sub eventtable_hashref {
+ { 'cust_bill' => 1 };
+}
+
+sub default_weight { 51; }
+
+sub do_action {
+ my( $self, $cust_bill ) = @_;
+
+ #my $cust_main = $self->cust_main($cust_bill);
+ my $cust_main = $cust_bill->cust_main;
+
+ $cust_bill->email;
+}
+
+1;
diff --git a/FS/FS/part_event/Action/cust_bill_fee_percent.pm b/FS/FS/part_event/Action/cust_bill_fee_percent.pm
index 570fd63..b0397d4 100644
--- a/FS/FS/part_event/Action/cust_bill_fee_percent.pm
+++ b/FS/FS/part_event/Action/cust_bill_fee_percent.pm
@@ -9,10 +9,17 @@ sub eventtable_hashref {
{ 'cust_bill' => 1 };
}
+sub event_stage { 'pre-bill'; }
+
sub option_fields {
(
- 'percent' => { label=>'Percent', size=>2, },
- 'reason' => 'Reason',
+ 'percent' => { label=>'Percent', size=>2, },
+ 'reason' => 'Reason',
+ 'taxclass' => { label=>'Tax class', type=>'select-taxclass', },
+ 'nextbill' => { label=>'Hold late fee until next invoice',
+ type=>'checkbox', value=>'Y' },
+ 'setuptax' => { label=>'Late fee is tax exempt',
+ type=>'checkbox', value=>'Y' },
);
}
@@ -24,10 +31,24 @@ sub do_action {
#my $cust_main = $self->cust_main($cust_bill);
my $cust_main = $cust_bill->cust_main;
- my $error = $cust_main->charge(
- sprintf('%.2f', $cust_bill->owed * $self->option('percent') / 100 ),
- $self->option('reason')
+ my $conf = new FS::Conf;
+
+ my $amount =
+ sprintf('%.2f', $cust_bill->owed * $self->option('percent') / 100 );
+
+ my %charge = (
+ 'amount' => $amount,
+ 'pkg' => $self->option('reason'),
+ 'taxclass' => $self->option('taxclass'),
+ 'classnum' => $conf->config('finance_pkgclass'),
+ 'setuptax' => $self->option('setuptax'),
);
+
+ $charge{'start_date'} = $cust_main->next_bill_date #unless its more than N months away?
+ if $self->option('nextbill');
+
+ my $error = $cust_main->charge( \%charge );
+
die $error if $error;
'';
diff --git a/FS/FS/part_event/Action/cust_bill_send.pm b/FS/FS/part_event/Action/cust_bill_send.pm
index 663caf1..587a7c6 100644
--- a/FS/FS/part_event/Action/cust_bill_send.pm
+++ b/FS/FS/part_event/Action/cust_bill_send.pm
@@ -14,9 +14,6 @@ sub default_weight { 50; }
sub do_action {
my( $self, $cust_bill ) = @_;
- #my $cust_main = $self->cust_main($cust_bill);
- my $cust_main = $cust_bill->cust_main;
-
$cust_bill->send;
}
diff --git a/FS/FS/part_event/Action/cust_bill_send_reminder.pm b/FS/FS/part_event/Action/cust_bill_send_reminder.pm
new file mode 100644
index 0000000..2ba8136
--- /dev/null
+++ b/FS/FS/part_event/Action/cust_bill_send_reminder.pm
@@ -0,0 +1,31 @@
+package FS::part_event::Action::cust_bill_send_reminder;
+
+use strict;
+use base qw( FS::part_event::Action );
+
+sub description { 'Send invoice (email/print/fax) reminder'; }
+
+sub eventtable_hashref {
+ { 'cust_bill' => 1 };
+}
+
+sub option_fields {
+ (
+ 'notice_name' => 'Reminder name',
+ #'notes' => { 'label' => 'Reminder notes' },
+ #include standard notes? no/prepend/append
+ );
+}
+
+sub default_weight { 50; }
+
+sub do_action {
+ my( $self, $cust_bill ) = @_;
+
+ #my $cust_main = $self->cust_main($cust_bill);
+ #my $cust_main = $cust_bill->cust_main;
+
+ $cust_bill->send({ 'notice_name' => $self->option('notice_name') });
+}
+
+1;
diff --git a/FS/FS/part_event/Action/cust_bill_spool_csv.pm b/FS/FS/part_event/Action/cust_bill_spool_csv.pm
index f20ee46..43d2300 100644
--- a/FS/FS/part_event/Action/cust_bill_spool_csv.pm
+++ b/FS/FS/part_event/Action/cust_bill_spool_csv.pm
@@ -35,6 +35,7 @@ sub option_fields {
},
'spoolagent_spools' => { label => 'Individual per-agent spools',
type => 'checkbox',
+ value => '1',
},
);
}
diff --git a/FS/FS/part_event/Action/cust_statement.pm b/FS/FS/part_event/Action/cust_statement.pm
new file mode 100644
index 0000000..2d9e877
--- /dev/null
+++ b/FS/FS/part_event/Action/cust_statement.pm
@@ -0,0 +1,39 @@
+package FS::part_event::Action::cust_statement;
+
+use strict;
+
+use base qw( FS::part_event::Action );
+
+use FS::cust_statement;
+
+sub description {
+ 'Group invoices into an informational statement.';
+}
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub default_weight {
+ 90;
+}
+
+sub do_action {
+ my( $self, $cust_main ) = @_;
+
+ #my( $self, $object ) = @_;
+ #my $cust_main = $self->cust_main($object);
+
+ my $cust_statement = new FS::cust_statement {
+ 'custnum' => $cust_main->custnum
+ };
+ my $error = $cust_statement->insert;
+ die $error if $error;
+
+ '';
+
+}
+
+1;
diff --git a/FS/FS/part_event/Action/cust_statement_send.pm b/FS/FS/part_event/Action/cust_statement_send.pm
new file mode 100644
index 0000000..74cc48c
--- /dev/null
+++ b/FS/FS/part_event/Action/cust_statement_send.pm
@@ -0,0 +1,26 @@
+package FS::part_event::Action::cust_statement_send;
+
+use strict;
+
+use base qw( FS::part_event::Action );
+
+sub description {
+ 'Send statement (email/print/fax)';
+}
+
+sub eventtable_hashref {
+ { 'cust_statement' => 1, };
+}
+
+sub default_weight {
+ 95;
+}
+
+sub do_action {
+ my( $self, $cust_statement ) = @_;
+
+ $cust_statement->send( 'statement' ); #XXX configure
+
+}
+
+1;
diff --git a/FS/FS/part_event/Action/fee.pm b/FS/FS/part_event/Action/fee.pm
index 3cf50fb..163b4fa 100644
--- a/FS/FS/part_event/Action/fee.pm
+++ b/FS/FS/part_event/Action/fee.pm
@@ -5,10 +5,17 @@ use base qw( FS::part_event::Action );
sub description { 'Late fee (flat)'; }
+sub event_stage { 'pre-bill'; }
+
sub option_fields {
(
- 'charge' => { label=>'Amount', type=>'money', }, # size=>7, },
- 'reason' => 'Reason',
+ 'charge' => { label=>'Amount', type=>'money', }, # size=>7, },
+ 'reason' => 'Reason',
+ 'taxclass' => { label=>'Tax class', type=>'select-taxclass', },
+ 'nextbill' => { label=>'Hold late fee until next invoice',
+ type=>'checkbox', value=>'Y' },
+ 'setuptax' => { label=>'Late fee is tax exempt',
+ type=>'checkbox', value=>'Y' },
);
}
@@ -19,7 +26,20 @@ sub do_action {
my $cust_main = $self->cust_main($cust_object);
- my $error = $cust_main->charge( $self->option('charge'), $self->option('reason') );
+ my $conf = new FS::Conf;
+
+ my %charge = (
+ 'amount' => $self->option('charge'),
+ 'pkg' => $self->option('reason'),
+ 'taxclass' => $self->option('taxclass'),
+ 'classnum' => $conf->config('finance_pkgclass'),
+ 'setuptax' => $self->option('setuptax'),
+ );
+
+ $charge{'start_date'} = $cust_main->next_bill_date #unless its more than N months away?
+ if $self->option('nextbill');
+
+ my $error = $cust_main->charge( \%charge );
die $error if $error;
diff --git a/FS/FS/part_event/Action/pkg_referral_credit_pkg.pm b/FS/FS/part_event/Action/pkg_referral_credit_pkg.pm
index 08cf9a8..eb9b510 100644
--- a/FS/FS/part_event/Action/pkg_referral_credit_pkg.pm
+++ b/FS/FS/part_event/Action/pkg_referral_credit_pkg.pm
@@ -38,6 +38,7 @@ sub _calc_referral_credit {
my $what = $self->option('what');
+ #false laziness w/Condition/cust_payments_pkg.pm
if ( $what eq 'base_recur_permonth' ) { #huh. yuck.
if ( $part_pkg->freq !~ /^\d+$/ ) {
die 'WARNING: Not crediting customer '. $cust_main->referral_custnum.
diff --git a/FS/FS/part_event/Action/writeoff.pm b/FS/FS/part_event/Action/writeoff.pm
new file mode 100644
index 0000000..8529d29
--- /dev/null
+++ b/FS/FS/part_event/Action/writeoff.pm
@@ -0,0 +1,33 @@
+package FS::part_event::Action::writeoff;
+
+use strict;
+use base qw( FS::part_event::Action );
+
+sub description { 'Write off bad debt with a credit entry.'; }
+
+sub option_fields {
+ (
+ #'charge' => { label=>'Amount', type=>'money', }, # size=>7, },
+ 'reasonnum' => { 'label' => 'Reason',
+ 'type' => 'select-reason',
+ 'reason_class' => 'R',
+ },
+ );
+}
+
+sub default_weight { 65; }
+
+sub do_action {
+ my( $self, $cust_object ) = @_;
+
+ my $cust_main = $self->cust_main($cust_object);
+
+ my $reasonnum = $self->option('reasonnum');
+
+ my $error = $cust_main->credit( $cust_main->balance, \$reasonnum );
+ die $error if $error;
+
+ '';
+}
+
+1;
diff --git a/FS/FS/part_event/Condition.pm b/FS/FS/part_event/Condition.pm
index 544b560..ddd8a61 100644
--- a/FS/FS/part_event/Condition.pm
+++ b/FS/FS/part_event/Condition.pm
@@ -41,6 +41,7 @@ of eventtables (values set true indicate the condition can be tested):
'cust_bill' => 1,
'cust_pkg' => 0,
'cust_pay_batch' => 0,
+ 'cust_statement' => 0,
};
}
@@ -52,6 +53,7 @@ sub eventtable_hashref {
'cust_bill' => 1,
'cust_pkg' => 1,
'cust_pay_batch' => 1,
+ 'cust_statement' => 1,
};
}
diff --git a/FS/FS/part_event/Condition/cust_payments.pm b/FS/FS/part_event/Condition/cust_payments.pm
index 41ef6c7..477ecdb 100644
--- a/FS/FS/part_event/Condition/cust_payments.pm
+++ b/FS/FS/part_event/Condition/cust_payments.pm
@@ -3,7 +3,7 @@ package FS::part_event::Condition::cust_payments;
use strict;
use base qw( FS::part_event::Condition );
-sub description { 'Customer total payments'; }
+sub description { 'Customer total payments (amount)'; }
sub option_fields {
(
diff --git a/FS/FS/part_event/Condition/cust_payments_pkg.pm b/FS/FS/part_event/Condition/cust_payments_pkg.pm
new file mode 100644
index 0000000..d6c493b
--- /dev/null
+++ b/FS/FS/part_event/Condition/cust_payments_pkg.pm
@@ -0,0 +1,68 @@
+package FS::part_event::Condition::cust_payments_pkg;
+
+use strict;
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer total payments (multiplier of package)'; }
+
+sub eventtable_hashref {
+ { 'cust_pkg' => 1 };
+}
+
+sub option_fields {
+ (
+ 'over_times' => { 'label' => 'Customer total payments as least',
+ 'type' => 'text',
+ 'value' => '1', #default
+ },
+ 'what' => { 'label' => 'Times',
+ 'type' => 'select',
+ #also add some way to specify in the package def, no?
+ 'options' => [ qw( base_recur_permonth ) ],
+ 'labels' => { 'base_recur_permonth' => 'Base monthly fee', },
+ },
+ );
+}
+
+sub condition {
+ my($self, $cust_pkg) = @_;
+
+ my $cust_main = $self->cust_main($cust_pkg);
+
+ my $part_pkg = $cust_pkg->part_pkg;
+
+ my $over_times = $self->option('over_times');
+ $over_times = 0 unless length($over_times);
+
+ my $what = $self->option('what');
+
+ #false laziness w/Condition/cust_payments_pkg.pm
+ if ( $what eq 'base_recur_permonth' ) { #huh. yuck.
+ if ( $part_pkg->freq !~ /^\d+$/ ) {
+ die 'WARNING: Not crediting customer '. $cust_main->referral_custnum.
+ ' for package '. $cust_pkg->pkgnum.
+ ' ( customer '. $cust_pkg->custnum. ')'.
+ ' - Referral credits not (yet) available for '.
+ ' packages with '. $part_pkg->freq_pretty. ' frequency';
+ }
+ }
+
+ $cust_main->total_paid >= $over_times * $part_pkg->$what($cust_pkg);
+
+}
+
+#XXX add for efficiency. could use cust_main::total_paid_sql
+#use FS::cust_main;
+#sub condition_sql {
+# my( $class, $table ) = @_;
+#
+# my $over = $class->condition_sql_option('balance');
+#
+# my $balance_sql = FS::cust_main->balance_sql;
+#
+# "$balance_sql > $over";
+#
+#}
+
+1;
+
diff --git a/FS/FS/part_event/Condition/has_pkg_class.pm b/FS/FS/part_event/Condition/has_pkg_class.pm
new file mode 100644
index 0000000..59a3675
--- /dev/null
+++ b/FS/FS/part_event/Condition/has_pkg_class.pm
@@ -0,0 +1,40 @@
+package FS::part_event::Condition::has_pkg_class;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+use FS::Record qw( qsearch );
+use FS::pkg_class;
+
+sub description {
+ 'Customer has uncancelled package with class';
+}
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+#something like this
+sub option_fields {
+ (
+ 'pkgclass' => { 'label' => 'Package Class',
+ 'type' => 'select-pkg_class',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $hashref = $self->option('pkgclass') || {};
+ grep $hashref->{ $_->part_pkg->classnum }, $cust_main->ncancelled_pkgs;
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/has_pkgpart.pm b/FS/FS/part_event/Condition/has_pkgpart.pm
new file mode 100644
index 0000000..c54b7e2
--- /dev/null
+++ b/FS/FS/part_event/Condition/has_pkgpart.pm
@@ -0,0 +1,41 @@
+package FS::part_event::Condition::has_pkgpart;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer has uncancelled package of specified definitions'; }
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub option_fields {
+ (
+ 'if_pkgpart' => { 'label' => 'Only packages: ',
+ 'type' => 'select-part_pkg',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $if_pkgpart = $self->option('if_pkgpart') || {};
+ grep $if_pkgpart->{ $_->pkgpart }, $cust_main->ncancelled_pkgs;
+
+}
+
+#XXX
+#sub condition_sql {
+#
+#}
+
+1;
diff --git a/FS/FS/part_event/Condition/has_referral_custnum.pm b/FS/FS/part_event/Condition/has_referral_custnum.pm
index d43d6c0..61a8155 100644
--- a/FS/FS/part_event/Condition/has_referral_custnum.pm
+++ b/FS/FS/part_event/Condition/has_referral_custnum.pm
@@ -7,18 +7,42 @@ use base qw( FS::part_event::Condition );
sub description { 'Customer has a referring customer'; }
+sub option_fields {
+ (
+ 'active' => { 'label' => 'Referring customer is active',
+ 'type' => 'checkbox',
+ 'value' => 'Y',
+ },
+ );
+}
+
sub condition {
my($self, $object) = @_;
my $cust_main = $self->cust_main($object);
- $cust_main->referral_custnum;
+ if ( $self->option('active') ) {
+
+ return 0 unless $cust_main->referral_custnum;
+
+ #check for no cust_main for referral_custnum? (deleted?)
+
+ $cust_main->referral_custnum_cust_main->status eq 'active';
+
+ } else {
+
+ $cust_main->referral_custnum; # ? 1 : 0;
+
+ }
+
}
sub condition_sql {
#my( $class, $table ) = @_;
"cust_main.referral_custnum IS NOT NULL";
+
+ #XXX a bit harder to check active status here
}
1;
diff --git a/FS/FS/part_event/Condition/hasnt_pkgpart.pm b/FS/FS/part_event/Condition/hasnt_pkgpart.pm
new file mode 100644
index 0000000..421d023
--- /dev/null
+++ b/FS/FS/part_event/Condition/hasnt_pkgpart.pm
@@ -0,0 +1,40 @@
+package FS::part_event::Condition::hasnt_pkgpart;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer does not have uncancelled package of specified definitions'; }
+
+sub eventtable_hashref {
+ { 'cust_main' => 1,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub option_fields {
+ (
+ 'unless_pkgpart' => { 'label' => 'Packages: ',
+ 'type' => 'select-part_pkg',
+ 'multiple' => 1,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ #XXX test
+ my $unless_pkgpart = $self->option('unless_pkgpart') || {};
+ ! grep $unless_pkgpart->{ $_->pkgpart }, $cust_main->ncancelled_pkgs;
+}
+
+#XXX
+#sub condition_sql {
+#
+#}
+
+1;
diff --git a/FS/FS/part_event/Condition/once.pm b/FS/FS/part_event/Condition/once.pm
index 5a9161f..d004814 100644
--- a/FS/FS/part_event/Condition/once.pm
+++ b/FS/FS/part_event/Condition/once.pm
@@ -7,7 +7,7 @@ use FS::cust_event;
use base qw( FS::part_event::Condition );
-sub description { "Don't run this event again after it has completed sucessfully"; }
+sub description { "Don't run this event again after it has completed successfully"; }
sub implicit_flag { 10; }
diff --git a/FS/FS/part_export/acct_plesk.pm b/FS/FS/part_export/acct_plesk.pm
index 1be820a..d8d70a3 100644
--- a/FS/FS/part_export/acct_plesk.pm
+++ b/FS/FS/part_export/acct_plesk.pm
@@ -23,7 +23,7 @@ Real-time export to
<a href="http://www.swsoft.com/">Plesk</a> managed server.
Requires installation of
<a href="http://search.cpan.org/dist/Net-Plesk">Net::Plesk</a>
-from CPAN.
+from CPAN and proper <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration:acct_plesk.pm">configuration</a>.
END
);
diff --git a/FS/FS/part_export/amazon_ec2.pm b/FS/FS/part_export/amazon_ec2.pm
new file mode 100644
index 0000000..0e65ca0
--- /dev/null
+++ b/FS/FS/part_export/amazon_ec2.pm
@@ -0,0 +1,169 @@
+package FS::part_export::amazon_ec2;
+
+use base qw( FS::part_export );
+
+use vars qw(@ISA %info $replace_ok_kludge);
+use Tie::IxHash;
+use FS::Record qw( qsearchs );
+use FS::svc_external;
+
+tie my %options, 'Tie::IxHash',
+ 'access_key' => { label => 'AWS access key', },
+ 'secret_key' => { label => 'AWS secret key', },
+ 'ami' => { label => 'AMI', 'default' => 'ami-ff46a796', },
+ 'keyname' => { label => 'Keypair name', },
+ #option to turn off (or on) ip address allocation
+;
+
+%info = (
+ 'svc' => 'svc_external',
+ 'desc' =>
+ 'Export to Amazon EC2',
+ 'options' => \%options,
+ 'notes' => <<'END'
+Create instances in the Amazon EC2 (Elastic compute cloud). Install
+Net::Amazon::EC2 perl module. Advisable to set svc_external-skip_manual config
+option.
+END
+);
+
+$replace_ok_kludge = 0;
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self, $svc_external) = (shift, shift);
+ $err_or_queue = $self->amazon_ec2_queue( $svc_external->svcnum, 'insert',
+ $svc_external->svcnum,
+ $self->option('ami'),
+ $self->option('keyname'),
+ );
+ ref($err_or_queue) ? '' : $err_or_queue;
+}
+
+sub _export_replace {
+ my( $self, $new, $old ) = (shift, shift, shift);
+ return '' if $replace_ok_kludge;
+ return "can't change instance id or IP address";
+ #$err_or_queue = $self->amazon_ec2_queue( $new->svcnum,
+ # 'replace', $new->username, $new->_password );
+ #ref($err_or_queue) ? '' : $err_or_queue;
+}
+
+sub _export_delete {
+ my( $self, $svc_external ) = (shift, shift);
+ my( $instance_id, $ip ) = split(/:/, $svc_external->title );
+ $err_or_queue = $self->amazon_ec2_queue( $svc_external->svcnum, 'delete',
+ $instance_id,
+ $ip,
+ );
+ ref($err_or_queue) ? '' : $err_or_queue;
+}
+
+#these three are optional
+# fallback for svc_acct will change and restore password
+#sub _export_suspend {
+# my( $self, $svc_something ) = (shift, shift);
+# $err_or_queue = $self->amazon_ec2_queue( $svc_something->svcnum,
+# 'suspend', $svc_something->username );
+# ref($err_or_queue) ? '' : $err_or_queue;
+#}
+#
+#sub _export_unsuspend {
+# my( $self, $svc_something ) = (shift, shift);
+# $err_or_queue = $self->amazon_ec2_queue( $svc_something->svcnum,
+# 'unsuspend', $svc_something->username );
+# ref($err_or_queue) ? '' : $err_or_queue;
+#}
+
+sub export_links {
+ my($self, $svc_external, $arrayref) = (shift, shift, shift);
+ my( $instance_id, $ip ) = split(/:/, $svc_external->title );
+
+ push @$arrayref, qq!<A HREF="http://$ip/">http://$ip/</A>!;
+ '';
+}
+
+###
+
+#a good idea to queue anything that could fail or take any time
+sub amazon_ec2_queue {
+ my( $self, $svcnum, $method ) = (shift, shift, shift);
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ 'job' => "FS::part_export::amazon_ec2::amazon_ec2_$method",
+ };
+ $queue->insert( $self->option('access_key'),
+ $self->option('secret_key'),
+ @_
+ )
+ or $queue;
+}
+
+sub amazon_ec2_new {
+ my( $access_key, $secret_key, @rest ) = @_;
+
+ eval 'use Net::Amazon::EC2;';
+ die $@ if $@;
+
+ my $ec2 = new Net::Amazon::EC2 'AWSAccessKeyId' => $access_key,
+ 'SecretAccessKey' => $secret_key;
+
+ ( $ec2, @rest );
+}
+
+sub amazon_ec2_insert { #subroutine, not method
+ my( $ec2, $svcnum, $ami, $keyname ) = amazon_ec2_new(@_);
+
+ my $reservation_info = $ec2->run_instances( 'ImageId' => $ami,
+ 'KeyName' => $keyname,
+ 'MinCount' => 1,
+ 'MaxCount' => 1,
+ );
+
+ my $instance_id = $reservation_info->instances_set->[0]->instance_id;
+
+ my $ip = $ec2->allocate_address
+ or die "can't allocate address";
+ $ec2->associate_address('InstanceId' => $instance_id,
+ 'PublicIp' => $ip,
+ )
+ or die "can't assocate IP address $ip with instance $instance_id";
+
+ my $svc_external = qsearchs('svc_external', { 'svcnum' => $svcnum } )
+ or die "can't find svc_external.svcnum $svcnum\n";
+
+ $svc_external->title("$instance_id:$ip");
+
+ local($replace_ok_kludge) = 1;
+ my $error = $svc_external->replace;
+ die $error if $error;
+
+}
+
+#sub amazon_ec2_replace { #subroutine, not method
+#}
+
+sub amazon_ec2_delete { #subroutine, not method
+ my( $ec2, $id, $ip ) = amazon_ec2_new(@_);
+
+ my $instance_id = sprintf('i-%x', $id);
+ $ec2->disassociate_address('PublicIp'=>$ip)
+ or die "can't dissassocate $ip";
+
+ $ec2->release_address('PublicIp'=>$ip)
+ or die "can't release $ip";
+
+ my $result = $ec2->terminate_instances('InstanceId'=>$instance_id);
+ #check for instance_id match or something?
+
+}
+
+#sub amazon_ec2_suspend { #subroutine, not method
+#}
+
+#sub amazon_ec2_unsuspend { #subroutine, not method
+#}
+
+1;
+
diff --git a/FS/FS/part_export/domreg_net_dri.pm b/FS/FS/part_export/domreg_net_dri.pm
new file mode 100644
index 0000000..bf01602
--- /dev/null
+++ b/FS/FS/part_export/domreg_net_dri.pm
@@ -0,0 +1,614 @@
+package FS::part_export::domreg_net_dri;
+
+use vars qw(@ISA %info %options $conf);
+use Tie::IxHash;
+use FS::part_export::null;
+
+=head1 NAME
+
+FS::part_export::domreg_net_dri - Register or transfer domains with Net::DRI
+
+=head1 DESCRIPTION
+
+This module handles registering and transferring domains with select registrars or registries supported
+by L<Net::DRI>.
+
+As a part_export, this module can be designated for use with svc_domain services. When the svc_domain object
+is inserted into the Freeside database, registration or transferring of the domain may be initiated, depending
+on the setting of the svc_domain's action field. Further operations can be performed from the View Domain screen.
+
+Logging information is written to the Freeside log folder.
+
+For correct operation you must add name/value pairs to the protcol and transport options fields. The setttings
+depend on the domain registry driver (DRD) selected.
+
+=over 4
+
+=item N - Register the domain
+
+=item M - Transfer the domain
+
+=item I - Ignore the domain for registration purposes
+
+=back
+
+=cut
+
+@ISA = qw(FS::part_export::null);
+
+my @tldlist = qw/com net org biz info name mobi at be ca cc ch cn de dk es eu fr it mx nl tv uk us/;
+
+my $opensrs_protocol_opts=<<'END';
+username=
+password=
+auto_renew=0
+affiliate_id=
+reseller_id=
+END
+
+my $opensrs_transport_opts=<<'END';
+client_login=
+client_password=
+END
+
+tie %options, 'Tie::IxHash',
+ 'drd' => { label => 'Domain Registry Driver (DRD)',
+ type => 'select',
+ options => [ qw/BookMyName CentralNic Gandi OpenSRS OVH VNDS/ ],
+ default => 'OpenSRS' },
+ 'log_level' => { label => 'Logging',
+ type => 'select',
+ options => [ qw/debug info notice warning error critical alert emergency/ ],
+ default => 'warning' },
+ 'protocol_opts' => {
+ label => 'Protocol Options',
+ type => 'textarea',
+ default => $opensrs_protocol_opts,
+ },
+ 'transport_opts' => {
+ label => 'Transport Options',
+ type => 'textarea',
+ default => $opensrs_transport_opts,
+ },
+# 'register' => { label => 'Use for registration',
+# type => 'checkbox',
+# default => '1' },
+# 'transfer' => { label => 'Use for transfer',
+# type => 'checkbox',
+# default => '1' },
+# 'delete' => { label => 'Use for deletion',
+# type => 'checkbox',
+# default => '1' },
+# 'renew' => { label => 'Use for renewals',
+# type => 'checkbox',
+# default => '1' },
+ 'tlds' => { label => 'Use this export for these top-level domains (TLDs)',
+ type => 'select',
+ multi => 1,
+ size => scalar(@tldlist),
+ options => [ @tldlist ],
+ default => 'com net org' },
+;
+
+my $opensrs_protocol_defaults = $opensrs_protocol_opts;
+$opensrs_protocol_defaults =~ s|\n|\\n|g;
+
+my $opensrs_transport_defaults = $opensrs_transport_opts;
+$opensrs_transport_defaults =~ s|\n|\\n|g;
+
+%info = (
+ 'svc' => 'svc_domain',
+ 'desc' => 'Domain registration via Net::DRI',
+ 'options' => \%options,
+ 'notes' => <<"END"
+Registers and transfers domains via a Net::DRI registrar or registry.
+<a href="http://search.cpan.org/search?dist=Net-DRI">Net::DRI</a>
+must be installed. You must have an account at the selected registrar/registry.
+<BR />
+Some top-level domains have additional business rules not supported by this export. These TLDs cannot be registered or transfered with this export.
+<BR><BR>Use these buttons for some useful presets:
+<UL>
+ <LI>
+ <INPUT TYPE="button" VALUE="OpenSRS Live System (rr-n1-tor.opensrs.net)" onClick='
+ document.dummy.machine.value = "rr-n1-tor.opensrs.net";
+ this.form.machine.value = "rr-n1-tor.opensrs.net";
+ '>
+ <LI>
+ <INPUT TYPE="button" VALUE="OpenSRS Test System (horizon.opensrs.net)" onClick='
+ document.dummy.machine.value = "horizon.opensrs.net";
+ this.form.machine.value = "horizon.opensrs.net";
+ '>
+ <LI>
+ <INPUT TYPE="button" VALUE="OpenSRS protocol/transport options" onClick='
+ this.form.protocol_opts.value = "$opensrs_protocol_defaults";
+ this.form.transport_opts.value = "$opensrs_transport_defaults";
+ '>
+</UL>
+END
+);
+
+install_callback FS::UID sub {
+ $conf = new FS::Conf;
+};
+
+#sub rebless { shift; }
+
+# experiment: want the status of these right away, so no queueing
+
+sub _export_insert {
+ my( $self, $svc_domain ) = ( shift, shift );
+
+ return if $svc_domain->action eq 'I'; # Ignoring registration, just doing DNS
+
+ if ($svc_domain->action eq 'N') {
+ return $self->register( $svc_domain );
+ } elsif ($svc_domain->action eq 'M') {
+ return $self->transfer( $svc_domain );
+ }
+ return "Unknown domain action " . $svc_domain->action;
+}
+
+=item get_portfolio_credentials
+
+Returns, in list context, the user name and password for the domain portfolio.
+
+This is currently specified via the username and password keys in the protocol options.
+
+=cut
+
+sub get_portfolio_credentials {
+ my $self = shift;
+
+ my %opts = $self->get_protocol_options();
+ return ($opts{username}, $opts{password});
+}
+
+=item format_tel
+
+Reformats a phone number according to registry rules. Currently Freeside stores phone numbers
+in NANPA format and most registries prefer "+CCC.NPANPXNNNN"
+
+=cut
+
+sub format_tel {
+ my $tel = shift;
+
+ #if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})\s*(x\s*(\d+))?$/) {
+ if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})$/) {
+ $tel = "+1.$1$2$3"; # TBD: other country codes
+# if $tel .= "$4" if $4;
+ }
+ return $tel;
+}
+
+sub gen_contact_set {
+ my ($self, $dri, $cust_main) = @_;
+
+ my @invoicing_list = $cust_main->invoicing_list_emailonly;
+ if ( $conf->exists('emailinvoiceautoalways')
+ || $conf->exists('emailinvoiceauto') && ! @invoicing_list
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $cust_main->all_emails;
+ }
+
+ my $email = ($conf->exists('business-onlinepayment-email-override'))
+ ? $conf->config('business-onlinepayment-email-override')
+ : $invoicing_list[0];
+
+ my $cs=$dri->local_object('contactset');
+ my $co=$dri->local_object('contact');
+
+ my ($user, $pass) = $self->get_portfolio_credentials();
+
+ $co->srid($user); # Portfolio user name for OpenSRS?
+ $co->auth($pass); # Portfolio password for OpenSRS?
+
+ $co->firstname($cust_main->first);
+ $co->name($cust_main->last);
+ $co->org($cust_main->company || '-');
+ $co->street([$cust_main->address1, $cust_main->address2]);
+ $co->city($cust_main->city);
+ $co->sp($cust_main->state);
+ $co->pc($cust_main->zip);
+ $co->cc($cust_main->country);
+ $co->voice(format_tel($cust_main->daytime()));
+ $co->email($email);
+
+ $cs->set($co, 'registrant');
+ $cs->set($co, 'admin');
+ $cs->set($co, 'billing');
+
+ return $cs;
+}
+
+=item validate_contact_set
+
+Attempts to validate contact data for the domain based on OpenSRS rules.
+
+Returns undef if the contact data is acceptable, an error message if the contact
+data lacks one or more required fields.
+
+=cut
+
+sub validate_contact_set {
+ my $c = shift;
+
+ my %fields = (
+ firstname => "first name",
+ name => "last name",
+ street => "street address",
+ city => "city",
+ sp => "state",
+ pc => "ZIP/postal code",
+ cc => "country",
+ email => "email address",
+ voice => "phone number",
+ );
+ my @err = ();
+ foreach my $which (qw/registrant admin billing/) {
+ my $co = $c->get($which);
+ foreach (keys %fields) {
+ if (!$co->$_()) {
+ push @err, $fields{$_};
+ }
+ }
+ }
+ if (scalar(@err) > 0) {
+ return "Contact information needs: " . join(', ', @err);
+ }
+ undef;
+}
+
+#sub _export_replace {
+# my( $self, $new, $old ) = (shift, shift, shift);
+#
+# return '';
+#
+#}
+
+## Domain registration exports do nothing on delete. You're just removing the domain from Freeside, not the registry
+#sub _export_delete {
+# my( $self, $www ) = ( shift, shift );
+#
+# return '';
+#}
+
+=item split_textarea_options
+
+Split textarea contents into lines, split lines on =, and then trim the results;
+
+=cut
+
+sub split_textarea_options {
+ my ($self, $optname) = @_;
+ my %opts = map {
+ my ($key, $value) = split /=/, $_;
+ $key =~ s/^\s*//;
+ $key =~ s/\s*$//;
+ $value =~ s/^\s*//;
+ $value =~ s/\s*$//;
+ $key => $value } split /\n/, $self->option($optname);
+ %opts;
+}
+
+=item get_protocol_options
+
+Return a hash of protocol options
+
+=cut
+
+sub get_protocol_options {
+ my $self = shift;
+ my %opts = $self->split_textarea_options('protocol_opts');
+ if ($self->machine =~ /opensrs\.net/) {
+ my %topts = $self->get_transport_options;
+ $opts{reseller_id} = $topts{client_login};
+ }
+ %opts;
+}
+
+=item get_transport_options
+
+Return a hash of transport options
+
+=cut
+
+sub get_transport_options {
+ my $self = shift;
+ my %opts = $self->split_textarea_options('transport_opts');
+ $opts{remote_url} = "https://" . $self->machine . ":55443/resellers" if $self->machine =~ /opensrs\.net/;
+ %opts;
+}
+
+=item is_supported_domain
+
+Return undef if the domain name uses a TLD or SLD that is supported by this registrar.
+Otherwise return an error message explaining what's wrong.
+
+=cut
+
+sub is_supported_domain {
+ my $self = shift;
+ my $svc_domain = shift;
+
+ # Get the TLD of the new domain
+ my @bits = split /\./, $svc_domain->domain;
+
+ return "Can't register subdomains: " . $svc_domain->domain if scalar(@bits) != 2;
+
+ my $tld = pop @bits;
+
+ # See if it's one this export supports
+ my @tlds = split /\s+/, $self->option('tlds');
+ @tlds = map { s/\.//; $_ } @tlds;
+ return "Can't register top-level domain $tld, restricted to: " . $self->option('tlds') if ! grep { $_ eq $tld } @tlds;
+ return undef;
+}
+
+=item get_dri
+
+=cut
+
+sub get_dri {
+ my $self = shift;
+ my $dri;
+
+# return $self->{dri} if $self->{dri}; #!!!TBD!!! connection caching.
+
+ eval "use Net::DRI 0.95;";
+ return $@ if $@;
+
+# $dri=Net::DRI->new(...) to create the global object. Save the result,
+
+ eval {
+ #$dri = Net::DRI::TrapExceptions->new(10);
+ $dri = Net::DRI->new({logging => [ 'files', { output_directory => '%%%FREESIDE_LOG%%%' } ]}); #!!!TBD!!!
+ $dri->logging->level( $self->option('log_level') );
+ $dri->add_registry( $self->option('drd') );
+ my $protocol;
+ $protocol = 'xcp' if $self->option('drd') eq 'OpenSRS';
+
+ $dri->target( $self->option('drd') )->add_current_profile($self->option('drd') . '1',
+# 'Net::DRI::Protocol::' . $self->option('protocol_type'),
+# $self->option('protocol_type'),
+# 'xcp', #TBD!!!!
+ $protocol, # Implies transport
+# 'Net::DRI::Transport::' . $self->option('transport_type'),
+ { $self->get_transport_options() },
+# [ $self->get_protocol_options() ]
+ );
+ };
+ return $@ if $@;
+
+ $self->{dri} = $dri;
+ return $dri;
+}
+
+=item get_status
+
+Returns a reference to a hashref containing information on the domain's status. The keys
+defined depend on the status.
+
+'unregistered' means the domain is not registered.
+
+Otherwise, if the domain is in an asynchronous operation such as a transfer, returns the state
+of that operation.
+
+Otherwise returns a value indicating if the domain can be managed through our reseller account.
+
+=cut
+
+sub get_status {
+ my ( $self, $svc_domain ) = @_;
+ my $rc;
+ my $rslt = {};
+
+ my $dri = $self->get_dri;
+
+ if (UNIVERSAL::isa($dri, 'Net::DRI::Exception')) {
+ $rslt->{'message'} = $dri->as_string;
+ return $rslt;
+ }
+ eval {
+ $rc = $dri->domain_check( $svc_domain->domain );
+ if (!$rc->is_success()) {
+ # Problem accessing the registry/registrar
+ $rslt->{'message'} = $rc->message;
+ } elsif (!$dri->get_info('exist')) {
+ # Domain is not registered
+ $rslt->{'unregistered'} = 1;
+ } else {
+ $rc = $dri->domain_transfer_query( $svc_domain->domain );
+ if ($rc->is_success() && $dri->get_info('status')) {
+ # Transfer in progress
+ $rslt->{status} = $dri->get_info('status');
+ $rslt->{contact_email} = $dri->get_info('request_address');
+ $rslt->{last_update_time} = $dri->get_info('unixtime');
+ } elsif ($dri->get_info('reason')) {
+ $rslt->{'reason'} = $dri->get_info('reason');
+ # Domain is not being transferred...
+ $rc = $dri->domain_info( $svc_domain->domain, { $self->get_protocol_options() } );
+ if ($rc->is_success() && $dri->get_info('exDate')) {
+ $rslt->{'expdate'} = $dri->get_info('exDate');
+ }
+ } else {
+ $rslt->{status} = 'Unknown';
+ }
+ }
+ };
+# rslt->{'message'} = $@->as_string if $@;
+ if ($@) {
+ $rslt->{'message'} = (UNIVERSAL::isa($@, 'Net::DRI::Exception')) ? $@->as_string : $@->message;
+ }
+
+ return $rslt; # Success
+}
+
+=item register
+
+Attempts to register the domain through the reseller account associated with this export.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub register {
+ my ( $self, $svc_domain, $years ) = @_;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $dri = $self->get_dri;
+ return $dri->as_string if (UNIVERSAL::isa($dri, 'Net::DRI::Exception'));
+
+ eval { # All $dri methods can throw an exception.
+
+# Call methods
+ my $cust_main = $svc_domain->cust_svc->cust_pkg->cust_main;
+
+ my $cs = $self->gen_contact_set($dri, $cust_main);
+
+ $err = validate_contact_set($cs);
+ return $err if $err;
+
+# !!!TBD!!! add custom name servers when supported; add ns => $ns to hash passed to domain_create
+
+ $res = $dri->domain_create($svc_domain->domain, { $self->get_protocol_options(), pure_create => 1, contact => $cs, duration => DateTime::Duration->new(years => $years) });
+ $err = $res->is_success ? '' : $res->message;
+ };
+ if ($@) {
+ $err = (UNIVERSAL::isa($@, 'Net::DRI::Exception')) ? $@->msg : $@->message;
+ }
+
+ return $err;
+}
+
+=item transfer
+
+Attempts to transfer the domain into the reseller account associated with this export.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub transfer {
+ my ( $self, $svc_domain ) = @_;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+# $dri=Net::DRI->new(...) to create the global object. Save the result,
+ my $dri = $self->get_dri;
+ return $dri->as_string if (UNIVERSAL::isa($dri, 'Net::DRI::Exception'));
+
+ eval { # All $dri methods can throw an exception
+
+# Call methods
+ my $cust_main = $svc_domain->cust_svc->cust_pkg->cust_main;
+
+ my $cs = $self->gen_contact_set($dri, $cust_main);
+
+ $err = validate_contact_set($cs);
+ return $err if $err;
+
+# !!!TBD!!! add custom name servers when supported; add ns => $ns to hash passed to domain_transfer_start
+
+ $res = $dri->domain_transfer_start($svc_domain->domain, { $self->get_protocol_options(), contact => $cs });
+ $err = $res->is_success ? '' : $res->message;
+ };
+ if ($@) {
+ $err = (UNIVERSAL::isa($@, 'Net::DRI::Exception')) ? $@->msg : $@->message;
+ }
+
+ return $err;
+}
+
+=item renew
+
+Attempts to renew the domain for the specified number of years.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub renew {
+ my ( $self, $svc_domain, $years ) = @_;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $dri = $self->get_dri;
+ return $dri->as_string if (UNIVERSAL::isa($dri, 'Net::DRI::Exception'));
+
+ eval { # All $dri methods can throw an exception
+ my $expdate;
+ my $res = $dri->domain_info( $svc_domain->domain, { $self->get_protocol_options() } );
+ if ($res->is_success() && $dri->get_info('exDate')) {
+ $expdate = $dri->get_info('exDate');
+
+# return "Domain renewal not enabled" if !$self->option('renew');
+ $res = $dri->domain_renew( $svc_domain->domain, { $self->get_protocol_options(), duration => DateTime::Duration->new(years => $years), current_expiration => $expdate });
+ }
+ $err = $res->is_success ? '' : $res->message;
+ };
+ if ($@) {
+ $err = (UNIVERSAL::isa($@, 'Net::DRI::Exception')) ? $@->msg : $@->message;
+ }
+
+ return $err;
+}
+
+=item revoke
+
+Attempts to revoke the domain registration. Only succeeds if invoked during the DRI
+grace period immediately after registration.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub revoke {
+ my ( $self, $svc_domain ) = @_;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $dri = $self->get_dri;
+ return $dri->as_string if (UNIVERSAL::isa($dri, 'Net::DRI::Exception'));
+
+ eval { # All $dri methods can throw an exception
+
+# return "Domain registration revocation not enabled" if !$self->option('revoke');
+ my $res = $dri->domain_delete( $svc_domain->domain, { $self->get_protocol_options(), domain => $svc_domain->domain, pure_delete => 1 });
+ $err = $res->is_success ? '' : $res->message;
+ };
+ if ($@) {
+ $err = (UNIVERSAL::isa($@, 'Net::DRI::Exception')) ? $@->msg : $@->message;
+ }
+
+ return $err;
+}
+
+=item registrar
+
+Should return a full-blown object representing the Net::DRI DRD, but current just returns a hashref
+containing the registrar name.
+
+=cut
+
+sub registrar {
+ my $self = shift;
+ return {
+ name => $self->option('drd'),
+ };
+}
+
+=head1 SEE ALSO
+
+L<FS::part_export_option>, L<FS::export_svc>, L<FS::svc_domain>,
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_export/domreg_opensrs.pm b/FS/FS/part_export/domreg_opensrs.pm
new file mode 100644
index 0000000..1799ed0
--- /dev/null
+++ b/FS/FS/part_export/domreg_opensrs.pm
@@ -0,0 +1,512 @@
+package FS::part_export::domreg_opensrs;
+
+use vars qw(@ISA %info %options $conf);
+use Tie::IxHash;
+use FS::Record qw(qsearchs qsearch);
+use FS::Conf;
+use FS::part_export::null;
+use FS::svc_domain;
+use FS::part_pkg;
+
+=head1 NAME
+
+FS::part_export::domreg_opensrs - Register or transfer domains with Tucows OpenSRS
+
+=head1 DESCRIPTION
+
+This module handles registering and transferring domains using a registration service provider (RSP) account
+at Tucows OpenSRS, an ICANN-approved domain registrar.
+
+As a part_export, this module can be designated for use with svc_domain services. When the svc_domain object
+is inserted into the Freeside database, registration or transferring of the domain may be initiated, depending
+on the setting of the svc_domain's action field.
+
+=over 4
+
+=item N - Register the domain
+
+=item M - Transfer the domain
+
+=item I - Ignore the domain for registration purposes
+
+=back
+
+This export uses Net::OpenSRS. Registration and transfer attempts will fail unless Net::OpenSRS is installed
+and LWP::UserAgent is able to make HTTPS posts. You can turn on debugging messages and use the OpenSRS test
+gateway when setting up this export.
+
+=cut
+
+@ISA = qw(FS::part_export::null);
+
+my @tldlist = qw/com net org biz info name mobi at be ca cc ch cn de dk es eu fr it mx nl tv uk us/;
+
+tie %options, 'Tie::IxHash',
+ 'username' => { label => 'Reseller user name at OpenSRS',
+ },
+ 'privatekey' => { label => 'Private key',
+ },
+ 'password' => { label => 'Password for management account',
+ },
+ 'masterdomain' => { label => 'Master domain at OpenSRS',
+ },
+ 'debug_level' => { label => 'Net::OpenSRS debug level',
+ type => 'select',
+ options => [ 0, 1, 2, 3 ],
+ default => 0 },
+# 'register' => { label => 'Use for registration',
+# type => 'checkbox',
+# default => '1' },
+# 'transfer' => { label => 'Use for transfer',
+# type => 'checkbox',
+# default => '1' },
+ 'tlds' => { label => 'Use this export for these top-level domains (TLDs)',
+ type => 'select',
+ multi => 1,
+ size => scalar(@tldlist),
+ options => [ @tldlist ],
+ default => 'com net org' },
+;
+
+%info = (
+ 'svc' => 'svc_domain',
+ 'desc' => 'Domain registration via Tucows OpenSRS',
+ 'options' => \%options,
+ 'notes' => <<'END'
+Registers and transfers domains via the <a href="http://opensrs.com/">Tucows OpenSRS</a> registrar (using <a href="http://search.cpan.org/dist/Net-OpenSRS">Net::OpenSRS</a>).
+All of the Net::OpenSRS restrictions apply:
+<UL>
+ <LI>You must have a reseller account with Tucows.
+ <LI>You must add the public IP address of the Freeside server to the 'Script API allow' list in the OpenSRS web interface.
+ <LI>You must generate an API access key in the OpenSRS web interface and enter it below.
+ <LI>All domains are managed using the same user name and password, but you can create sub-accounts for clients.
+ <LI>The user name must be the same as your OpenSRS reseller ID.
+ <LI>You must enter a master domain that all other domains are associated with. That domain must be registered through your OpenSRS account.
+</UL>
+Some top-level domains offered by OpenSRS have additional business rules not supported by this export. These TLDs cannot be registered or transfered with this export.
+<BR><BR>Use these buttons for some useful presets:
+<UL>
+ <LI>
+ <INPUT TYPE="button" VALUE="OpenSRS Live System (rr-n1-tor.opensrs.net)" onClick='
+ document.dummy.machine.value = "rr-n1-tor.opensrs.net";
+ this.form.machine.value = "rr-n1-tor.opensrs.net";
+ '>
+ <LI>
+ <INPUT TYPE="button" VALUE="OpenSRS Test System (horizon.opensrs.net)" onClick='
+ document.dummy.machine.value = "horizon.opensrs.net";
+ this.form.machine.value = "horizon.opensrs.net";
+ '>
+</UL>
+END
+);
+
+install_callback FS::UID sub {
+ $conf = new FS::Conf;
+};
+
+=head1 METHODS
+
+=over 4
+
+=item format_tel
+
+Reformats a phone number according to registry rules. Currently Freeside stores phone numbers
+in NANPA format and the registry prefers "+CCC.NPANPXNNNN"
+
+=cut
+
+sub format_tel {
+ my $tel = shift;
+
+ #if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})( x(\d+))?$/) {
+ if ($tel =~ /^(\d{3})-(\d{3})-(\d{4})$/) {
+ $tel = "+1.$1$2$3";
+# if $tel .= "$4" if $4;
+ }
+ return $tel;
+}
+
+=item gen_contact_info
+
+Generates contact data for the domain based on the customer data.
+
+Currently relies on Net::OpenSRS to format the telephone number for OpenSRS.
+
+=cut
+
+sub gen_contact_info
+{
+ my ($co)=@_;
+
+ my @invoicing_list = $co->invoicing_list_emailonly;
+ if ( $conf->exists('emailinvoiceautoalways')
+ || $conf->exists('emailinvoiceauto') && ! @invoicing_list
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $co->all_emails;
+ }
+
+ my $email = ($conf->exists('business-onlinepayment-email-override'))
+ ? $conf->config('business-onlinepayment-email-override')
+ : $invoicing_list[0];
+
+ my $c = {
+ firstname => $co->first,
+ lastname => $co->last,
+ company => $co->company,
+ address => $co->address1,
+ city => $co->city(),
+ state => $co->state(),
+ zip => $co->zip(),
+ country => uc($co->country()),
+ email => $email,
+ #phone => format_tel($co->daytime()),
+ phone => $co->daytime() || $co->night,
+ };
+ return $c;
+}
+
+=item validate_contact_info
+
+Attempts to validate contact data for the domain based on OpenSRS rules.
+
+Returns undef if the contact data is acceptable, an error message if the contact
+data lacks one or more required fields.
+
+=cut
+
+sub validate_contact_info {
+ my $c = shift;
+
+ my %fields = (
+ firstname => "first name",
+ lastname => "last name",
+ address => "street address",
+ city => "city",
+ state => "state",
+ zip => "ZIP/postal code",
+ country => "country",
+ email => "email address",
+ phone => "phone number",
+ );
+ my @err = ();
+ foreach (keys %fields) {
+ if (!defined($c->{$_}) || !$c->{$_}) {
+ push @err, $fields{$_};
+ }
+ }
+ if (scalar(@err) > 0) {
+ return "Contact information needs: " . join(', ', @err);
+ }
+ undef;
+}
+
+=item testmode
+
+Returns the Net::OpenSRS-required test mode string based on whether the export
+is configured to use the live or the test gateway.
+
+=cut
+
+sub testmode {
+ my $self = shift;
+
+ return 'live' if $self->machine eq "rr-n1-tor.opensrs.net";
+ return 'test' if $self->machine eq "horizon.opensrs.net";
+ undef;
+}
+
+=item _export_insert
+
+Attempts to "export" the domain, i.e. register or transfer it if the user selected
+that option when editing the domain.
+
+Returns an error message on failure or undef on success.
+
+May also return an error message if it cannot load the required Perl module Net::OpenSRS,
+or if the domain is not registerable, or if insufficient data is provided in the customer
+record to generate the required contact information to register or transfer the domain.
+
+=cut
+
+sub _export_insert {
+ my( $self, $svc_domain ) = ( shift, shift );
+
+ return if $svc_domain->action eq 'I'; # Ignoring registration, just doing DNS
+
+ if ($svc_domain->action eq 'N') {
+ return $self->register( $svc_domain );
+ } elsif ($svc_domain->action eq 'M') {
+ return $self->transfer( $svc_domain );
+ }
+ return "Unknown domain action " . $svc_domain->action;
+}
+
+## Domain registration exports do nothing on replace. Mainly because we haven't decided what they should do.
+#sub _export_replace {
+# my( $self, $new, $old ) = (shift, shift, shift);
+#
+# return '';
+#
+#}
+
+## Domain registration exports do nothing on delete. You're just removing the domain from Freeside, not the registry
+#sub _export_delete {
+# my( $self, $svc_domain ) = ( shift, shift );
+#
+# return '';
+#}
+
+=item is_supported_domain
+
+Return undef if the domain name uses a TLD or SLD that is supported by this registrar.
+Otherwise return an error message explaining what's wrong.
+
+=cut
+
+sub is_supported_domain {
+ my $self = shift;
+ my $svc_domain = shift;
+
+ # Get the TLD of the new domain
+ my @bits = split /\./, $svc_domain->domain;
+
+ return "Can't register subdomains: " . $svc_domain->domain if scalar(@bits) != 2;
+
+ my $tld = pop @bits;
+
+ # See if it's one this export supports
+ my @tlds = split /\s+/, $self->option('tlds');
+ @tlds = map { s/\.//; $_ } @tlds;
+ return "Can't register top-level domain $tld, restricted to: " . $self->option('tlds') if ! grep { $_ eq $tld } @tlds;
+ return undef;
+}
+
+=item get_srs
+
+=cut
+
+sub get_srs {
+ my $self = shift;
+
+ my $srs = Net::OpenSRS->new();
+
+ $srs->debug_level( $self->option('debug_level') ); # Output should be in the Apache error log
+
+ $srs->environment( $self->testmode() );
+ $srs->set_key( $self->option('privatekey') );
+
+ $srs->set_manage_auth( $self->option('username'), $self->option('password') );
+ return $srs;
+}
+
+=item get_status
+
+Returns a reference to a hashref containing information on the domain's status. The keys
+defined depend on the status.
+
+'unregistered' means the domain is not registered.
+
+Otherwise, if the domain is in an asynchronous operation such as a transfer, returns the state
+of that operation.
+
+Otherwise returns a value indicating if the domain can be managed through our reseller account.
+
+=cut
+
+sub get_status {
+ my ( $self, $svc_domain ) = @_;
+ my $rslt = {};
+
+ eval "use Net::OpenSRS;";
+ return $@ if $@;
+
+ my $srs = $self->get_srs;
+
+ if ($srs->is_available( $svc_domain->domain )) {
+ $rslt->{'unregistered'} = 1;
+ } else {
+ $rslt = $srs->check_transfer( $svc_domain->domain );
+ if (defined($rslt->{'reason'})) {
+ my $rv = $srs->make_request(
+ {
+ action => 'belongs_to_rsp',
+ object => 'domain',
+ attributes => {
+ domain => $svc_domain->domain
+ }
+ }
+ );
+ if ($rv) {
+ $self->_set_response;
+ if ( $rv->{attributes}->{'domain_expdate'} ) {
+ $rslt->{'expdate'} = $rv->{attributes}->{'domain_expdate'};
+ }
+ }
+ }
+ }
+
+ return $rslt; # Success
+}
+
+=item register
+
+Attempts to register the domain through the reseller account associated with this export.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub register {
+ my ( $self, $svc_domain, $years ) = @_;
+
+ return "Net::OpenSRS does not support period other than 1 year" if $years != 1;
+
+ eval "use Net::OpenSRS;";
+ return $@ if $@;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $cust_main = $svc_domain->cust_svc->cust_pkg->cust_main;
+
+ my $c = gen_contact_info($cust_main);
+
+ $err = validate_contact_info($c);
+ return $err if $err;
+
+ my $srs = $self->get_srs;
+
+ my $cookie = $srs->get_cookie( $self->option('masterdomain') );
+ if (!$cookie) {
+ return "Unable to get cookie at OpenSRS: " . $srs->last_response();
+ }
+
+# return "Domain registration not enabled" if !$self->option('register');
+ return $srs->last_response() if !$srs->register_domain( $svc_domain->domain, $c);
+
+ return ''; # Should only get here if register succeeded
+}
+
+=item transfer
+
+Attempts to transfer the domain into the reseller account associated with this export.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub transfer {
+ my ( $self, $svc_domain ) = @_;
+
+ eval "use Net::OpenSRS;";
+ return $@ if $@;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $cust_main = $svc_domain->cust_svc->cust_pkg->cust_main;
+
+ my $c = gen_contact_info($cust_main);
+
+ $err = validate_contact_info($c);
+ return $err if $err;
+
+ my $srs = $self->get_srs;
+
+ my $cookie = $srs->get_cookie( $self->option('masterdomain') );
+ if (!$cookie) {
+ return "Unable to get cookie at OpenSRS: " . $srs->last_response();
+ }
+
+# return "Domain transfer not enabled" if !$self->option('transfer');
+ return $srs->last_response() if !$srs->transfer_domain( $svc_domain->domain, $c);
+
+ return ''; # Should only get here if transfer succeeded
+}
+
+=item renew
+
+Attempts to renew the domain for the specified number of years.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub renew {
+ my ( $self, $svc_domain, $years ) = @_;
+
+ eval "use Net::OpenSRS;";
+ return $@ if $@;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $srs = $self->get_srs;
+
+ my $cookie = $srs->get_cookie( $self->option('masterdomain') );
+ if (!$cookie) {
+ return "Unable to get cookie at OpenSRS: " . $srs->last_response();
+ }
+
+# return "Domain renewal not enabled" if !$self->option('renew');
+ return $srs->last_response() if !$srs->renew_domain( $svc_domain->domain, $years );
+
+ return ''; # Should only get here if renewal succeeded
+}
+
+=item revoke
+
+Attempts to revoke the domain registration. Only succeeds if invoked during the OpenSRS
+grace period immediately after registration.
+
+Like most export functions, returns an error message on failure or undef on success.
+
+=cut
+
+sub revoke {
+ my ( $self, $svc_domain ) = @_;
+
+ eval "use Net::OpenSRS;";
+ return $@ if $@;
+
+ my $err = $self->is_supported_domain( $svc_domain );
+ return $err if $err;
+
+ my $srs = $self->get_srs;
+
+ my $cookie = $srs->get_cookie( $self->option('masterdomain') );
+ if (!$cookie) {
+ return "Unable to get cookie at OpenSRS: " . $srs->last_response();
+ }
+
+# return "Domain registration revocation not enabled" if !$self->option('revoke');
+ return $srs->last_response() if !$srs->revoke_domain( $svc_domain->domain);
+
+ return ''; # Should only get here if transfer succeeded
+}
+
+=item registrar
+
+Should return a full-blown object representing OpenSRS, but current just returns a hashref
+containing the registrar name.
+
+=cut
+
+sub registrar {
+ return {
+ name => 'OpenSRS',
+ };
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<Net::OpenSRS>, L<FS::part_export_option>, L<FS::export_svc>, L<FS::svc_domain>,
+L<FS::Record>, schema.html from the base documentation.
+
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_export/globalpops_voip.pm b/FS/FS/part_export/globalpops_voip.pm
index 3bd5783..67b48bb 100644
--- a/FS/FS/part_export/globalpops_voip.pm
+++ b/FS/FS/part_export/globalpops_voip.pm
@@ -32,7 +32,7 @@ sub get_dids {
my $self = shift;
my %opt = ref($_[0]) ? %{$_[0]} : @_;
- my %search = ();
+ my %getdids = ();
# 'orderby' => 'npa', #but it doesn't seem to work :/
if ( $opt{'areacode'} && $opt{'exchange'} ) { #return numbers
diff --git a/FS/FS/part_export/netsapiens.pm b/FS/FS/part_export/netsapiens.pm
new file mode 100644
index 0000000..cf4b5e3
--- /dev/null
+++ b/FS/FS/part_export/netsapiens.pm
@@ -0,0 +1,308 @@
+package FS::part_export::netsapiens;
+
+use vars qw(@ISA $me %info);
+use URI;
+use MIME::Base64;
+use Tie::IxHash;
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+$me = '[FS::part_export::netsapiens]';
+
+tie my %options, 'Tie::IxHash',
+ 'login' => { label=>'NetSapiens tac2 User API username' },
+ 'password' => { label=>'NetSapiens tac2 User API password' },
+ 'url' => { label=>'NetSapiens tac2 User URL' },
+ 'device_login' => { label=>'NetSapiens tac2 Device API username' },
+ 'device_password' => { label=>'NetSapiens tac2 Device API password' },
+ 'device_url' => { label=>'NetSapiens tac2 Device URL' },
+ 'domain' => { label=>'NetSapiens Domain' },
+ 'debug' => { label=>'Enable debugging', type=>'checkbox' },
+;
+
+%info = (
+ 'svc' => 'svc_phone',
+ 'desc' => 'Provision phone numbers to NetSapiens',
+ 'options' => \%options,
+ 'notes' => <<'END'
+Requires installation of
+<a href="http://search.cpan.org/dist/REST-Client">REST::Client</a>
+from CPAN.
+END
+);
+
+sub rebless { shift; }
+
+sub ns_command {
+ my $self = shift;
+ $self->_ns_command('', @_);
+}
+
+sub ns_device_command {
+ my $self = shift;
+ $self->_ns_command('device_', @_);
+}
+
+sub _ns_command {
+ my( $self, $prefix, $method, $command ) = splice(@_,0,4);
+
+ eval 'use REST::Client';
+ die $@ if $@;
+
+ my $ns = new REST::Client 'host'=>$self->option($prefix.'url');
+
+ my @args = ( $command );
+
+ if ( $method eq 'PUT' ) {
+ my $content = $ns->buildQuery( { @_ } );
+ $content =~ s/^\?//;
+ push @args, $content;
+ } elsif ( $method eq 'GET' ) {
+ $args[0] .= $ns->buildQuery( { @_ } );
+ }
+
+ warn "$me $method ". $self->option($prefix.'url').
+ " $command ". join(', ', @_). "\n"
+ if $self->option('debug');
+
+ my $auth = encode_base64( $self->option($prefix.'login'). ':'.
+ $self->option($prefix.'password') );
+ push @args, { 'Authorization' => "Basic $auth" };
+
+ $ns->$method( @args );
+ $ns;
+}
+
+sub ns_subscriber {
+ my($self, $svc_phone) = (shift, shift);
+
+ my $domain = $self->option('domain');
+ my $phonenum = $svc_phone->phonenum;
+
+ "/domains_config/$domain/subscriber_config/$phonenum";
+}
+
+sub ns_registrar {
+ my($self, $svc_phone) = (shift, shift);
+
+ $self->ns_subscriber($svc_phone).
+ '/registrar_config/'. $self->ns_devicename($svc_phone);
+}
+
+sub ns_devicename {
+ my( $self, $svc_phone ) = (shift, shift);
+
+ my $domain = $self->option('domain');
+ #my $countrycode = $svc_phone->countrycode;
+ my $phonenum = $svc_phone->phonenum;
+
+ #"sip:$countrycode$phonenum\@$domain";
+ "sip:$phonenum\@$domain";
+}
+
+sub ns_dialplan {
+ my($self, $svc_phone) = (shift, shift);
+
+ #my $countrycode = $svc_phone->countrycode;
+ my $phonenum = $svc_phone->phonenum;
+
+ #"/dialplans/DID+Table/dialplan_config/sip:$countrycode$phonenum\@*"
+ "/dialplans/DID+Table/dialplan_config/sip:$phonenum\@*"
+}
+
+sub ns_device {
+ my($self, $svc_phone, $phone_device ) = (shift, shift, shift);
+
+ #my $countrycode = $svc_phone->countrycode;
+ #my $phonenum = $svc_phone->phonenum;
+
+ "/phones_config/". lc($phone_device->mac_addr);
+}
+
+sub ns_create_or_update {
+ my($self, $svc_phone, $dial_policy) = (shift, shift, shift);
+
+ my $domain = $self->option('domain');
+ #my $countrycode = $svc_phone->countrycode;
+ my $phonenum = $svc_phone->phonenum;
+
+ my( $firstname, $lastname );
+ if ( $svc_phone->phone_name =~ /^\s*(\S+)\s+(\S.*\S)\s*$/ ) {
+ $firstname = $1;
+ $lastname = $2;
+ } else {
+ #deal w/unaudited netsapiens services?
+ my $cust_main = $svc_phone->cust_svc->cust_pkg->cust_main;
+ $firstname = $cust_main->get('first');
+ $lastname = $cust_main->get('last');
+ }
+
+ # Piece 1 (already done) - User creation
+
+ my $ns = $self->ns_command( 'PUT', $self->ns_subscriber($svc_phone),
+ 'subscriber_login' => $phonenum.'@'.$domain,
+ 'firstname' => $firstname,
+ 'lastname' => $lastname,
+ 'subscriber_pin' => $svc_phone->pin,
+ 'dial_plan' => 'Default', #config?
+ 'dial_policy' => $dial_policy,
+ );
+
+ if ( $ns->responseCode !~ /^2/ ) {
+ return $ns->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns->responseContent ) );
+ }
+
+ #Piece 2 - sip device creation
+
+ my $ns2 = $self->ns_command( 'PUT', $self->ns_registrar($svc_phone),
+ 'termination_match' => $self->ns_devicename($svc_phone)
+ );
+
+ if ( $ns2->responseCode !~ /^2/ ) {
+ return $ns2->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns2->responseContent ) );
+ }
+
+ #Piece 3 - DID mapping to user
+
+ my $ns3 = $self->ns_command( 'PUT', $self->ns_dialplan($svc_phone),
+ 'to_user' => $phonenum,
+ 'to_host' => $domain,
+ );
+
+ if ( $ns3->responseCode !~ /^2/ ) {
+ return $ns3->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns3->responseContent ) );
+ }
+
+ '';
+}
+
+sub ns_delete {
+ my($self, $svc_phone) = (shift, shift);
+
+ my $ns = $self->ns_command( 'DELETE', $self->ns_subscriber($svc_phone) );
+
+ #delete other things?
+
+ if ( $ns->responseCode !~ /^2/ ) {
+ return $ns->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns->responseContent ) );
+ }
+
+ '';
+
+}
+
+sub ns_parse_response {
+ my( $self, $content ) = ( shift, shift );
+
+ #try to screen-scrape something useful
+ tie my %hash, Tie::IxHash;
+ while ( $content =~ s/^.*?<p>\s*<b>(.+?)<\/b>\s*(.+?)\s*<\/p>//is ) {
+ ( $hash{$1} = $2 ) =~ s/^\s*<(\w+)>(.+?)<\/\1>/$2/is;
+ }
+
+ %hash;
+}
+
+sub _export_insert {
+ my($self, $svc_phone) = (shift, shift);
+ $self->ns_create_or_update($svc_phone, 'Permit All');
+}
+
+sub _export_replace {
+ my( $self, $new, $old ) = (shift, shift, shift);
+ return "can't change phonenum with NetSapiens (unprovision and reprovision?)"
+ if $old->phonenum ne $new->phonenum;
+ $self->_export_insert($new);
+}
+
+sub _export_delete {
+ my( $self, $svc_phone ) = (shift, shift);
+
+ $self->ns_delete($svc_phone);
+}
+
+sub _export_suspend {
+ my( $self, $svc_phone ) = (shift, shift);
+ $self->ns_create_or_update($svc_phone, 'Deny');
+}
+
+sub _export_unsuspend {
+ my( $self, $svc_phone ) = (shift, shift);
+ #$self->ns_create_or_update($svc_phone, 'Permit All');
+ $self->_export_insert($svc_phone);
+}
+
+sub export_device_insert {
+ my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
+
+ #my $domain = $self->option('domain');
+ my $countrycode = $svc_phone->countrycode;
+ my $phonenum = $svc_phone->phonenum;
+
+ my $device = $self->ns_devicename($svc_phone);
+
+ my $ns = $self->ns_device_command(
+ 'PUT', $self->ns_device($svc_phone, $phone_device),
+ 'line1_enable' => 'yes',
+ 'device1' => $self->ns_devicename($svc_phone),
+ 'line1_ext' => $phonenum,
+,
+ #'line2_enable' => 'yes',
+ #'device2' =>
+ #'line2_ext' =>
+
+ #'notes' =>
+ 'server' => 'SiPbx',
+ 'domain' => $self->option('domain'),
+
+ 'brand' => $phone_device->part_device->devicename,
+
+ );
+
+ if ( $ns->responseCode !~ /^2/ ) {
+ return $ns->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns->responseContent ) );
+ }
+
+ '';
+
+}
+
+sub export_device_delete {
+ my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
+
+ my $ns = $self->ns_device_command(
+ 'DELETE', $self->ns_device($svc_phone, $phone_device),
+ );
+
+ if ( $ns->responseCode !~ /^2/ ) {
+ return $ns->responseCode. ' '.
+ join(', ', $self->ns_parse_response( $ns->responseContent ) );
+ }
+
+ '';
+
+}
+
+
+sub export_device_replace {
+ my( $self, $svc_phone, $new_phone_device, $old_phone_device ) =
+ (shift, shift, shift, shift);
+
+ #?
+ $self->export_device_insert( $svc_phone, $new_phone_device );
+
+}
+
+sub export_links {
+ my($self, $svc_phone, $arrayref) = (shift, shift, shift);
+ #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_phone->username.
+ # qq!">!. $svc_phone->username. qq!</A>!;
+ '';
+}
+
+1;
diff --git a/FS/FS/part_export/prizm.pm b/FS/FS/part_export/prizm.pm
index 2d4d858..9705440 100644
--- a/FS/FS/part_export/prizm.pm
+++ b/FS/FS/part_export/prizm.pm
@@ -200,6 +200,9 @@ sub _export_insert {
# }
# }
+ my $performance_profile = $svc->performance_profile;
+ $performance_profile ||= $svc->cust_svc->cust_pkg->part_pkg->pkg;
+
my $element_name_length = 50;
$element_name_length = $1
if $self->option('element_name_length') =~ /^\s*(\d+)\s*$/;
@@ -211,7 +214,7 @@ sub _export_insert {
$location,
$contact,
sprintf("%032X", $svc->authkey),
- $svc->cust_svc->cust_pkg->part_pkg->pkg,
+ $performance_profile,
$svc->vlan_profile,
($self->option('ems') ? 1 : 0 ),
);
@@ -256,7 +259,7 @@ sub _export_insert {
$err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet',
[ $element ],
- $svc->cust_svc->cust_pkg->part_pkg->pkg,
+ $performance_profile,
0,
1,
);
@@ -395,9 +398,12 @@ sub _export_replace {
return $err_or_som
unless ref($err_or_som);
+ my $performance_profile = $new->performance_profile;
+ $performance_profile ||= $new->cust_svc->cust_pkg->part_pkg->pkg;
+
$err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet',
[ $element ],
- $new->cust_svc->cust_pkg->part_pkg->pkg,
+ $performance_profile,
0,
1,
);
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
index c55fa36..7baf2da 100644
--- a/FS/FS/part_export/shellcommands.pm
+++ b/FS/FS/part_export/shellcommands.pm
@@ -14,6 +14,9 @@ tie my %options, 'Tie::IxHash',
default=>'useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username'
#default=>'cp -pr /etc/skel $dir; chown -R $uid.$gid $dir'
},
+ 'useradd_no_queue' => { label=>'Run immediately',
+ type => 'checkbox',
+ },
'useradd_stdin' => { label=>'Insert command STDIN',
type =>'textarea',
default=>'',
@@ -22,6 +25,9 @@ tie my %options, 'Tie::IxHash',
default=>'userdel -r $username',
#default=>'rm -rf $dir',
},
+ 'userdel_no_queue' => { label=>'Run immediately',
+ type =>'checkbox',
+ },
'userdel_stdin' => { label=>'Delete command STDIN',
type =>'textarea',
default=>'',
@@ -35,6 +41,9 @@ tie my %options, 'Tie::IxHash',
# 'rm -rf $old_dir'.
#')'
},
+ 'usermod_no_queue' => { label=>'Run immediately',
+ type =>'checkbox',
+ },
'usermod_stdin' => { label=>'Modify command STDIN',
type =>'textarea',
default=>'',
@@ -48,12 +57,18 @@ tie my %options, 'Tie::IxHash',
'suspend' => { label=>'Suspension command',
default=>'usermod -L $username',
},
+ 'suspend_no_queue' => { label=>'Run immediately',
+ type =>'checkbox',
+ },
'suspend_stdin' => { label=>'Suspension command STDIN',
default=>'',
},
'unsuspend' => { label=>'Unsuspension command',
default=>'usermod -U $username',
},
+ 'unsuspend_no_queue' => { label=>'Run immediately',
+ type =>'checkbox',
+ },
'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
default=>'',
},
@@ -65,6 +80,9 @@ tie my %options, 'Tie::IxHash',
'Radius group mapping to reason (via template user)',
type => 'textarea',
},
+# 'no_queue' => { label => 'Run command immediately',
+# type => 'checkbox',
+# },
;
%info = (
@@ -172,6 +190,8 @@ old_ for replace operations):
<LI><code>$reasontext (when suspending)</code>
<LI><code>$reasontypenum (when suspending)</code>
<LI><code>$reasontypetext (when suspending)</code>
+ <LI><code>$pkgnum</code>
+ <LI><code>$custnum</code>
<LI>All other fields in <a href="../docs/schema.html#svc_acct">svc_acct</a> are also available.
</UL>
END
@@ -296,15 +316,27 @@ sub _export_command {
$finger = shell_quote $finger;
$crypt_password = shell_quote $crypt_password;
$ldap_password = shell_quote $ldap_password;
+ $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : '';
+ $custnum = $cust_pkg ? $cust_pkg->custnum : '';
my $command_string = eval(qq("$command"));
-
- $self->shellcommands_queue( $svc_acct->svcnum,
- user => $self->option('user')||'root',
- host => $self->machine,
- command => $command_string,
- stdin_string => $stdin_string,
+ my @ssh_cmd_args = (
+ user => $self->option('user') || 'root',
+ host => $self->machine,
+ command => $command_string,
+ stdin_string => $stdin_string,
);
+
+ if($self->option($action . '_no_queue')) {
+ # discard return value just like freeside-queued.
+ eval { ssh_cmd(@ssh_cmd_args) };
+ $error = $@;
+ return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')'
+ if $error;
+ }
+ else {
+ $self->shellcommands_queue( $svc_acct->svcnum, @ssh_cmd_args );
+ }
}
sub _export_replace {
@@ -317,6 +349,8 @@ sub _export_replace {
${"old_$_"} = $old->getfield($_) foreach $old->fields;
${"new_$_"} = $new->getfield($_) foreach $new->fields;
}
+ my $old_cust_pkg = $old->cust_svc->cust_pkg;
+ my $new_cust_pkg = $new->cust_svc->cust_pkg;
$new_finger =~ /^(.*)\s+(\S+)$/ or $new_finger =~ /^((.*))$/;
($new_first, $new_last ) = ( $1, $2 );
$quoted_new__password = shell_quote $new__password; #old, wrong?
@@ -364,15 +398,30 @@ sub _export_replace {
$new_finger = shell_quote $new_finger;
$new_crypt_password = shell_quote $new_crypt_password;
$new_ldap_password = shell_quote $new_ldap_password;
+ $old_pkgnum = $old_cust_pkg ? $old_cust_pkg->pkgnum : '';
+ $old_custnum = $old_cust_pkg ? $old_cust_pkg->custnum : '';
+ $new_pkgnum = $new_cust_pkg ? $new_cust_pkg->pkgnum : '';
+ $new_custnum = $new_cust_pkg ? $new_cust_pkg->custnum : '';
my $command_string = eval(qq("$command"));
- $self->shellcommands_queue( $new->svcnum,
- user => $self->option('user')||'root',
- host => $self->machine,
- command => $command_string,
- stdin_string => $stdin_string,
+ my @ssh_cmd_args = (
+ user => $self->option('user') || 'root',
+ host => $self->machine,
+ command => $command_string,
+ stdin_string => $stdin_string,
);
+
+ if($self->option('usermod_no_queue')) {
+ # discard return value just like freeside-queued.
+ eval { ssh_cmd(@ssh_cmd_args) };
+ $error = $@;
+ return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')'
+ if $error;
+ }
+ else {
+ $self->shellcommands_queue( $new->svcnum, @ssh_cmd_args );
+ }
}
#a good idea to queue anything that could fail or take any time
diff --git a/FS/FS/part_export/shellcommands_withdomain.pm b/FS/FS/part_export/shellcommands_withdomain.pm
index 7c5d904..c209002 100644
--- a/FS/FS/part_export/shellcommands_withdomain.pm
+++ b/FS/FS/part_export/shellcommands_withdomain.pm
@@ -15,6 +15,9 @@ tie my %options, 'Tie::IxHash',
type =>'textarea',
#default=>"$_password\n$_password\n",
},
+ 'useradd_no_queue' => { label => 'Run immediately',
+ type => 'checkbox',
+ },
'userdel' => { label=>'Delete command',
#default=>'',
},
@@ -22,6 +25,9 @@ tie my %options, 'Tie::IxHash',
type =>'textarea',
#default=>'',
},
+ 'userdel_no_queue' => { label => 'Run immediately',
+ type => 'checkbox',
+ },
'usermod' => { label=>'Modify command',
default=>'',
},
@@ -29,6 +35,9 @@ tie my %options, 'Tie::IxHash',
type =>'textarea',
#default=>"$_password\n$_password\n",
},
+ 'usermod_no_queue' => { label => 'Run immediately',
+ type => 'checkbox',
+ },
'usermod_pwonly' => { label=>'Disallow username, domain, uid, dir and RADIUS group changes',
type =>'checkbox',
},
@@ -41,12 +50,18 @@ tie my %options, 'Tie::IxHash',
'suspend_stdin' => { label=>'Suspension command STDIN',
default=>'',
},
+ 'suspend_no_queue' => { label => 'Run immediately',
+ type => 'checkbox',
+ },
'unsuspend' => { label=>'Unsuspension command',
default=>'',
},
'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
default=>'',
},
+ 'unsuspend_no_queue' => { label => 'Run immediately',
+ type => 'checkbox',
+ },
'crypt' => { label => 'Default password encryption',
type=>'select', options=>[qw(crypt md5)],
default => 'crypt',
@@ -84,6 +99,17 @@ the same username with different domains. You will need to
this.form.usermod_stdin.value = "";
this.form.usermod_pwonly.checked = true;
'>
+ <LI><INPUT TYPE="button" VALUE="MagicMail" onClick='
+ this.form.useradd.value = "/usr/bin/mm_create_email_service -e $svcnum -d $domain -u $username -p $quoted_password -f $first -l $last -m $svcnum -g EMAIL";
+ this.form.useradd_stdin.value = "";
+ this.form.useradd_no_queue.checked = 1;
+ this.form.userdel.value = "/usr/bin/mm_delete_user -e ${username}\\\@${domain}";
+ this.form.userdel_stdin.value = "";
+ this.form.suspend.value = "/usr/bin/mm_suspend_user -e ${username}\\\@${domain}";
+ this.form.suspend_stdin.value = "";
+ this.form.unsuspend.value = "/usr/bin/mm_activate_user -e ${username}\\\@${domain}";
+ this.form.unsuspend_stdin.value = "";
+ '>
</UL>
The following variables are available for interpolation (prefixed with
diff --git a/FS/FS/part_export/www_plesk.pm b/FS/FS/part_export/www_plesk.pm
index 82d5557..ccf9b3e 100644
--- a/FS/FS/part_export/www_plesk.pm
+++ b/FS/FS/part_export/www_plesk.pm
@@ -26,7 +26,7 @@ Real-time export to
<a href="http://www.swsoft.com/">Plesk</a> managed server.
Requires installation of
<a href="http://search.cpan.org/dist/Net-Plesk">Net::Plesk</a>
-from CPAN.
+from CPAN and proper <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration:www_plesk.pm">configuration</a>.
END
);
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index ef24b53..287453f 100644
--- a/FS/FS/part_pkg.pm
+++ b/FS/FS/part_pkg.pm
@@ -1,7 +1,7 @@
package FS::part_pkg;
use strict;
-use vars qw( @ISA %plans $DEBUG $setup_hack );
+use vars qw( @ISA %plans $DEBUG $setup_hack $skip_pkg_svc_hack );
use Carp qw(carp cluck confess);
use Scalar::Util qw( blessed );
use Time::Local qw( timelocal_nocheck );
@@ -23,6 +23,7 @@ use FS::part_pkg_link;
@ISA = qw( FS::m2m_Common FS::option_Common );
$DEBUG = 0;
$setup_hack = 0;
+$skip_pkg_svc_hack = 0;
=head1 NAME
@@ -85,6 +86,12 @@ inherits from FS::Record. The following fields are currently supported:
=item disabled - Disabled flag, empty or `Y'
+=item custom - Custom flag, empty or `Y'
+
+=item setup_cost - for cost tracking
+
+=item recur_cost - for cost tracking
+
=item pay_weight - Weight (relative to credit_weight and other package definitions) that controls payment application to specific line items.
=item credit_weight - Weight (relative to other package definitions) that controls credit application to specific line items.
@@ -109,9 +116,8 @@ sub table { 'part_pkg'; }
=item clone
An alternate constructor. Creates a new package definition by duplicating
-an existing definition. A new pkgpart is assigned and `(CUSTOM) ' is prepended
-to the comment field. To add the package definition to the database, see
-L<"insert">.
+an existing definition. A new pkgpart is assigned and the custom flag is
+set to Y. To add the package definition to the database, see L<"insert">.
=cut
@@ -120,8 +126,7 @@ sub clone {
my $class = ref($self);
my %hash = $self->hash;
$hash{'pkgpart'} = '';
- $hash{'comment'} = "(CUSTOM) ". $hash{'comment'}
- unless $hash{'comment'} =~ /^\(CUSTOM\) /;
+ $hash{'custom'} = 'Y';
#new FS::part_pkg ( \%hash ); # ?
new $class ( \%hash ); # ?
}
@@ -213,26 +218,30 @@ sub insert {
}
}
- warn " inserting pkg_svc records" if $DEBUG;
- my $pkg_svc = $options{'pkg_svc'} || {};
- foreach my $part_svc ( qsearch('part_svc', {} ) ) {
- my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
- my $primary_svc =
- ( $options{'primary_svc'} && $options{'primary_svc'}==$part_svc->svcpart )
- ? 'Y'
- : '';
-
- my $pkg_svc = new FS::pkg_svc( {
- 'pkgpart' => $self->pkgpart,
- 'svcpart' => $part_svc->svcpart,
- 'quantity' => $quantity,
- 'primary_svc' => $primary_svc,
- } );
- my $error = $pkg_svc->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
+ unless ( $skip_pkg_svc_hack ) {
+
+ warn " inserting pkg_svc records" if $DEBUG;
+ my $pkg_svc = $options{'pkg_svc'} || {};
+ foreach my $part_svc ( qsearch('part_svc', {} ) ) {
+ my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
+ my $primary_svc =
+ ( $options{'primary_svc'} && $options{'primary_svc'}==$part_svc->svcpart )
+ ? 'Y'
+ : '';
+
+ my $pkg_svc = new FS::pkg_svc( {
+ 'pkgpart' => $self->pkgpart,
+ 'svcpart' => $part_svc->svcpart,
+ 'quantity' => $quantity,
+ 'primary_svc' => $primary_svc,
+ } );
+ my $error = $pkg_svc->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
}
+
}
if ( $options{'cust_pkg'} ) {
@@ -365,7 +374,7 @@ sub replace {
foreach my $part_svc ( qsearch('part_svc', {} ) ) {
my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
my $primary_svc =
- ( defined($options->{'primary_svc'})
+ ( defined($options->{'primary_svc'}) && $options->{'primary_svc'}
&& $options->{'primary_svc'} == $part_svc->svcpart
)
? 'Y'
@@ -448,6 +457,11 @@ sub check {
|| $self->ut_enum('recurtax', [ '', 'Y' ] )
|| $self->ut_textn('taxclass')
|| $self->ut_enum('disabled', [ '', 'Y' ] )
+ || $self->ut_enum('custom', [ '', 'Y' ] )
+ #|| $self->ut_moneyn('setup_cost')
+ #|| $self->ut_moneyn('recur_cost')
+ || $self->ut_floatn('setup_cost')
+ || $self->ut_floatn('recur_cost')
|| $self->ut_floatn('pay_weight')
|| $self->ut_floatn('credit_weight')
|| $self->ut_numbern('taxproductnum')
@@ -480,20 +494,30 @@ sub check {
'';
}
-=item pkg_comment
+=item pkg_comment [ OPTION => VALUE... ]
Returns an (internal) string representing this package. Currently,
"pkgpart: pkg - comment", is returned. "pkg - comment" may be returned in the
-future, omitting pkgpart.
+future, omitting pkgpart. The comment will have '(CUSTOM) ' prepended if
+custom is Y.
+
+If the option nopkgpart is true then the "pkgpart: ' is omitted.
=cut
sub pkg_comment {
my $self = shift;
+ my %opt = @_;
#$self->pkg. ' - '. $self->comment;
#$self->pkg. ' ('. $self->comment. ')';
- $self->pkgpart. ': '. $self->pkg. ' - '. $self->comment;
+ my $pre = $opt{nopkgpart} ? '' : $self->pkgpart. ': ';
+ $pre. $self->pkg. ' - '. $self->custom_comment;
+}
+
+sub custom_comment {
+ my $self = shift;
+ ( $self->custom ? '(CUSTOM) ' : '' ). $self->comment;
}
=item pkg_class
@@ -613,25 +637,49 @@ Returns the svcpart of the primary service definition (see L<FS::part_svc>)
associated with this package definition (see L<FS::pkg_svc>). Returns
false if there not a primary service definition or exactly one service
definition with quantity 1, or if SVCDB is specified and does not match the
-svcdb of the service definition,
+svcdb of the service definition. SVCDB can be specified as a scalar table
+name, such as 'svc_acct', or as an arrayref of possible table names.
=cut
sub svcpart {
+ my $pkg_svc = shift->_primary_pkg_svc(@_);
+ $pkg_svc ? $pkg_svc->svcpart : '';
+}
+
+=item part_svc [ SVCDB ]
+
+Like the B<svcpart> method, but returns the FS::part_svc object (see
+L<FS::part_svc>).
+
+=cut
+
+sub part_svc {
+ my $pkg_svc = shift->_primary_pkg_svc(@_);
+ $pkg_svc ? $pkg_svc->part_svc : '';
+}
+
+sub _primary_pkg_svc {
my $self = shift;
- my $svcdb = scalar(@_) ? shift : '';
+
+ my $svcdb = scalar(@_) ? shift : [];
+ $svcdb = ref($svcdb) ? $svcdb : [ $svcdb ];
+ my %svcdb = map { $_=>1 } @$svcdb;
+
my @svcdb_pkg_svc =
- grep { ( $svcdb eq $_->part_svc->svcdb || !$svcdb ) } $self->pkg_svc;
+ grep { !scalar(@$svcdb) || $svcdb{ $_->part_svc->svcdb } }
+ $self->pkg_svc;
+
my @pkg_svc = grep { $_->primary_svc =~ /^Y/i } @svcdb_pkg_svc;
@pkg_svc = grep {$_->quantity == 1 } @svcdb_pkg_svc
unless @pkg_svc;
return '' if scalar(@pkg_svc) != 1;
- $pkg_svc[0]->svcpart;
+ $pkg_svc[0];
}
=item svcpart_unique_svcdb SVCDB
-Returns the svcpart of the a service definition (see L<FS::part_svc>) matching
+Returns the svcpart of a service definition (see L<FS::part_svc>) matching
SVCDB associated with this package definition (see L<FS::pkg_svc>). Returns
false if there not a primary service definition for SVCDB or there are multiple
service definitions for SVCDB.
@@ -874,10 +922,12 @@ sub svc_part_pkg_link {
sub _part_pkg_link {
my( $self, $type ) = @_;
- qsearch('part_pkg_link', { 'src_pkgpart' => $self->pkgpart,
- 'link_type' => $type,
- }
- );
+ qsearch({ table => 'part_pkg_link',
+ hashref => { 'src_pkgpart' => $self->pkgpart,
+ 'link_type' => $type,
+ },
+ order_by => "ORDER BY hidden",
+ });
}
sub self_and_bill_linked {
@@ -885,12 +935,18 @@ sub self_and_bill_linked {
}
sub _self_and_linked {
- my( $self, $type ) = @_;
+ my( $self, $type, $hidden ) = @_;
+ $hidden ||= '';
+
+ my @result = ();
+ foreach ( ( $self, map { $_->dst_pkg->_self_and_linked($type, $_->hidden) }
+ $self->_part_pkg_link($type) ) )
+ {
+ $_->hidden($hidden) if $hidden;
+ push @result, $_;
+ }
- ( $self,
- map { $_->dst_pkg->_self_and_linked($type) }
- $self->_part_pkg_link($type)
- );
+ (@result);
}
=item part_pkg_taxoverride [ CLASS ]
@@ -1116,6 +1172,9 @@ sub calc_remain { 0; }
sub calc_cancel { 0; }
sub calc_units { 0; }
+#fallback for everything except bulk.pm
+sub hide_svc_detail { 0; }
+
=item format OPTION DATA
Returns data formatted according to the function 'format' described
@@ -1179,27 +1238,29 @@ sub _upgrade_data { # class method
foreach my $part_pkg (@part_pkg) {
unless ( $part_pkg->plan ) {
-
$part_pkg->plan('flat');
+ }
- if ( $part_pkg->setup =~ /^\s*([\d\.]+)\s*$/ ) {
+ if ( length($part_pkg->option('setup_fee')) == 0
+ && $part_pkg->setup =~ /^\s*([\d\.]+)\s*$/ ) {
- my $opt = new FS::part_pkg_option {
- 'pkgpart' => $part_pkg->pkgpart,
- 'optionname' => 'setup_fee',
- 'optionvalue' => $1,
- };
- my $error = $opt->insert;
- die $error if $error;
+ my $opt = new FS::part_pkg_option {
+ 'pkgpart' => $part_pkg->pkgpart,
+ 'optionname' => 'setup_fee',
+ 'optionvalue' => $1,
+ };
+ my $error = $opt->insert;
+ die $error if $error;
- $part_pkg->setup('');
- } else {
- die "Can't parse part_pkg.setup for fee; convert pkgnum ".
- $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
- }
+ #} else {
+ # die "Can't parse part_pkg.setup for fee; convert pkgnum ".
+ # $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
+ }
+ $part_pkg->setup('');
- if ( $part_pkg->recur =~ /^\s*([\d\.]+)\s*$/ ) {
+ if ( length($part_pkg->option('recur_fee')) == 0
+ && $part_pkg->recur =~ /^\s*([\d\.]+)\s*$/ ) {
my $opt = new FS::part_pkg_option {
'pkgpart' => $part_pkg->pkgpart,
@@ -1209,19 +1270,45 @@ sub _upgrade_data { # class method
my $error = $opt->insert;
die $error if $error;
- $part_pkg->recur('');
-
- } else {
- die "Can't parse part_pkg.setup for fee; convert pkgnum ".
- $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
- }
+ #} else {
+ # die "Can't parse part_pkg.setup for fee; convert pkgnum ".
+ # $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
}
+ $part_pkg->recur('');
$part_pkg->replace; #this should take care of plandata, right?
}
+ # now upgrade to the explicit custom flag
+
+ @part_pkg = qsearch({
+ 'table' => 'part_pkg',
+ 'hashref' => { disabled => 'Y', custom => '' },
+ 'extra_sql' => "AND comment LIKE '(CUSTOM) %'",
+ });
+
+ foreach my $part_pkg (@part_pkg) {
+ my $new = new FS::part_pkg { $part_pkg->hash };
+ $new->custom('Y');
+ my $comment = $part_pkg->comment;
+ $comment =~ s/^\(CUSTOM\) //;
+ $comment = '(none)' unless $comment =~ /\S/;
+ $new->comment($comment);
+
+ my $pkg_svc = { map { $_->svcpart => $_->quantity } $part_pkg->pkg_svc };
+ my $primary = $part_pkg->svcpart;
+ my $options = { $part_pkg->options };
+
+ my $error = $new->replace( $part_pkg,
+ 'pkg_svc' => $pkg_svc,
+ 'primary_svc' => $primary,
+ 'options' => $options,
+ );
+ die $error if $error;
+ }
+
}
=item curuser_pkgs_sql
@@ -1233,9 +1320,31 @@ L<FS::type_pkgs>).
=cut
sub curuser_pkgs_sql {
- #my($class) = shift;
+ my $class = shift;
+
+ $class->_pkgs_sql( $FS::CurrentUser::CurrentUser->agentnums );
+
+}
+
+=item agent_pkgs_sql AGENT | AGENTNUM, ...
- my $agentnums = join(',', $FS::CurrentUser::CurrentUser->agentnums);
+Returns an SQL fragment for searching for packages the provided agent or agents
+can use, either via part_pkg.agentnum directly, or via agent type (see
+L<FS::type_pkgs>).
+
+=cut
+
+sub agent_pkgs_sql {
+ my $class = shift; #i'm a class method, not a sub (the question is... why??)
+ my @agentnums = map { ref($_) ? $_->agentnum : $_ } @_;
+
+ $class->_pkgs_sql(@agentnums); #is this why
+
+}
+
+sub _pkgs_sql {
+ my( $class, @agentnums ) = @_;
+ my $agentnums = join(',', @agentnums);
"
(
@@ -1322,6 +1431,8 @@ plandata should go
part_pkg_taxrate is Pg specific
+replace should be smarter about managing the related tables (options, pkg_svc)
+
=head1 SEE ALSO
L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.
diff --git a/FS/FS/part_pkg/agent.pm b/FS/FS/part_pkg/agent.pm
new file mode 100644
index 0000000..d41978c
--- /dev/null
+++ b/FS/FS/part_pkg/agent.pm
@@ -0,0 +1,175 @@
+package FS::part_pkg::agent;
+
+use strict;
+use vars qw(@ISA $DEBUG $me %info);
+use Date::Format;
+use FS::Record qw( qsearch );
+use FS::agent;
+use FS::cust_main;
+
+#use FS::part_pkg::recur_Common;;
+#@ISA = qw(FS::part_pkg::recur_Common);
+use FS::part_pkg::prorate;
+@ISA = qw(FS::part_pkg::prorate);
+
+$DEBUG = 0;
+
+$me = '[FS::part_pkg::agent]';
+
+%info = (
+ 'name' => 'Wholesale bulk billing, for master customers of an agent.',
+ 'shortname' => 'Wholesale bulk billing for agent.',
+
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Base recurring fee for this package',
+ 'default' => 0,
+ },
+
+
+ #'recur_method' => { 'name' => 'Recurring fee method',
+ # #'type' => 'radio',
+ # #'options' => \%recur_method,
+ # 'type' => 'select',
+ # 'select_options' => \%recur_Common::recur_method,
+ # },
+ 'cutoff_day' => { 'name' => 'Billing Day (1 - 28)',
+ 'default' => '1',
+ },
+
+ 'no_pkg_prorate' => { 'name' => 'Disable prorating bulk packages (charge full price for packages active only a portion of the month)',
+ 'type' => 'checkbox',
+ },
+
+ },
+
+ #'fieldorder' => [qw( setup_fee recur_fee recur_method cutoff_day ) ],
+ 'fieldorder' => [qw( setup_fee recur_fee cutoff_day no_pkg_prorate ) ],
+
+ 'weight' => 51,
+
+);
+
+#some false laziness-ish w/bulk.pm... not a lot
+sub calc_recur {
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_;
+
+ my $last_bill = $cust_pkg->last_bill;
+
+ return sprintf("%.2f", $self->SUPER::calc_recur(@_) )
+ unless $$sdate > $last_bill;
+
+ my $conf = new FS::Conf;
+ my $money_char = $conf->config('money_char') || '$';
+
+ my $total_agent_charge = 0;
+
+ warn "$me billing for agent packages from ". time2str('%x', $last_bill).
+ " to ". time2str('%x', $$sdate). "\n"
+ if $DEBUG;
+
+ my $prorate_ratio = ( $$sdate - $last_bill )
+ / ( $self->add_freq($last_bill) - $last_bill );
+
+ #almost always just one,
+ #unless you have multiple agents with same master customer0
+ my @agents = qsearch('agent', { 'agent_custnum' => $cust_pkg->custnum } );
+
+ foreach my $agent (@agents) {
+
+ warn "$me billing for agent ". $agent->agent. "\n"
+ if $DEBUG;
+
+ #not the most efficient to load them all into memory,
+ #but good enough for our current needs
+ my @cust_main = qsearch('cust_main', { 'agentnum' => $agent->agentnum } );
+
+ foreach my $cust_main (@cust_main) {
+
+ warn "$me billing agent charges for ". $cust_main->name_short. "\n"
+ if $DEBUG;
+
+ #make sure setup dates are filled in
+ my $error = $cust_main->bill; #options don't propogate from freeside-daily
+ die "Error pre-billing agent customer: $error" if $error;
+
+ my @cust_pkg = grep { my $setup = $_->get('setup');
+ my $cancel = $_->get('cancel');
+
+ $setup < $$sdate # END
+ && ( ! $cancel || $cancel > $last_bill ) #START
+ }
+ $cust_main->all_pkgs;
+
+ foreach my $cust_pkg ( @cust_pkg ) {
+
+ warn "$me billing agent charges for pkgnum ". $cust_pkg->pkgnum. "\n"
+ if $DEBUG;
+
+ my $pkg_details = $cust_main->name_short. ': '; #name?
+ # + something to identify package... primary service probably
+
+ my $pkg_charge = 0;
+
+ my $part_pkg = $cust_pkg->part_pkg;
+ #option to not fallback? via options above
+ my $pkg_setup_fee =
+ $part_pkg->setup_cost || $part_pkg->option('setup_fee');
+ my $pkg_base_recur =
+ $part_pkg->recur_cost || $part_pkg->base_recur_permonth($cust_pkg);
+
+ my $pkg_start = $cust_pkg->get('setup');
+ if ( $pkg_start < $last_bill ) {
+ $pkg_start = $last_bill;
+ } elsif ( $pkg_setup_fee ) {
+ $pkg_charge += $pkg_setup_fee;
+ $pkg_details .= $money_char. sprintf('%.2f setup, ', $pkg_setup_fee );
+ }
+
+ my $pkg_end = $cust_pkg->get('cancel');
+ $pkg_end = ( !$pkg_end || $pkg_end > $$sdate ) ? $$sdate : $pkg_end;
+
+
+ my $pkg_recur_charge = $prorate_ratio * $pkg_base_recur;
+ $pkg_recur_charge *= ( $pkg_end - $pkg_start )
+ / ( $$sdate - $last_bill )
+ unless $self->option('no_pkg_prorate');
+
+ my $recur_charge += $pkg_recur_charge;
+
+ $pkg_details .= $money_char. sprintf('%.2f', $recur_charge ).
+ ' ('. time2str('%x', $pkg_start).
+ ' - '. time2str('%x', $pkg_end ). ')'
+ if $recur_charge;
+
+ $pkg_charge += $recur_charge;
+
+ push @$details, $pkg_details
+ if $pkg_charge;
+ $total_agent_charge += $pkg_charge;
+
+ } #foreach $cust_pkg
+
+ } #foreach $cust_main
+
+ } #foreach $agent;
+
+ my $charges = $total_agent_charge + $self->SUPER::calc_recur(@_); #prorate
+
+ sprintf('%.2f', $charges );
+
+}
+
+sub hide_svc_detail {
+ 1;
+}
+
+sub is_free {
+ 0;
+}
+
+1;
+
diff --git a/FS/FS/part_pkg/base_rate.pm b/FS/FS/part_pkg/base_rate.pm
index 64636d9..440e985 100644
--- a/FS/FS/part_pkg/base_rate.pm
+++ b/FS/FS/part_pkg/base_rate.pm
@@ -63,7 +63,7 @@ sub calc_remain {
my $time = time; #should be able to pass this in for credit calculation
my $next_bill = $cust_pkg->getfield('bill') || 0;
my $last_bill = $cust_pkg->last_bill || 0;
- return 0 if ! $self->base_recur
+ return 0 if ! $self->base_recur($cust_pkg)
|| ! $self->option('unused_credit', 1)
|| ! $last_bill
|| ! $next_bill
@@ -81,7 +81,7 @@ sub calc_remain {
my $freq_sec = $1 * $sec{$2||'m'};
return 0 unless $freq_sec;
- sprintf("%.2f", $self->base_recur * ( $next_bill - $time ) / $freq_sec );
+ sprintf("%.2f", $self->base_recur($cust_pkg) * ( $next_bill - $time ) / $freq_sec );
}
diff --git a/FS/FS/part_pkg/bulk.pm b/FS/FS/part_pkg/bulk.pm
index 63d344d..1b52d9f 100644
--- a/FS/FS/part_pkg/bulk.pm
+++ b/FS/FS/part_pkg/bulk.pm
@@ -7,7 +7,7 @@ use FS::part_pkg::flat;
@ISA = qw(FS::part_pkg::flat);
-$DEBUG = 0;
+$DEBUG = 1;
$me = '[FS::part_pkg::bulk]';
%info = (
@@ -35,6 +35,7 @@ $me = '[FS::part_pkg::bulk]';
'weight' => 50,
);
+#some false laziness-ish w/agent.pm... not a lot
sub calc_recur {
my($self, $cust_pkg, $sdate, $details ) = @_;
@@ -45,6 +46,9 @@ sub calc_recur {
my $last_bill = $cust_pkg->last_bill;
+ return sprintf("%.2f", $self->base_recur($cust_pkg) )
+ unless $$sdate > $last_bill;
+
my $total_svc_charge = 0;
warn "$me billing for bulk services from ". time2str('%x', $last_bill).
@@ -52,16 +56,15 @@ sub calc_recur {
if $DEBUG;
# END START
- foreach my $h_svc ( $cust_pkg->h_cust_svc( $$sdate, $last_bill ) ) {
+ foreach my $h_cust_svc ( $cust_pkg->h_cust_svc( $$sdate, $last_bill ) ) {
- my @label = $h_svc->label( $$sdate, $last_bill );
+ my @label = $h_cust_svc->label_long( $$sdate, $last_bill );
die "fatal: no historical label found, wtf?" unless scalar(@label); #?
- #my $svc_details = $label[0].': '. $label[1]. ': ';
- my $svc_details = $label[1]. ': ';
+ my $svc_details = $label[0]. ': '. $label[1]. ': ';
my $svc_charge = 0;
- my $svc_start = $h_svc->date_inserted;
+ my $svc_start = $h_cust_svc->date_inserted;
if ( $svc_start < $last_bill ) {
$svc_start = $last_bill;
} elsif ( $svc_setup_fee ) {
@@ -69,23 +72,30 @@ sub calc_recur {
$svc_details .= $money_char. sprintf('%.2f setup, ', $svc_setup_fee);
}
- my $svc_end = $h_svc->date_deleted;
+ my $svc_end = $h_cust_svc->date_deleted;
$svc_end = ( !$svc_end || $svc_end > $$sdate ) ? $$sdate : $svc_end;
- $svc_charge = $self->option('svc_recur_fee') * ( $svc_end - $svc_start )
- / ( $$sdate - $last_bill );
+ my $recur_charge =
+ $self->option('svc_recur_fee') * ( $svc_end - $svc_start )
+ / ( $$sdate - $last_bill );
- $svc_details .= $money_char. sprintf('%.2f', $svc_charge ).
+ $svc_details .= $money_char. sprintf('%.2f', $recur_charge ).
' ('. time2str('%x', $svc_start).
' - '. time2str('%x', $svc_end ). ')'
- if $self->option('svc_recur_fee');
+ if $recur_charge;
+
+ $svc_charge += $recur_charge;
push @$details, $svc_details;
$total_svc_charge += $svc_charge;
}
- sprintf("%.2f", $self->base_recur($cust_pkg) + $total_svc_charge );
+ sprintf('%.2f', $self->base_recur($cust_pkg) + $total_svc_charge );
+}
+
+sub hide_svc_detail {
+ 1;
}
sub is_free_options {
diff --git a/FS/FS/part_pkg/cdr_termination.pm b/FS/FS/part_pkg/cdr_termination.pm
new file mode 100644
index 0000000..d99903d
--- /dev/null
+++ b/FS/FS/part_pkg/cdr_termination.pm
@@ -0,0 +1,207 @@
+package FS::part_pkg::cdr_termination;
+
+use strict;
+use base qw( FS::part_pkg::recur_Common );
+use vars qw( $DEBUG %info );
+use Tie::IxHash;
+use FS::Record qw( qsearch ); #qsearchs );
+use FS::cdr;
+use FS::cdr_termination;
+
+tie my %temporalities, 'Tie::IxHash',
+ 'upcoming' => "Upcoming (future)",
+ 'preceding' => "Preceding (past)",
+;
+
+%info = (
+ 'name' => 'VoIP rating of CDR records for termination partners.',
+ 'shortname' => 'VoIP/telco CDR termination',
+ 'fields' => {
+
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Base recurring fee for this package',
+ 'default' => 0,
+ },
+
+ #'cdr_column' => { 'name' => 'Column from CDR records',
+ # 'type' => 'select',
+ # 'select_enum' => [qw(
+ # dcontext
+ # channel
+ # dstchannel
+ # lastapp
+ # lastdata
+ # accountcode
+ # userfield
+ # cdrtypenum
+ # calltypenum
+ # description
+ # carrierid
+ # upstream_rateid
+ # )],
+ # },
+
+ #false laziness w/flat.pm
+ 'recur_temporality' => { 'name' => 'Charge recurring fee for period',
+ 'type' => 'select',
+ 'select_options' => \%temporalities,
+ },
+
+ 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
+ ' of service at cancellation',
+ 'type' => 'checkbox',
+ },
+
+ 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '.
+ 'subscription',
+ 'default' => '1',
+ },
+
+ 'recur_method' => { 'name' => 'Recurring fee method',
+ #'type' => 'radio',
+ #'options' => \%recur_method,
+ 'type' => 'select',
+ 'select_options' => \%FS::part_pkg::recur_Common::recur_method,
+ },
+
+ #false laziness w/cdr_termination.pm
+ 'output_format' => { 'name' => 'CDR invoice display format',
+ 'type' => 'select',
+ 'select_options' => { FS::cdr::invoice_formats() },
+ 'default' => 'simple2', #XXX test
+ },
+
+ 'usage_section' => { 'name' => 'Section in which to place separate usage charges',
+ },
+
+ 'summarize_usage' => { 'name' => 'Include usage summary with recurring charges when usage is in separate section',
+ 'type' => 'checkbox',
+ },
+
+ },
+ #cdr_column
+ 'fieldorder' => [qw(
+ setup_fee recur_fee
+ recur_temporality unused_credit recur_method cutoff_day
+ output_format usage_section summarize_usage
+ )
+ ],
+
+ 'weight' => 48,
+
+);
+
+sub calc_setup {
+ my($self, $cust_pkg ) = @_;
+ $self->option('setup_fee');
+}
+
+sub calc_recur {
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_;
+
+ #my $last_bill = $cust_pkg->last_bill;
+ my $last_bill = $cust_pkg->get('last_bill'); #->last_bill falls back to setup
+
+ return 0
+ if $self->option('recur_temporality', 1) eq 'preceding'
+ && ( $last_bill eq '' || $last_bill == 0 );
+
+ # termination calculations
+
+ my $term_percent = $cust_pkg->cust_main->cdr_termination_percentage;
+ die "no customer termination percentage" unless $term_percent;
+
+ my $output_format = $self->option('output_format', 'Hush!') || 'simple2';
+
+ my $charges = 0;
+
+ #find an svc_external record
+ my @svc_external = map { $_->svc_x }
+ grep { $_->part_svc->svcdb eq 'svc_external' }
+ $cust_pkg->cust_svc;
+
+ die "cdr_termination package has no svc_external service"
+ unless @svc_external;
+ die "cdr_termination package has multiple svc_external services"
+ if scalar(@svc_external) > 1;
+
+ my $svc_external = $svc_external[0];
+
+ # find CDRs:
+ # - matching our customer via svc_external.id/title? (and via what field?)
+
+ #let's try carrierid for now, can always make it configurable or rewrite
+ my $cdr_column = 'carrierid';
+
+ my %hashref = ( 'freesidestatus' => 'done' );
+
+ # try matching on svc_external.id for now... (or title? if ints don't cut it)
+ $hashref{$cdr_column} = $svc_external[0]->id;
+
+ # - with no cdr_termination.status
+
+ my $termpart = 1; #or from an option
+
+ #false lazienss w/search/cdr.html (i should be a part_termination method)
+ my $where_term =
+ "( cdr.acctid = cdr_termination.acctid AND termpart = $termpart ) ";
+ #my $join_term = "LEFT JOIN cdr_termination ON ( $where_term )";
+ my $extra_sql =
+ "AND NOT EXISTS ( SELECT 1 FROM cdr_termination WHERE $where_term )";
+
+ #may need to process in batches if there's waaay too many
+ my @cdrs = qsearch({
+ 'table' => 'cdr',
+ #'addl_from' => $join_term,
+ 'hashref' => \%hashref,
+ 'extra_sql' => "$extra_sql FOR UPDATE",
+ });
+
+ foreach my $cdr (@cdrs) {
+
+ #add a cdr_termination record and the charges
+
+ # XXX config?
+ #my $term_price = sprintf('%.2f', $cdr->rated_price * $term_percent / 100 );
+ my $term_price = sprintf('%.4f', $cdr->rated_price * $term_percent / 100 );
+
+ my $cdr_termination = new FS::cdr_termination {
+ 'acctid' => $cdr->acctid,
+ 'termpart' => $termpart,
+ 'rated_price' => $term_price,
+ 'status' => 'done',
+ };
+
+ my $error = $cdr_termination->insert;
+ die $error if $error; #next if $error; #or just skip this one??? why?
+
+ $charges += $term_price;
+
+ # and add a line to the invoice
+
+ my $call_details = $cdr->downstream_csv( 'format' => $output_format,
+ 'charge' => $term_price,
+ );
+
+ my $classnum = ''; #usage class?
+
+ #option to turn off? or just use squelch_cdr for the customer probably
+ push @$details, [ 'C', $call_details, $term_price, $classnum ];
+
+ }
+
+ # eotermiation calculation
+
+ $charges += $self->calc_recur_Common(@_);
+
+ $charges;
+}
+
+sub is_free {
+ 0;
+}
+
+1;
diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm
index 3ac44c4..02ac6ae 100644
--- a/FS/FS/part_pkg/flat.pm
+++ b/FS/FS/part_pkg/flat.pm
@@ -1,7 +1,10 @@
package FS::part_pkg::flat;
use strict;
-use vars qw(@ISA %info);
+use vars qw( @ISA %info
+ %usage_fields %usage_recharge_fields
+ @usage_fieldorder @usage_recharge_fieldorder
+ );
use Tie::IxHash;
#use FS::Record qw(qsearch);
use FS::UI::bytecount;
@@ -14,30 +17,8 @@ tie my %temporalities, 'Tie::IxHash',
'preceding' => "Preceding (past)",
;
-%info = (
- 'name' => 'Flat rate (anniversary billing)',
- 'shortname' => 'Anniversary',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
-
- #false laziness w/voip_cdr.pm
- 'recur_temporality' => { 'name' => 'Charge recurring fee for period',
- 'type' => 'select',
- 'select_options' => \%temporalities,
- },
+%usage_fields = (
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'externalid' => { 'name' => 'Optional External ID',
- 'default' => '',
- },
'seconds' => { 'name' => 'Time limit for this package',
'default' => '',
'check' => sub { shift =~ /^\d*$/ },
@@ -60,6 +41,10 @@ tie my %temporalities, 'Tie::IxHash',
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
},
+);
+
+%usage_recharge_fields = (
+
'recharge_amount' => { 'name' => 'Cost of recharge for this package',
'default' => '',
'check' => sub { shift =~ /^\d*(\.\d{2})?$/ },
@@ -94,13 +79,46 @@ tie my %temporalities, 'Tie::IxHash',
'package recharge',
'type' => 'checkbox',
},
+);
+
+@usage_fieldorder = qw( seconds upbytes downbytes totalbytes );
+@usage_recharge_fieldorder = qw(
+ recharge_amount recharge_seconds recharge_upbytes
+ recharge_downbytes recharge_totalbytes
+ usage_rollover recharge_reset
+);
+
+%info = (
+ 'name' => 'Flat rate (anniversary billing)',
+ 'shortname' => 'Anniversary',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+
+ #false laziness w/voip_cdr.pm
+ 'recur_temporality' => { 'name' => 'Charge recurring fee for period',
+ 'type' => 'select',
+ 'select_options' => \%temporalities,
+ },
+
+ %usage_fields,
+ %usage_recharge_fields,
+
+ 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
+ ' of service at cancellation',
+ 'type' => 'checkbox',
+ },
+ 'externalid' => { 'name' => 'Optional External ID',
+ 'default' => '',
+ },
},
- 'fieldorder' => [qw( setup_fee recur_fee recur_temporality unused_credit
- seconds upbytes downbytes totalbytes
- recharge_amount recharge_seconds recharge_upbytes
- recharge_downbytes recharge_totalbytes
- usage_rollover recharge_reset externalid
- )
+ 'fieldorder' => [ qw( setup_fee recur_fee recur_temporality unused_credit ),
+ @usage_fieldorder, @usage_recharge_fieldorder,
+ qw( externalid ),
],
'weight' => 10,
);
@@ -126,7 +144,8 @@ sub unit_setup {
}
sub calc_recur {
- my($self, $cust_pkg) = @_;
+ my $self = shift;
+ my($cust_pkg) = @_;
#my $last_bill = $cust_pkg->last_bill;
my $last_bill = $cust_pkg->get('last_bill'); #->last_bill falls back to setup
@@ -134,7 +153,7 @@ sub calc_recur {
return 0
if $self->option('recur_temporality', 1) eq 'preceding' && $last_bill == 0;
- $self->base_recur($cust_pkg);
+ $self->base_recur(@_);
}
sub base_recur {
@@ -143,11 +162,11 @@ sub base_recur {
}
sub base_recur_permonth {
- my($self, $cust_pkg) = @_; #$cust_pkg?
+ my($self, $cust_pkg) = @_;
return 0 unless $self->freq =~ /^\d+$/ && $self->freq > 0;
- sprintf('%.2f', $self->base_recur / $self->freq );
+ sprintf('%.2f', $self->base_recur($cust_pkg) / $self->freq );
}
sub calc_remain {
@@ -165,7 +184,7 @@ sub calc_remain {
#my $last_bill = $cust_pkg->last_bill || 0;
my $last_bill = $cust_pkg->get('last_bill') || 0; #->last_bill falls back to setup
- return 0 if ! $self->base_recur
+ return 0 if ! $self->base_recur($cust_pkg)
|| ! $self->option('unused_credit', 1)
|| ! $last_bill
|| ! $next_bill
@@ -183,7 +202,7 @@ sub calc_remain {
my $freq_sec = $1 * $sec{$2||'m'};
return 0 unless $freq_sec;
- sprintf("%.2f", $self->base_recur * ( $next_bill - $time ) / $freq_sec );
+ sprintf("%.2f", $self->base_recur($cust_pkg) * ( $next_bill - $time ) / $freq_sec );
}
@@ -195,16 +214,21 @@ sub is_prepaid {
0; #no, we're postpaid
}
+sub usage_valuehash {
+ my $self = shift;
+ map { $_, $self->option($_) }
+ grep { $self->option($_, 'hush') }
+ qw(seconds upbytes downbytes totalbytes);
+}
+
sub reset_usage {
my($self, $cust_pkg, %opt) = @_;
warn " resetting usage counters" if $opt{debug} > 1;
- my %values = map { $_, $self->option($_) }
- grep { $self->option($_, 'hush') }
- qw(seconds upbytes downbytes totalbytes);
+ my %values = $self->usage_valuehash;
if ($self->option('usage_rollover', 1)) {
$cust_pkg->recharge(\%values);
}else{
- $cust_pkg->set_usage(\%values);
+ $cust_pkg->set_usage(\%values, %opt);
}
}
diff --git a/FS/FS/part_pkg/flat_delayed.pm b/FS/FS/part_pkg/flat_delayed.pm
index 4a2f1ba..33f9dd8 100644
--- a/FS/FS/part_pkg/flat_delayed.pm
+++ b/FS/FS/part_pkg/flat_delayed.pm
@@ -58,7 +58,7 @@ sub calc_remain {
return 0 if $last_bill + (86400 * $free_days) == $next_bill
&& $last_bill == $cust_pkg->setup;
- return 0 if ! $self->base_recur
+ return 0 if ! $self->base_recur($cust_pkg)
|| ! $self->option('unused_credit', 1)
|| ! $last_bill
|| ! $next_bill;
diff --git a/FS/FS/part_pkg/flat_introrate.pm b/FS/FS/part_pkg/flat_introrate.pm
index 2568afa..2d551f1 100644
--- a/FS/FS/part_pkg/flat_introrate.pm
+++ b/FS/FS/part_pkg/flat_introrate.pm
@@ -1,46 +1,38 @@
package FS::part_pkg::flat_introrate;
use strict;
-use vars qw(@ISA %info $DEBUG $DEBUG_PRE);
+use vars qw(@ISA %info $DEBUG $me);
#use FS::Record qw(qsearch qsearchs);
use FS::part_pkg::flat;
use Date::Manip qw(DateCalc UnixDate ParseDate);
@ISA = qw(FS::part_pkg::flat);
+$me = '[' . __PACKAGE__ . ']';
$DEBUG = 0;
-$DEBUG_PRE = '[' . __PACKAGE__ . ']: ';
-%info = (
- 'name' => 'Introductory price for X months, then flat rate,'.
- 'relative to setup date (anniversary billing)',
- 'shortname' => 'Anniversary, with intro price',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
+(%info) = (%FS::part_pkg::flat::info);
+$info{name} = 'Introductory price for X months, then flat rate,'.
+ 'relative to setup date (anniversary billing)';
+$info{shortname} = 'Anniversary, with intro price';
+$info{fields} = { %{$info{fields}} };
+$info{fields}{intro_fee} =
+ { 'name' => 'Introductory recurring fee for this package',
'default' => 0,
- },
- 'intro_fee' => { 'name' => 'Introductory recurring free for this package',
- 'default' => 0,
- },
- 'intro_duration' => { 'name' => 'Duration of the introductory period, ' .
- 'in number of months',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- },
- 'fieldorder' => [ 'setup_fee', 'intro_duration', 'intro_fee', 'recur_fee', 'unused_credit' ],
- 'weight' => 14,
-);
-
-sub calc_recur {
+ };
+$info{fields}{intro_duration} =
+ { 'name' => 'Duration of the introductory period, in number of months',
+ 'default' => 0,
+ };
+$info{fieldorder} = [ @{ $info{fieldorder} } ];
+splice @{$info{fieldorder}}, 1, 0, qw( intro_duration intro_fee );
+$info{weight} = 14;
+
+sub base_recur {
my($self, $cust_pkg, $time ) = @_;
+ my $now = $time ? $$time : time;
+
my ($duration) = ($self->option('intro_duration') =~ /^(\d+)$/);
unless ($duration) {
die "Invalid intro_duration: " . $self->option('intro_duration');
@@ -50,11 +42,11 @@ sub calc_recur {
my $intro_end = &DateCalc($setup, "+${duration} month");
my $recur;
- warn $DEBUG_PRE . "\$duration = ${duration}" if $DEBUG;
- warn $DEBUG_PRE . "\$intro_end = ${intro_end}" if $DEBUG;
- warn $DEBUG_PRE . "$$time < " . &UnixDate($intro_end, '%s') if $DEBUG;
+ warn "$me: \$duration = ${duration}" if $DEBUG;
+ warn "$me: \$intro_end = ${intro_end}" if $DEBUG;
+ warn "$me: $now < " . &UnixDate($intro_end, '%s') if $DEBUG;
- if ($$time < &UnixDate($intro_end, '%s')) {
+ if ($now < &UnixDate($intro_end, '%s')) {
$recur = $self->option('intro_fee');
} else {
$recur = $self->option('recur_fee');
diff --git a/FS/FS/part_pkg/prepaid.pm b/FS/FS/part_pkg/prepaid.pm
index 4499d0e..cff165a 100644
--- a/FS/FS/part_pkg/prepaid.pm
+++ b/FS/FS/part_pkg/prepaid.pm
@@ -12,6 +12,11 @@ tie %recur_action, 'Tie::IxHash',
'cancel' => 'cancel',
;
+tie my %overlimit_action, 'Tie::IxHash',
+ 'overlimit' => 'Default overlimit processing',
+ 'cancel' => 'Cancel',
+;
+
%info = (
'name' => 'Prepaid, flat rate',
#'name' => 'Prepaid (no automatic recurring)', #maybe use it here too
@@ -27,8 +32,17 @@ tie %recur_action, 'Tie::IxHash',
'type' => 'select',
'select_options' => \%recur_action,
},
+ %FS::part_pkg::flat::usage_fields,
+ 'overlimit_action' => { 'name' => 'Action to take upon reaching a usage limit.',
+ 'type' => 'select',
+ 'select_options' => \%overlimit_action,
+ },
+ #XXX if you set overlimit_action to 'cancel', should also have the ability
+ # to select a reason
},
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'recur_action', ],
+ 'fieldorder' => [ qw( setup_fee recur_fee recur_action ),
+ @FS::part_pkg::flat::usage_fieldorder, 'overlimit_action',
+ ],
'weight' => 25,
);
diff --git a/FS/FS/part_pkg/prorate_delayed.pm b/FS/FS/part_pkg/prorate_delayed.pm
index 1d22798..0073493 100644
--- a/FS/FS/part_pkg/prorate_delayed.pm
+++ b/FS/FS/part_pkg/prorate_delayed.pm
@@ -56,7 +56,7 @@ sub calc_remain {
return 0 if $last_bill + (86400 * $free_days) == $next_bill
&& $last_bill == $cust_pkg->setup;
- return 0 if ! $self->base_recur
+ return 0 if ! $self->base_recur($cust_pkg)
|| ! $self->option('unused_credit', 1)
|| ! $last_bill
|| ! $next_bill;
diff --git a/FS/FS/part_pkg/recur_Common.pm b/FS/FS/part_pkg/recur_Common.pm
new file mode 100644
index 0000000..2739cbc
--- /dev/null
+++ b/FS/FS/part_pkg/recur_Common.pm
@@ -0,0 +1,59 @@
+package FS::part_pkg::recur_Common;
+
+use strict;
+use vars qw( @ISA %info %recur_method );
+use Tie::IxHash;
+use Time::Local;
+use FS::part_pkg::prorate;
+
+@ISA = qw(FS::part_pkg::prorate);
+
+%info = ( 'disabled' => 1 ); #recur_Common not a usable price plan directly
+
+tie %recur_method, 'Tie::IxHash',
+ 'anniversary' => 'Charge the recurring fee at the frequency specified above',
+ 'prorate' => 'Charge a prorated fee the first time (selectable billing date)',
+ 'subscription' => 'Charge the full fee for the first partial period (selectable billing date)',
+;
+
+sub calc_recur_Common {
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_; #only need $sdate & $param
+
+ my $charges = 0;
+
+ if ( $param->{'increment_next_bill'} ) {
+
+ my $recur_method = $self->option('recur_method', 1) || 'anniversary';
+
+ if ( $recur_method eq 'prorate' ) {
+
+ $charges = $self->SUPER::calc_recur(@_);
+
+ } else {
+
+ $charges = $self->option('recur_fee');
+
+ if ( $recur_method eq 'subscription' ) {
+
+ my $cutoff_day = $self->option('cutoff_day', 1) || 1;
+ my ($day, $mon, $year) = ( localtime($$sdate) )[ 3..5 ];
+
+ if ( $day < $cutoff_day ) {
+ if ( $mon == 0 ) { $mon=11; $year--; }
+ else { $mon--; }
+ }
+
+ $$sdate = timelocal(0, 0, 0, $cutoff_day, $mon, $year);
+
+ }#$recur_method eq 'subscription'
+
+ }#$recur_method eq 'prorate'
+
+ }#increment_next_bill
+
+ $charges;
+
+}
+
+1;
diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm
index a691fda..eccf2c1 100644
--- a/FS/FS/part_pkg/voip_cdr.pm
+++ b/FS/FS/part_pkg/voip_cdr.pm
@@ -6,20 +6,22 @@ use Date::Format;
use Tie::IxHash;
use FS::Conf;
use FS::Record qw(qsearchs qsearch);
-use FS::part_pkg::flat;
+use FS::part_pkg::recur_Common;
use FS::cdr;
use FS::rate;
use FS::rate_prefix;
use FS::rate_detail;
+use FS::part_pkg::recur_Common;
-@ISA = qw(FS::part_pkg::flat);
+@ISA = qw(FS::part_pkg::recur_Common);
$DEBUG = 0;
tie my %rating_method, 'Tie::IxHash',
'prefix' => 'Rate calls by using destination prefix to look up a region and rate according to the internal prefix and rate tables',
- 'upstream' => 'Rate calls based on upstream data: If the call type is "1", map the upstream rate ID directly to an internal rate (rate_detail), otherwise, pass the upstream price through directly.',
+# 'upstream' => 'Rate calls based on upstream data: If the call type is "1", map the upstream rate ID directly to an internal rate (rate_detail), otherwise, pass the upstream price through directly.',
'upstream_simple' => 'Simply pass through and charge the "upstream_price" amount.',
+ 'single_price' => 'A single price per minute for all calls.',
;
#tie my %cdr_location, 'Tie::IxHash',
@@ -33,6 +35,8 @@ tie my %temporalities, 'Tie::IxHash',
'preceding' => "Preceding (past)",
;
+tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
+
%info = (
'name' => 'VoIP rating by plan of CDR records in an internal (or external) SQL table',
'shortname' => 'VoIP/telco CDR rating (standard)',
@@ -55,7 +59,19 @@ tie my %temporalities, 'Tie::IxHash',
'type' => 'checkbox',
},
- 'rating_method' => { 'name' => 'Region rating method',
+ 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '.
+ 'subscription',
+ 'default' => '1',
+ },
+
+ 'recur_method' => { 'name' => 'Recurring fee method',
+ #'type' => 'radio',
+ #'options' => \%recur_method,
+ 'type' => 'select',
+ 'select_options' => \%FS::part_pkg::recur_Common::recur_method,
+ },
+
+ 'rating_method' => { 'name' => 'Rating method',
'type' => 'radio',
'options' => \%rating_method,
},
@@ -67,6 +83,14 @@ tie my %temporalities, 'Tie::IxHash',
'select_label' => 'ratename',
},
+ 'min_charge' => { 'name' => 'Charge per minute when using "single price per minute" rating method',
+ },
+
+ 'sec_granularity' => { 'name' => 'Granularity when using "single price per minute" rating method',
+ 'type' => 'select',
+ 'select_options' => \%granularity,
+ },
+
'ignore_unrateable' => { 'name' => 'Ignore calls without a rate in the rate tables. By default, the system will throw a fatal error upon encountering unrateable calls.',
'type' => 'checkbox',
},
@@ -119,6 +143,12 @@ tie my %temporalities, 'Tie::IxHash',
'skip_dstchannel_prefix' => { 'name' => 'Do not charge for CDRs where the dstchannel starts with:',
},
+ 'skip_dst_length_less' => { 'name' => 'Do not charge for CDRs where the destination is less than this many digits:',
+ },
+
+ 'skip_lastapp' => { 'name' => 'Do not charge for CDRs where the lastapp matches this value',
+ },
+
'use_duration' => { 'name' => 'Calculate usage based on the duration field instead of the billsec field',
'type' => 'checkbox',
},
@@ -126,23 +156,33 @@ tie my %temporalities, 'Tie::IxHash',
'411_rewrite' => { 'name' => 'Rewrite these (comma-separated) destination numbers to 411 for rating purposes (also ignore any carrierid check): ',
},
+ #false laziness w/cdr_termination.pm
'output_format' => { 'name' => 'CDR invoice display format',
'type' => 'select',
'select_options' => { FS::cdr::invoice_formats() },
'default' => 'default', #XXX test
},
- 'usage_section' => { 'name' => 'Section in which to place separate usage charges',
+ 'usage_section' => { 'name' => 'Section in which to place usage charges (whether separated or not)',
},
'summarize_usage' => { 'name' => 'Include usage summary with recurring charges when usage is in separate section',
'type' => 'checkbox',
},
+ 'usage_mandate' => { 'name' => 'Always put usage details in separate section',
+ 'type' => 'checkbox',
+ },
+ #eofalse
+
'bill_every_call' => { 'name' => 'Generate an invoice immediately for every call. Useful for prepaid.',
'type' => 'checkbox',
},
+ 'count_available_phones' => { 'name' => 'Consider for tax purposes the number of lines to be svc_phones that may be provisioned rather than those that actually are.',
+ 'type' => 'checkbox',
+ },
+
#XXX also have option for an external db
# 'cdr_location' => { 'name' => 'CDR database location'
# 'type' => 'select',
@@ -169,7 +209,9 @@ tie my %temporalities, 'Tie::IxHash',
},
'fieldorder' => [qw(
setup_fee recur_fee recur_temporality unused_credit
- rating_method ratenum ignore_unrateable
+ recur_method cutoff_day
+ rating_method ratenum min_charge sec_granularity
+ ignore_unrateable
default_prefix
disable_src
domestic_prefix international_prefix
@@ -177,10 +219,12 @@ tie my %temporalities, 'Tie::IxHash',
use_amaflags use_disposition
use_disposition_taqua use_carrierid use_cdrtypenum
skip_dcontext skip_dstchannel_prefix
+ skip_dst_length_less skip_lastapp
use_duration
411_rewrite
- output_format summarize_usage usage_section
+ output_format usage_mandate summarize_usage usage_section
bill_every_call
+ count_available_phones
)
],
'weight' => 40,
@@ -191,15 +235,38 @@ sub calc_setup {
$self->option('setup_fee');
}
-#false laziness w/voip_sqlradacct calc_recur resolve it if that one ever gets used again
sub calc_recur {
- my($self, $cust_pkg, $sdate, $details, $param ) = @_;
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_;
+
+ my $charges = 0;
+
+ $charges += $self->calc_usage(@_);
+ $charges += $self->calc_recur_Common(@_);
+
+ $charges;
+
+}
+
+sub calc_cancel {
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_;
+
+ $self->calc_usage(@_);
+}
+
+#false laziness w/voip_sqlradacct calc_recur resolve it if that one ever gets used again
+
+sub calc_usage {
+ my $self = shift;
+ my($cust_pkg, $sdate, $details, $param ) = @_;
#my $last_bill = $cust_pkg->last_bill;
my $last_bill = $cust_pkg->get('last_bill'); #->last_bill falls back to setup
return 0
- if $self->option('recur_temporality', 1) eq 'preceding' && $last_bill == 0;
+ if $self->option('recur_temporality', 1) eq 'preceding'
+ && ( $last_bill eq '' || $last_bill == 0 );
my $ratenum = $cust_pkg->part_pkg->option('ratenum');
@@ -209,7 +276,7 @@ sub calc_recur {
my $charges = 0;
- my $downstream_cdr = '';
+# my $downstream_cdr = '';
my $rating_method = $self->option('rating_method') || 'prefix';
my $intl = $self->option('international_prefix') || '011';
@@ -285,9 +352,7 @@ sub calc_recur {
###
my( $to_or_from, $number );
- if ( $cdr->dst =~ /^(\+?1)?8([02-8])\1/
- && ! $disable_tollfree
- )
+ if ( $cdr->is_tollfree && ! $disable_tollfree )
{ #tollfree call
$to_or_from = 'from';
$number = $cdr->src;
@@ -364,48 +429,78 @@ sub calc_recur {
}
- } elsif ( $rating_method eq 'upstream' ) { #XXX this was convergent, not currently used. very much becoming the odd one out. remove?
+# } elsif ( $rating_method eq 'upstream' ) { #XXX this was convergent, not currently used. very much becoming the odd one out. remove?
+#
+# if ( $cdr->cdrtypenum == 1 ) { #rate based on upstream rateid
+#
+# $rate_detail = $cdr->cdr_upstream_rate->rate_detail;
+#
+# $regionnum = $rate_detail->dest_regionnum;
+# $rate_region = $rate_detail->dest_region;
+#
+# $pretty_destnum = $cdr->dst;
+#
+# warn " found rate for regionnum $regionnum and ".
+# "rate detail $rate_detail\n"
+# if $DEBUG;
+#
+# } else { #pass upstream price through
+#
+# $charge = sprintf('%.2f', $cdr->upstream_price);
+# $charges += $charge;
+#
+# @call_details = (
+# #time2str("%Y %b %d - %r", $cdr->calldate_unix ),
+# time2str("%c", $cdr->calldate_unix), #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot
+# 'N/A', #minutes...
+# '$'.$charge,
+# #$pretty_destnum,
+# $cdr->description, #$rate_region->regionname,
+# );
+#
+# }
- if ( $cdr->cdrtypenum == 1 ) { #rate based on upstream rateid
+ } elsif ( $rating_method eq 'upstream_simple' ) {
- $rate_detail = $cdr->cdr_upstream_rate->rate_detail;
+ #XXX $charge = sprintf('%.2f', $cdr->upstream_price);
+ $charge = sprintf('%.3f', $cdr->upstream_price);
+ $charges += $charge;
- $regionnum = $rate_detail->dest_regionnum;
- $rate_region = $rate_detail->dest_region;
+ @call_details = ($cdr->downstream_csv( 'format' => $output_format,
+ 'charge' => $charge,
+ )
+ );
+ $classnum = $cdr->calltypenum;
- $pretty_destnum = $cdr->dst;
+ } elsif ( $rating_method eq 'single_price' ) {
- warn " found rate for regionnum $regionnum and ".
- "rate detail $rate_detail\n"
- if $DEBUG;
+ # a little false laziness w/below
- } else { #pass upstream price through
+ my $granularity = length($self->option('sec_granularity'))
+ ? $self->option('sec_granularity')
+ : 60;
- $charge = sprintf('%.2f', $cdr->upstream_price);
- $charges += $charge;
-
- @call_details = (
- #time2str("%Y %b %d - %r", $cdr->calldate_unix ),
- time2str("%c", $cdr->calldate_unix), #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot
- 'N/A', #minutes...
- '$'.$charge,
- #$pretty_destnum,
- $cdr->description, #$rate_region->regionname,
- );
+ # length($cdr->billsec) ? $cdr->billsec : $cdr->duration;
+ my $seconds = $use_duration ? $cdr->duration : $cdr->billsec;
- }
+ $seconds += $granularity - ( $seconds % $granularity )
+ if $seconds # don't granular-ize 0 billsec calls (bills them)
+ && $granularity; # 0 is per call
+ my $minutes = $seconds / 60; # sprintf("%.1f",
+ #$minutes =~ s/\.0$// if $granularity == 60;
- } elsif ( $rating_method eq 'upstream_simple' ) {
+ # XXX config?
+ #$charge = sprintf('%.2f', ( $self->option('min_charge') * $minutes )
+ #+ 0.00000001 ); #so 1.005 rounds to 1.01
+ $charge = sprintf('%.4f', ( $self->option('min_charge') * $minutes )
+ + 0.0000000001 ); #so 1.00005 rounds to 1.0001
- #XXX $charge = sprintf('%.2f', $cdr->upstream_price);
- $charge = sprintf('%.3f', $cdr->upstream_price);
$charges += $charge;
@call_details = ($cdr->downstream_csv( 'format' => $output_format,
'charge' => $charge,
)
);
- $classnum = $cdr->calltypenum;
} else {
die "don't know how to rate CDRs using method: $rating_method\n";
@@ -449,9 +544,11 @@ sub calc_recur {
$included_min{$regionnum} -= $minutes;
if ( $included_min{$regionnum} < 0 ) {
- my $charge_min = 0 - $included_min{$regionnum};
+ my $charge_min = 0 - $included_min{$regionnum}; #XXX should preserve
+ #(display?) this
$included_min{$regionnum} = 0;
- $charge = sprintf('%.2f', $rate_detail->min_charge * $charge_min );
+ $charge = sprintf('%.2f', ( $rate_detail->min_charge * $charge_min )
+ + 0.00000001 ); #so 1.005 rounds to 1.01
$charges += $charge;
}
@@ -475,13 +572,16 @@ sub calc_recur {
if ( $charge > 0 ) {
#just use FS::cust_bill_pkg_detail objects?
my $call_details;
+ my $phonenum = $cust_svc->svc_x->phonenum;
#if ( $self->option('rating_method') eq 'upstream_simple' ) {
if ( scalar(@call_details) == 1 ) {
- $call_details = [ 'C', $call_details[0], $charge, $classnum ];
+ $call_details =
+ [ 'C', $call_details[0], $charge, $classnum, $phonenum ];
} else { #only used for $rating_method eq 'upstream' now
$csv->combine(@call_details);
- $call_details = [ 'C', $csv->string, $charge, $classnum ];
+ $call_details =
+ [ 'C', $csv->string, $charge, $classnum, $phonenum ];
}
warn " adding details on charge to invoice: [ ".
join(', ', @{$call_details} ). " ]"
@@ -492,10 +592,13 @@ sub calc_recur {
# if the customer flag is on, call "downstream_csv" or something
# like it to export the call downstream!
# XXX price plan option to pick format, or something...
- $downstream_cdr .= $cdr->downstream_csv( 'format' => 'convergent' )
- if $spool_cdr;
+ #$downstream_cdr .= $cdr->downstream_csv( 'format' => 'XXX format' )
+ # if $spool_cdr;
- my $error = $cdr->set_status_and_rated_price('done', $charge);
+ my $error = $cdr->set_status_and_rated_price( 'done',
+ $charge,
+ $cust_svc->svcnum,
+ );
die $error if $error;
}
@@ -507,35 +610,32 @@ sub calc_recur {
unshift @$details, [ 'C', FS::cdr::invoice_header($output_format) ]
if @$details && $rating_method ne 'upstream';
- if ( $spool_cdr && length($downstream_cdr) ) {
-
- use FS::UID qw(datasrc);
- my $dir = '/usr/local/etc/freeside/export.'. datasrc. '/cdr';
- mkdir $dir, 0700 unless -d $dir;
- $dir .= '/'. $cust_pkg->custnum.
- mkdir $dir, 0700 unless -d $dir;
- my $filename = time2str("$dir/CDR%Y%m%d-spool.CSV", time); #XXX invoice date instead? would require changing the order things are generated in cust_main::bill insert cust_bill first - with transactions it could be done though
-
- push @{ $param->{'precommit_hooks'} },
- sub {
- #lock the downstream spool file and append the records
- use Fcntl qw(:flock);
- use IO::File;
- my $spool = new IO::File ">>$filename"
- or die "can't open $filename: $!\n";
- flock( $spool, LOCK_EX)
- or die "can't lock $filename: $!\n";
- seek($spool, 0, 2)
- or die "can't seek to end of $filename: $!\n";
- print $spool $downstream_cdr;
- flock( $spool, LOCK_UN );
- close $spool;
- };
-
- } #if ( $spool_cdr && length($downstream_cdr) )
-
- $charges += $self->option('recur_fee')
- if $param->{'increment_next_bill'};
+# if ( $spool_cdr && length($downstream_cdr) ) {
+#
+# use FS::UID qw(datasrc);
+# my $dir = '/usr/local/etc/freeside/export.'. datasrc. '/cdr';
+# mkdir $dir, 0700 unless -d $dir;
+# $dir .= '/'. $cust_pkg->custnum.
+# mkdir $dir, 0700 unless -d $dir;
+# my $filename = time2str("$dir/CDR%Y%m%d-spool.CSV", time); #XXX invoice date instead? would require changing the order things are generated in cust_main::bill insert cust_bill first - with transactions it could be done though
+#
+# push @{ $param->{'precommit_hooks'} },
+# sub {
+# #lock the downstream spool file and append the records
+# use Fcntl qw(:flock);
+# use IO::File;
+# my $spool = new IO::File ">>$filename"
+# or die "can't open $filename: $!\n";
+# flock( $spool, LOCK_EX)
+# or die "can't lock $filename: $!\n";
+# seek($spool, 0, 2)
+# or die "can't seek to end of $filename: $!\n";
+# print $spool $downstream_cdr;
+# flock( $spool, LOCK_UN );
+# close $spool;
+# };
+#
+# } #if ( $spool_cdr && length($downstream_cdr) )
$charges;
}
@@ -554,10 +654,12 @@ sub check_chargable {
use_carrierid
use_cdrtypenum
skip_dcontext
- skip_dstchannel_prefix;
+ skip_dstchannel_prefix
+ skip_dst_length_less
+ skip_lastapp
);
foreach my $opt (grep !exists($flags{option_cache}->{$_}), @opt ) {
- $flags{option_cache}->{$opt} = $self->option($opt);
+ $flags{option_cache}->{$opt} = $self->option($opt, 1);
}
my %opt = %{ $flags{option_cache} };
@@ -583,10 +685,17 @@ sub check_chargable {
if $opt{'skip_dcontext'} =~ /\S/
&& grep { $cdr->dcontext eq $_ } split(/\s*,\s*/, $opt{'skip_dcontext'});
- my $len = length($opt{'skip_dstchannel_prefix'});
+ my $len_prefix = length($opt{'skip_dstchannel_prefix'});
return "dstchannel starts with $opt{'skip_dstchannel_prefix'}"
- if $len
- && substr($cdr->dstchannel, 0, $len) eq $opt{'skip_dstchannel_prefix'};
+ if $len_prefix
+ && substr($cdr->dstchannel,0,$len_prefix) eq $opt{'skip_dstchannel_prefix'};
+
+ my $dst_length = $opt{'skip_dst_length_less'};
+ return "destination less than $dst_length digits"
+ if $dst_length && length($cdr->dst) < $dst_length;
+
+ return "lastapp is $opt{'skip_lastapp'}"
+ if length($opt{'skip_lastapp'}) && $cdr->lastapp eq $opt{'skip_lastapp'};
#all right then, rate it
'';
@@ -596,16 +705,20 @@ sub is_free {
0;
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_fee');
-}
-
# This equates svc_phone records; perhaps svc_phone should have a field
# to indicate it represents a line
sub calc_units {
my($self, $cust_pkg ) = @_;
- scalar(grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc);
+ my $count = 0;
+ if ( $self->option('count_available_phones', 1)) {
+ map { $count += ( $_->quantity || 0 ) }
+ grep { $_->part_svc->svcdb eq 'svc_phone' }
+ $cust_pkg->part_pkg->pkg_svc;
+ } else {
+ $count =
+ scalar(grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc);
+ }
+ $count;
}
1;
diff --git a/FS/FS/part_pkg_link.pm b/FS/FS/part_pkg_link.pm
index f517360..fb7a8d3 100644
--- a/FS/FS/part_pkg_link.pm
+++ b/FS/FS/part_pkg_link.pm
@@ -51,6 +51,11 @@ Destination package (see L<FS::part_pkg>)
Link type - currently, "bill" (source package bills a line item from target
package), or "svc" (source package includes services from target package).
+=item hidden
+
+Flag indicating that this subpackage should be felt, but not seen as an invoice
+line item when set to 'Y'
+
=back
=head1 METHODS
@@ -114,7 +119,8 @@ sub check {
$self->ut_numbern('pkglinknum')
|| $self->ut_foreign_key('src_pkgpart', 'part_pkg', 'pkgpart')
|| $self->ut_foreign_key('dst_pkgpart', 'part_pkg', 'pkgpart')
- || $self->ut_text('link_type', [ 'bill', 'svc' ] )
+ || $self->ut_enum('link_type', [ 'bill', 'svc' ] )
+ || $self->ut_enum('hidden', [ '', 'Y' ] )
;
return $error if $error;
diff --git a/FS/FS/part_pkg_option.pm b/FS/FS/part_pkg_option.pm
index 9708f11..3cb330b 100644
--- a/FS/FS/part_pkg_option.pm
+++ b/FS/FS/part_pkg_option.pm
@@ -127,11 +127,16 @@ sub check {
sub _upgrade_data { # class method
my ($class, %opts) = @_;
- my $sql = "UPDATE part_pkg_option SETUP optionname = 'recur_fee'".
+ my $sql = "UPDATE part_pkg_option SET optionname = 'recur_fee'".
" WHERE optionname = 'recur_flat'";
my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute or die $sth->errstr;
+ $sql = "UPDATE part_pkg_option SET optionname = 'recur_method',".
+ "optionvalue = 'prorate' WHERE optionname = 'enable_prorate'";
+ $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
'';
}
diff --git a/FS/FS/part_pkg_report_option.pm b/FS/FS/part_pkg_report_option.pm
new file mode 100644
index 0000000..16a4c98
--- /dev/null
+++ b/FS/FS/part_pkg_report_option.pm
@@ -0,0 +1,125 @@
+package FS::part_pkg_report_option;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::part_pkg_report_option - Object methods for part_pkg_report_option records
+
+=head1 SYNOPSIS
+
+ use FS::part_pkg_report_option;
+
+ $record = new FS::part_pkg_report_option \%hash;
+ $record = new FS::part_pkg_report_option { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::part_pkg_report_option object represents a package definition optional
+reporting classification. FS::part_pkg_report_option inherits from
+FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item num
+
+primary key
+
+=item name
+
+name - The name associated with the reporting option
+
+=item disabled
+
+disabled - set to 'Y' to prevent addition to new packages
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new report option. To add the option to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'part_pkg_report_option'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete {
+ return "Can't delete part_pkg_report_option records!";
+}
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+=item check
+
+Checks all fields to make sure this is a valid example. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('num')
+ || $self->ut_text('name')
+ || $self->ut_enum('disabled', [ '', 'Y' ])
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+Overlaps somewhat with pkg_class and pkg_category
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_pkg_taxclass.pm b/FS/FS/part_pkg_taxclass.pm
index fda200e..6e3acf2 100644
--- a/FS/FS/part_pkg_taxclass.pm
+++ b/FS/FS/part_pkg_taxclass.pm
@@ -2,8 +2,9 @@ package FS::part_pkg_taxclass;
use strict;
use vars qw( @ISA );
-use FS::UID qw(dbh);
-use FS::Record qw( qsearch qsearchs );
+use FS::UID qw( dbh );
+use FS::Record; # qw( qsearch qsearchs );
+use FS::cust_main_county;
@ISA = qw(FS::Record);
@@ -41,6 +42,10 @@ Primary key
Tax class
+=item disabled
+
+Disabled flag, empty or 'Y'
+
=back
=head1 METHODS
@@ -67,7 +72,57 @@ otherwise returns false.
=cut
-# the insert method can be inherited from FS::Record
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ my $sth = dbh->prepare("
+ SELECT country, state, county FROM cust_main_county
+ WHERE taxclass IS NOT NULL AND taxclass != ''
+ GROUP BY country, state, county
+ ") or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ while ( my $row = $sth->fetchrow_hashref ) {
+ #warn "inserting for $row";
+ my $cust_main_county = new FS::cust_main_county {
+ 'country' => $row->{country},
+ 'state' => $row->{state},
+ 'county' => $row->{county},
+ 'tax' => 0,
+ 'taxclass' => $self->taxclass,
+ #exempt_amount
+ #taxname
+ #setuptax
+ #recurtax
+ };
+ $error = $cust_main_county->insert;
+ #last if $error;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+}
=item delete
@@ -84,7 +139,18 @@ returns the error, otherwise returns false.
=cut
-# the replace method can be inherited from FS::Record
+sub replace {
+ my $new = shift;
+
+ my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
+ ? shift
+ : $new->replace_old;
+
+ return "Can't change tax class name (disable and create anew)"
+ if $old->taxclass ne $new->taxclass;
+
+ $new->SUPER::replace(@_);
+}
=item check
@@ -103,6 +169,7 @@ sub check {
my $error =
$self->ut_numbern('taxclassnum')
|| $self->ut_text('taxclass')
+ || $self->ut_enum('disabled', [ '', 'Y' ] )
;
return $error if $error;
diff --git a/FS/FS/part_pkg_taxproduct.pm b/FS/FS/part_pkg_taxproduct.pm
index c66fb8c..56e63b6 100644
--- a/FS/FS/part_pkg_taxproduct.pm
+++ b/FS/FS/part_pkg_taxproduct.pm
@@ -1,10 +1,11 @@
package FS::part_pkg_taxproduct;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $delete_kludge );
use FS::Record qw( qsearch );
@ISA = qw(FS::Record);
+$delete_kludge = 0;
=head1 NAME
@@ -85,8 +86,10 @@ sub delete {
return "Can't delete a tax product which has attached package tax rates!"
if qsearch( 'part_pkg_taxrate', { 'taxproductnum' => $self->taxproductnum } );
- return "Can't delete a tax product which has attached packages!"
- if qsearch( 'part_pkg', { 'taxproductnum' => $self->taxproductnum } );
+ unless ( $delete_kludge ) {
+ return "Can't delete a tax product which has attached packages!"
+ if qsearch( 'part_pkg', { 'taxproductnum' => $self->taxproductnum } );
+ }
$self->SUPER::delete(@_);
}
diff --git a/FS/FS/part_pkg_taxrate.pm b/FS/FS/part_pkg_taxrate.pm
index 6d1414a..5a1e7ba 100644
--- a/FS/FS/part_pkg_taxrate.pm
+++ b/FS/FS/part_pkg_taxrate.pm
@@ -3,6 +3,8 @@ package FS::part_pkg_taxrate;
use strict;
use vars qw( @ISA );
use Date::Parse;
+use DateTime;
+use DateTime::Format::Strptime;
use FS::UID qw(dbh);
use FS::Record qw( qsearch qsearchs );
use FS::part_pkg_taxproduct;
@@ -181,7 +183,7 @@ sub batch_import {
if ( $format eq 'cch-fixed' || $format eq 'cch-fixed-update' ) {
$format =~ s/-fixed//;
my $date_format = sub { my $r='';
- /^(\d{4})(\d{2})(\d{2})$/ && ($r="$1/$2/$3");
+ /^(\d{4})(\d{2})(\d{2})$/ && ($r="$3/$2/$1");
$r;
};
$column_callbacks[16] = $date_format;
@@ -248,8 +250,8 @@ sub batch_import {
$part_pkg_taxproduct{'description'} =
join(' : ', (map{ $hash->{$_} } qw(groupdesc itemdesc)),
- $providers{$hash->{'provider'}},
- $customers{$hash->{'customer'}},
+ $providers{$hash->{'provider'}} || '',
+ $customers{$hash->{'customer'}} || '',
);
$part_pkg_taxproduct = new FS::part_pkg_taxproduct \%part_pkg_taxproduct;
my $error = $part_pkg_taxproduct->insert;
@@ -286,7 +288,12 @@ sub batch_import {
delete($hash->{$_}) foreach @{$map{$item}};
}
- $hash->{'effdate'} = str2time($hash->{'effdate'});
+ my $parser = new DateTime::Format::Strptime( pattern => "%m/%d/%Y",
+ time_zone => 'floating',
+ );
+ my $dt = $parser->parse_datetime( $hash->{'effdate'} );
+ $hash->{'effdate'} = $dt ? $dt->epoch : '';
+
$hash->{'country'} = 'US'; # CA is available
delete($hash->{'taxable'}) if ($hash->{'taxable'} eq 'N');
@@ -295,10 +302,18 @@ sub batch_import {
delete($hash->{actionflag});
my $part_pkg_taxrate = qsearchs('part_pkg_taxrate', $hash);
- return "Can't find part_pkg_taxrate to delete: ".
- #join(" ", map { "$_ => ". $hash->{$_} } @fields)
- join(" ", map { "$_ => *". $hash->{$_}. '*' } keys(%$hash) )
- unless $part_pkg_taxrate;
+ unless ( $part_pkg_taxrate ) {
+ if ( $hash->{taxproductnum} ) {
+ my $taxproduct =
+ qsearchs( 'part_pkg_taxproduct',
+ { 'taxproductnum' => $hash->{taxproductnum} }
+ );
+ $hash->{taxproductnum} .= ' ( '. $taxproduct->taxproduct. ' )'
+ if $taxproduct;
+ }
+ return "Can't find part_pkg_taxrate to delete: ".
+ join(" ", map { "$_ => *". $hash->{$_}. '*' } keys(%$hash) );
+ }
my $error = $part_pkg_taxrate->delete;
return $error if $error;
@@ -345,7 +360,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax matrix"
);
die $error if $error;
$last = time;
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 580038b..e57efe4 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -133,7 +133,8 @@ sub insert {
# fields('part_svc');
foreach my $field (
grep { $_ ne 'svcnum'
- && defined( $self->getfield($svcdb.'__'.$_.'_flag') )
+ && ( defined( $self->getfield($svcdb.'__'.$_.'_flag') )
+ || $self->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
} (fields($svcdb), @fields)
) {
my $part_svc_column = $self->part_svc_column($field);
@@ -142,20 +143,28 @@ sub insert {
'columnname' => $field,
} );
- my $flag = $self->getfield($svcdb.'__'.$field.'_flag');
- #if ( uc($flag) =~ /^([DFMAX])$/ ) {
- if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it
- my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
- || sub { shift };
- $part_svc_column->setfield('columnflag', $1);
- $part_svc_column->setfield('columnvalue',
- &$parser($self->getfield($svcdb.'__'.$field))
- );
+ my $flag = $self->getfield($svcdb.'__'.$field.'_flag');
+ my $label = $self->getfield($svcdb.'__'.$field.'_label');
+ if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
+
+ if ( uc($flag) =~ /^([A-Z])$/ ) {
+ my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+ || sub { shift };
+ $part_svc_column->setfield('columnflag', $1);
+ $part_svc_column->setfield('columnvalue',
+ &$parser($self->getfield($svcdb.'__'.$field))
+ );
+ }
+
+ $part_svc_column->setfield('columnlabel', $label)
+ if $label !~ /^\s*$/;
+
if ( $previous ) {
$error = $part_svc_column->replace($previous);
} else {
$error = $part_svc_column->insert;
}
+
} else {
$error = $previous ? $previous->delete : '';
}
@@ -254,7 +263,8 @@ sub replace {
my $svcdb = $new->svcdb;
foreach my $field (
grep { $_ ne 'svcnum'
- && defined( $new->getfield($svcdb.'__'.$_.'_flag') )
+ && ( defined( $new->getfield($svcdb.'__'.$_.'_flag') )
+ || $new->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
} (fields($svcdb),@fields)
) {
my $part_svc_column = $new->part_svc_column($field);
@@ -263,15 +273,23 @@ sub replace {
'columnname' => $field,
} );
- my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
- #if ( uc($flag) =~ /^([DFMAX])$/ ) {
- if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it
- my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+ my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
+ my $label = $new->getfield($svcdb.'__'.$field.'_label');
+
+ if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
+
+ if ( uc($flag) =~ /^([A-Z])$/ ) {
+ my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
|| sub { shift };
- $part_svc_column->setfield('columnflag', $1);
- $part_svc_column->setfield('columnvalue',
- &$parser($new->getfield($svcdb.'__'.$field))
- );
+ $part_svc_column->setfield('columnflag', $1);
+ $part_svc_column->setfield('columnvalue',
+ &$parser($new->getfield($svcdb.'__'.$field))
+ );
+ }
+
+ $part_svc_column->setfield('columnlabel', $label)
+ if $label !~ /^\s*$/;
+
if ( $previous ) {
$error = $part_svc_column->replace($previous);
} else {
@@ -713,17 +731,16 @@ sub process {
push @fields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
map {
- if ( $param->{ $svcdb.'__'.$_.'_flag' } =~ /^[MA]$/ ) {
- $param->{ $svcdb.'__'.$_ } =
- delete( $param->{ $svcdb.'__'.$_.'_classnum' } );
+ my $f = $svcdb.'__'.$_;
+ if ( $param->{ $f.'_flag' } =~ /^[MA]$/ ) {
+ $param->{ $f } = delete( $param->{ $f.'_classnum' } );
}
- if ( $param->{ $svcdb.'__'.$_.'_flag' } =~ /^S$/ ) {
- $param->{ $svcdb.'__'.$_} =
- ref($param->{ $svcdb.'__'.$_})
- ? join(',', @{$param->{ $svcdb.'__'.$_ }} )
- : $param->{ $svcdb.'__'.$_ };
+ if ( $param->{ $f.'_flag' } =~ /^S$/ ) {
+ $param->{ $f } = ref($param->{ $f })
+ ? join(',', @{$param->{ $f }} )
+ : $param->{ $f };
}
- ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' );
+ ( $f, $f.'_flag', $f.'_label' );
}
@fields;
@@ -738,7 +755,7 @@ sub process {
my $error;
if ( $param->{'svcpart'} ) {
$error = $new->replace( $old,
- '1.3-COMPAT',
+ '1.3-COMPAT', #totally bunk, as jeff noted
[ 'usergroup' ],
\%exportnums,
$job
diff --git a/FS/FS/part_svc_column.pm b/FS/FS/part_svc_column.pm
index d2b8fd9..f5b39c0 100644
--- a/FS/FS/part_svc_column.pm
+++ b/FS/FS/part_svc_column.pm
@@ -39,6 +39,8 @@ fields are currently supported:
=item columnname - column name in part_svc.svcdb table
+=item columnlabel - label for the column
+
=item columnvalue - default or fixed value for the column
=item columnflag - null or empty (no default), `D' for default, `F' for fixed (unchangeable), `S' for selectable choice, `M' for manual selection from inventory, or `A' for automatic selection from inventory. For virtual fields, can also be 'X' for excluded.
@@ -87,11 +89,12 @@ sub check {
$self->ut_numbern('columnnum')
|| $self->ut_number('svcpart')
|| $self->ut_alpha('columnname')
+ || $self->ut_textn('columnlabel')
|| $self->ut_anything('columnvalue')
;
return $error if $error;
- $self->columnflag =~ /^([DFSMAX])$/
+ $self->columnflag =~ /^([DFSMAX]?)$/
or return "illegal columnflag ". $self->columnflag;
$self->columnflag(uc($1));
diff --git a/FS/FS/pay_batch.pm b/FS/FS/pay_batch.pm
index 5448b03..83bf7a3 100644
--- a/FS/FS/pay_batch.pm
+++ b/FS/FS/pay_batch.pm
@@ -1,11 +1,12 @@
package FS::pay_batch;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $DEBUG %import_info %export_info $conf );
use Time::Local;
use Text::CSV_XS;
use FS::Record qw( dbh qsearch qsearchs );
use FS::cust_pay;
+use FS::Conf;
@ISA = qw(FS::Record);
@@ -137,6 +138,42 @@ sub set_status {
$self->replace();
}
+# further false laziness
+
+%import_info = %export_info = ();
+foreach my $INC (@INC) {
+ warn "globbing $INC/FS/pay_batch/*.pm\n" if $DEBUG;
+ foreach my $file ( glob("$INC/FS/pay_batch/*.pm")) {
+ warn "attempting to load batch format from $file\n" if $DEBUG;
+ $file =~ /\/(\w+)\.pm$/;
+ next if !$1;
+ my $mod = $1;
+ my ($import, $export, $name) =
+ eval "use FS::pay_batch::$mod;
+ ( \\%FS::pay_batch::$mod\::import_info,
+ \\%FS::pay_batch::$mod\::export_info,
+ \$FS::pay_batch::$mod\::name)";
+ $name ||= $mod; # in case it's not defined
+ if( $@) {
+ # in FS::cdr this is a die, not a warn. That's probably a bug.
+ warn "error using FS::pay_batch::$mod (skipping): $@\n";
+ next;
+ }
+ if(!keys(%$import)) {
+ warn "no \%import_info found in FS::pay_batch::$mod (skipping)\n";
+ }
+ else {
+ $import_info{$name} = $import;
+ }
+ if(!keys(%$export)) {
+ warn "no \%export_info found in FS::pay_batch::$mod (skipping)\n";
+ }
+ else {
+ $export_info{$name} = $export;
+ }
+ }
+}
+
=item import_results OPTION => VALUE, ...
Import batch results.
@@ -155,222 +192,19 @@ sub import_results {
my $param = ref($_[0]) ? shift : { @_ };
my $fh = $param->{'filehandle'};
my $format = $param->{'format'};
-
- my $filetype; # CSV, Fixed80, Fixed264
- my @fields;
- my $formatre; # for Fixed.+
- my @values;
- my $begin_condition;
- my $end_condition;
- my $end_hook;
- my $hook;
- my $approved_condition;
- my $declined_condition;
-
- if ( $format eq 'csv-td_canada_trust-merchant_pc_batch' ) {
-
- $filetype = "CSV";
-
- @fields = (
- 'paybatchnum', # Reference#: Invoice number of the transaction
- 'paid', # Amount: Amount of the transaction. Dollars and cents
- # with no decimal entered.
- '', # Card Type: 0 - MCrd, 1 - Visa, 2 - AMEX, 3 - Discover,
- # 4 - Insignia, 5 - Diners/EnRoute, 6 - JCB
- '_date', # Transaction Date: Date the Transaction was processed
- 'time', # Transaction Time: Time the transaction was processed
- 'payinfo', # Card Number: Card number for the transaction
- '', # Expiry Date: Expiry date of the card
- '', # Auth#: Authorization number entered for force post
- # transaction
- 'type', # Transaction Type: 0 - purchase, 40 - refund,
- # 20 - force post
- 'result', # Processing Result: 3 - Approval,
- # 4 - Declined/Amount over limit,
- # 5 - Invalid/Expired/stolen card,
- # 6 - Comm Error
- '', # Terminal ID: Terminal ID used to process the transaction
- );
-
- $end_condition = sub {
- my $hash = shift;
- $hash->{'type'} eq '0BC';
- };
-
- $end_hook = sub {
- my( $hash, $total) = @_;
- $total = sprintf("%.2f", $total);
- my $batch_total = sprintf("%.2f", $hash->{'paybatchnum'} / 100 );
- return "Our total $total does not match bank total $batch_total!"
- if $total != $batch_total;
- '';
- };
-
- $hook = sub {
- my $hash = shift;
- $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100 );
- $hash->{'_date'} = timelocal( substr($hash->{'time'}, 4, 2),
- substr($hash->{'time'}, 2, 2),
- substr($hash->{'time'}, 0, 2),
- substr($hash->{'_date'}, 6, 2),
- substr($hash->{'_date'}, 4, 2)-1,
- substr($hash->{'_date'}, 0, 4)-1900, );
- };
-
- $approved_condition = sub {
- my $hash = shift;
- $hash->{'type'} eq '0' && $hash->{'result'} == 3;
- };
-
- $declined_condition = sub {
- my $hash = shift;
- $hash->{'type'} eq '0' && ( $hash->{'result'} == 4
- || $hash->{'result'} == 5 );
- };
-
-
- }elsif ( $format eq 'csv-chase_canada-E-xactBatch' ) {
-
- $filetype = "CSV";
-
- @fields = (
- '', # Internal(bank) id of the transaction
- '', # Transaction Type: 00 - purchase, 01 - preauth,
- # 02 - completion, 03 - forcepost,
- # 04 - refund, 05 - auth,
- # 06 - purchase corr, 07 - refund corr,
- # 08 - void 09 - void return
- '', # gateway used to process this transaction
- 'paid', # Amount: Amount of the transaction. Dollars and cents
- # with decimal entered.
- 'auth', # Auth#: Authorization number (if approved)
- 'payinfo', # Card Number: Card number for the transaction
- '', # Expiry Date: Expiry date of the card
- '', # Cardholder Name
- 'bankcode', # Bank response code (3 alphanumeric)
- 'bankmess', # Bank response message
- 'etgcode', # ETG response code (2 alphanumeric)
- 'etgmess', # ETG response message
- '', # Returned customer number for the transaction
- 'paybatchnum', # Reference#: paybatch number of the transaction
- '', # Reference#: Invoice number of the transaction
- 'result', # Processing Result: Approved of Declined
- );
-
- $end_condition = sub {
- '';
- };
-
- $hook = sub {
- my $hash = shift;
- my $cpb = shift;
- $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'}); #hmmmm
- $hash->{'_date'} = time; # got a better one?
- $hash->{'payinfo'} = $cpb->{'payinfo'}
- if( substr($hash->{'payinfo'}, -4) eq substr($cpb->{'payinfo'}, -4) );
- };
-
- $approved_condition = sub {
- my $hash = shift;
- $hash->{'etgcode'} eq '00' && $hash->{'result'} eq "Approved";
- };
-
- $declined_condition = sub {
- my $hash = shift;
- $hash->{'etgcode'} ne '00' # internal processing error
- || ( $hash->{'result'} eq "Declined" );
- };
-
-
- }elsif ( $format eq 'PAP' ) {
-
- $filetype = "Fixed264";
-
- @fields = (
- 'recordtype', # We are interested in the 'D' or debit records
- 'batchnum', # Record#: batch number we used when sending the file
- 'datacenter', # Where in the bowels of the bank the data was processed
- 'paid', # Amount: Amount of the transaction. Dollars and cents
- # with no decimal entered.
- '_date', # Transaction Date: Date the Transaction was processed
- 'bank', # Routing information
- 'payinfo', # Account number for the transaction
- 'paybatchnum', # Reference#: Invoice number of the transaction
- );
-
- $formatre = '^(.).{19}(.{4})(.{3})(.{10})(.{6})(.{9})(.{12}).{110}(.{19}).{71}$';
-
- $end_condition = sub {
- my $hash = shift;
- $hash->{'recordtype'} eq 'W';
- };
-
- $end_hook = sub {
- my( $hash, $total) = @_;
- $total = sprintf("%.2f", $total);
- my $batch_total = $hash->{'datacenter'}.$hash->{'paid'}.
- substr($hash->{'_date'},0,1); # YUCK!
- $batch_total = sprintf("%.2f", $batch_total / 100 );
- return "Our total $total does not match bank total $batch_total!"
- if $total != $batch_total;
- '';
- };
-
- $hook = sub {
- my $hash = shift;
- $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100 );
- my $tmpdate = timelocal( 0,0,1,1,0,substr($hash->{'_date'}, 0, 3)+2000);
- $tmpdate += 86400*(substr($hash->{'_date'}, 3, 3)-1) ;
- $hash->{'_date'} = $tmpdate;
- $hash->{'payinfo'} = $hash->{'payinfo'} . '@' . $hash->{'bank'};
- };
-
- $approved_condition = sub {
- 1;
- };
-
- $declined_condition = sub {
- 0;
- };
-
- }elsif ( $format eq 'ach-spiritone' ) {
-
- $filetype = "CSV";
-
- @fields = (
- '', # Name
- 'paybatchnum', # ID: Number of the transaction
- 'aba', # ABA Number for the transaction
- 'payinfo', # Bank Account Number for the transaction
- '', # Transaction Type: 27 - debit
- 'paid', # Amount: Amount of the transaction. Dollars and cents
- # with decimal entered.
- '', # Default Transaction Type
- '', # Default Amount: Dollars and cents with decimal entered.
- );
-
- $end_condition = sub {
- '';
- };
-
- $hook = sub {
- my $hash = shift;
- $hash->{'_date'} = time; # got a better one?
- $hash->{'payinfo'} = $hash->{'payinfo'} . '@' . $hash->{'aba'};
- };
-
- $approved_condition = sub {
- 1;
- };
-
- $declined_condition = sub {
- 0;
- };
-
-
- } else {
- return "Unknown format $format";
- }
+ my $info = $import_info{$format}
+ or die "unknown format $format";
+
+ my $filetype = $info->{'filetype'}; # CSV or fixed
+ my @fields = @{ $info->{'fields'} };
+ my $formatre = $info->{'formatre'}; # for fixed
+ my @all_values;
+ my $begin_condition = $info->{'begin_condition'};
+ my $end_condition = $info->{'end_condition'};
+ my $end_hook = $info->{'end_hook'};
+ my $hook = $info->{'hook'};
+ my $approved_condition = $info->{'approved'};
+ my $declined_condition = $info->{'declined'};
my $csv = new Text::CSV_XS;
@@ -390,36 +224,68 @@ sub import_results {
unless ( $reself->status eq 'I' ) {
$dbh->rollback if $oldAutoCommit;
return "batchnum ". $self->batchnum. "no longer in transit";
- };
+ }
my $error = $self->set_status('R');
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return $error
+ return $error;
}
my $total = 0;
my $line;
- while ( defined($line=<$fh>) ) {
-
- next if $line =~ /^\s*$/; #skip blank lines
- if ($filetype eq "CSV") {
- $csv->parse($line) or do {
- $dbh->rollback if $oldAutoCommit;
- return "can't parse: ". $csv->error_input();
- };
- @values = $csv->fields();
- }elsif ($filetype eq "Fixed80" || $filetype eq "Fixed264"){
- @values = $line =~ /$formatre/;
- unless (@values) {
- $dbh->rollback if $oldAutoCommit;
- return "can't parse: ". $line;
- };
- }else{
+ # Order of operations has been changed here.
+ # We now slurp everything into @all_values, then
+ # process one line at a time.
+
+ if ($filetype eq 'XML') {
+ eval "use XML::Simple";
+ die $@ if $@;
+ my @xmlkeys = @{ $info->{'xmlkeys'} }; # for XML
+ my $xmlrow = $info->{'xmlrow'}; # also for XML
+
+ # Do everything differently.
+ my $data = XML::Simple::XMLin($fh, KeepRoot => 1);
+ my $rows = $data;
+ # $xmlrow = [ RootKey, FirstLevelKey, SecondLevelKey... ]
+ $rows = $rows->{$_} foreach( @$xmlrow );
+ if(!defined($rows)) {
$dbh->rollback if $oldAutoCommit;
- return "Unknown file type $filetype";
+ return "can't find rows in XML file";
+ }
+ $rows = [ $rows ] if ref($rows) ne 'ARRAY';
+ foreach my $row (@$rows) {
+ push @all_values, [ @{$row}{@xmlkeys} ];
}
+ }
+ else {
+ while ( defined($line=<$fh>) ) {
+
+ next if $line =~ /^\s*$/; #skip blank lines
+
+ if ($filetype eq "CSV") {
+ $csv->parse($line) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $csv->error_input();
+ };
+ push @all_values, [ $csv->fields() ];
+ }elsif ($filetype eq 'fixed'){
+ my @values = $line =~ /$formatre/;
+ unless (@values) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $line;
+ };
+ push @all_values, \@values;
+ }else{
+ $dbh->rollback if $oldAutoCommit;
+ return "Unknown file type $filetype";
+ }
+ }
+ }
+
+ foreach (@all_values) {
+ my @values = @$_;
my %hash;
foreach my $field ( @fields ) {
@@ -428,8 +294,9 @@ sub import_results {
$hash{$field} = $value;
}
- if ( &{$end_condition}(\%hash) ) {
- my $error = &{$end_hook}(\%hash, $total);
+ if ( defined($end_condition) and &{$end_condition}(\%hash) ) {
+ my $error;
+ $error = &{$end_hook}(\%hash, $total) if defined($end_hook);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -514,7 +381,6 @@ sub import_results {
}
-
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -522,6 +388,94 @@ sub import_results {
}
+sub export_batch {
+# Formerly httemplate/misc/download-batch.cgi
+ my $self = shift;
+ my $conf = new FS::Conf;
+ my $format = shift || $conf->config('batch-default_format')
+ or die "No batch format configured\n";
+ my $info = $export_info{$format} or die "Format not found: '$format'\n";
+ &{$info->{'init'}}($conf) if exists($info->{'init'});
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error;
+
+ my $first_download;
+ if($self->status eq 'O') {
+ $first_download = 1;
+ }
+ elsif($self->status eq 'I' and
+ $FS::CurrentUser::CurrentUser->access_right('Reprocess batches')) {
+ $first_download = 0;
+ }
+ else {
+ die "No pending batch.\n"
+ }
+
+ $error = $self->set_status('I');
+ die "error updating pay_batch status: $error\n" if $error;
+
+ my $batch = '';
+ my $batchtotal = 0;
+ my $batchcount = 0;
+
+ my @cust_pay_batch = sort { $a->paybatchnum <=> $b->paybatchnum }
+ qsearch('cust_pay_batch', { batchnum => $self->batchnum } );
+
+ my $h = $info->{'header'};
+ if(ref($h) eq 'CODE') {
+ $batch .= &$h($self, \@cust_pay_batch) . "\n";
+ }
+ else {
+ $batch .= $h . "\n";
+ }
+ foreach my $cust_pay_batch (@cust_pay_batch) {
+ if($first_download) {
+ my $balance = $cust_pay_batch->cust_main->balance;
+ $error = '';
+ if($balance <= 0) { # then don't charge this customer
+ $error = $cust_pay_batch->delete;
+ undef $cust_pay_batch;
+ }
+ elsif($balance < $cust_pay_batch->amount) { # then reduce the charge to the remaining balance
+ $cust_pay_batch->amount($balance);
+ $error = $cust_pay_batch->replace;
+ }
+ # else $balance >= $cust_pay_batch->amount
+ if($error) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+ if($cust_pay_batch) { # that is, it wasn't deleted
+ $batchcount++;
+ $batchtotal += $cust_pay_batch->amount;
+ $batch .= &{$info->{'row'}}($cust_pay_batch, $self) . "\n";
+ }
+ }
+ my $f = $info->{'footer'};
+ if(ref($f) eq 'CODE') {
+ $batch .= &$f($self, $batchcount, $batchtotal) . "\n";
+ }
+ else {
+ $batch .= $f . "\n";
+ }
+
+ if ($info->{'autopost'}) {
+ $error = &{$info->{'autopost'}}($self, $batch);
+ if($error) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return $batch;
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/pay_batch/BoM.pm b/FS/FS/pay_batch/BoM.pm
new file mode 100644
index 0000000..7bfc22a
--- /dev/null
+++ b/FS/FS/pay_batch/BoM.pm
@@ -0,0 +1,73 @@
+package FS::pay_batch::BoM;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local 'timelocal';
+use FS::Conf;
+
+my $conf;
+my ($origid, $datacenter, $typecode, $shortname, $longname, $mybank, $myacct);
+
+$name = 'BoM';
+
+%import_info = (
+ 'filetype' => 'CSV',
+ 'fields' => [],
+ 'hook' => sub { die "Can't import BoM" },
+ 'approved' => sub { 1 },
+ 'declined' => sub { 0 },
+);
+
+%export_info = (
+ init => sub {
+ $conf = shift;
+ ($origid,
+ $datacenter,
+ $typecode,
+ $shortname,
+ $longname,
+ $mybank,
+ $myacct) = $conf->config("batchconfig-BoM");
+ },
+ header => sub {
+ my $pay_batch = shift;
+ sprintf( "A%10s%04u%06u%05u%54s\n",
+ $origid,
+ $pay_batch->batchnum,
+ jdate($pay_batch->download),
+ $datacenter,
+ "") .
+ sprintf( "XD%03u%06u%-15s%-30s%09u%-12s \n",
+ $typecode,
+ jdate($pay_batch->download),
+ $shortname,
+ $longname,
+ $mybank,
+ $myacct);
+ },
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+ my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+ sprintf( "D%010.0f%09u%-12s%-29s%-19s\n",
+ $cust_pay_batch->amount * 100,
+ $aba,
+ $account,
+ $cust_pay_batch->payname,
+ $cust_pay_batch->paybatchnum
+ );
+ },
+ footer => sub {
+ my ($pay_batch, $batchcount, $batchtotal) = @_;
+ sprintf( "YD%08u%014.0f%56s\n", $batchcount, $batchtotal*100, "").
+ sprintf( "Z%014u%04u%014u%05u%41s\n",
+ $batchtotal*100, $batchcount, "0", "0", "");
+ },
+);
+
+sub jdate {
+ my (@date) = localtime(shift);
+ sprintf("%03d%03d", $date[5] % 100, $date[7] + 1);
+}
+
+1;
+
diff --git a/FS/FS/pay_batch/PAP.pm b/FS/FS/pay_batch/PAP.pm
new file mode 100644
index 0000000..432ef07
--- /dev/null
+++ b/FS/FS/pay_batch/PAP.pm
@@ -0,0 +1,103 @@
+package FS::pay_batch::PAP;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local 'timelocal';
+use FS::Conf;
+
+my $conf;
+my ($origid, $datacenter, $typecode, $shortname, $longname, $mybank, $myacct);
+
+$name = 'PAP';
+
+%import_info = (
+ 'filetype' => 'fixed',
+ 'formatre' => '^(.).{19}(.{4})(.{3})(.{10})(.{6})(.{9})(.{12}).{110}(.{19}).{71}$',
+ 'fields' => [
+ 'recordtype',
+ 'batchnum',
+ 'datacenter',
+ 'paid',
+ '_date',
+ 'bank',
+ 'payinfo',
+ 'paybatchnum',
+ ],
+ 'hook' => sub {
+ my $hash = shift;
+ $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100 );
+ my $tmpdate = timelocal( 0,0,1,1,0,substr($hash->{'_date'}, 0, 3)+2000);
+ $tmpdate += 86400*(substr($hash->{'_date'}, 3, 3)-1) ;
+ $hash->{'_date'} = $tmpdate;
+ $hash->{'payinfo'} = $hash->{'payinfo'} . '@' . $hash->{'bank'};
+ },
+ 'approved' => sub { 1 },
+ 'declined' => sub { 0 },
+# Why does pay_batch.pm have approved_condition and declined_condition?
+# It doesn't even try to handle the case of neither condition being met.
+ 'end_hook' => sub {
+ my( $hash, $total) = @_;
+ $total = sprintf("%.2f", $total);
+ my $batch_total = $hash->{'datacenter'}.$hash->{'paid'}.
+ substr($hash->{'_date'},0,1); # YUCK!
+ $batch_total = sprintf("%.2f", $batch_total / 100 );
+ return "Our total $total does not match bank total $batch_total!"
+ if $total != $batch_total;
+ '';
+ },
+ 'end_condition' => sub {
+ my $hash = shift;
+ $hash->{recordtype} eq 'W';
+ },
+);
+
+%export_info = (
+ init => sub {
+ $conf = shift;
+ ($origid,
+ $datacenter,
+ $typecode,
+ $shortname,
+ $longname,
+ $mybank,
+ $myacct) = $conf->config("batchconfig-PAP");
+ },
+ header => sub {
+ my $pay_batch = shift;
+ sprintf( "H%10sD%3s%06u%-15s%09u%-12s%04u%19s\n",
+ $origid,
+ $typecode,
+ cdate($pay_batch->download),
+ $shortname,
+ $mybank,
+ $myacct,
+ $pay_batch->batchnum,
+ "" )
+ },
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+ my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+ sprintf( "D%-23s%06u%-19s%09u%-12s%010.0f\n",
+ $cust_pay_batch->payname,
+ cdate($pay_batch->download),
+ $cust_pay_batch->paybatchnum,
+ $aba,
+ $account,
+ $cust_pay_batch->amount*100 );
+ },
+ footer => sub {
+ my ($pay_batch, $batchcount, $batchtotal) = @_;
+ sprintf( "T%08u%014.0f%57s\n",
+ $batchcount,
+ $batchtotal*100,
+ "" );
+ },
+);
+
+sub cdate {
+ my (@date) = localtime(shift);
+ sprintf("%02d%02d%02d", $date[3], $date[4] + 1, $date[5] % 100);
+}
+
+1;
+
diff --git a/FS/FS/pay_batch/ach_spiritone.pm b/FS/FS/pay_batch/ach_spiritone.pm
new file mode 100644
index 0000000..bd3bb14
--- /dev/null
+++ b/FS/FS/pay_batch/ach_spiritone.pm
@@ -0,0 +1,65 @@
+package FS::pay_batch::ach_spiritone;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local 'timelocal';
+use FS::Conf;
+use File::Temp;
+
+my $conf;
+my ($origid, $datacenter, $typecode, $shortname, $longname, $mybank, $myacct);
+
+$name = 'ach-spiritone'; # note spelling
+
+%import_info = (
+ 'filetype' => 'CSV',
+ 'fields' => [
+ '', #name
+ 'paybatchnum',
+ 'aba',
+ 'payinfo',
+ '', #transaction type
+ 'paid',
+ '', #default transaction type
+ '', #default amount
+ ],
+ 'hook' => sub {
+ my $hash = shift;
+ $hash->{'_date'} = time;
+ $hash->{'payinfo'} = $hash->{'payinfo'} . '@' . $hash->{'aba'};
+ },
+ 'approved' => sub { 1 },
+ 'declined' => sub { 0 },
+);
+
+%export_info = (
+# This is the simplest case.
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+ my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+ my $payname = $cust_pay_batch->first . ' ' . $cust_pay_batch->last;
+ $payname =~ tr/",/ /;
+ qq!"$payname","!.$cust_pay_batch->paybatchnum.
+ qq!","$aba","$account","27","!.$cust_pay_batch->amount.
+ qq!","27","0.00"!; #"
+ },
+ autopost => sub {
+ my ($pay_batch, $batch) = @_;
+ my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
+ my $fh = new File::Temp(
+ TEMPLATE => 'paybatch.'. $pay_batch->batchnum .'.XXXXXXXX',
+ DIR => $dir,
+ ) or return "can't open temp file: $!\n";
+
+ print $fh $batch;
+ seek $fh, 0, 0;
+
+ my $error = $pay_batch->import_results( 'filehandle' => $fh,
+ 'format' => $name,
+ );
+ return $error if $error;
+ },
+);
+
+1;
+
diff --git a/FS/FS/pay_batch/chase_canada.pm b/FS/FS/pay_batch/chase_canada.pm
new file mode 100644
index 0000000..909e4ae
--- /dev/null
+++ b/FS/FS/pay_batch/chase_canada.pm
@@ -0,0 +1,104 @@
+package FS::pay_batch::chase_canada;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local 'timelocal';
+use FS::Conf;
+
+my $conf;
+my $origid;
+
+$name = 'csv-chase_canada-E-xactBatch';
+
+%import_info = (
+ 'filetype' => 'CSV',
+ 'fields' => [
+ '',
+ '',
+ '',
+ 'paid',
+ 'auth',
+ 'payinfo',
+ '',
+ '',
+ 'bankcode',
+ 'bankmess',
+ 'etgcode',
+ 'etgmess',
+ '',
+ 'paybatchnum',
+ '',
+ 'result',
+ ],
+ 'hook' => sub {
+ my $hash = shift;
+ my $cpb = shift;
+ $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} );
+ $hash->{'_date'} = time;
+ $hash->{'payinfo'} = $cpb->{'payinfo'}
+ if( substr($hash->{'payinfo'}, -4) eq substr($cpb->{'payinfo'}, -4) );
+ },
+ 'approved' => sub {
+ my $hash = shift;
+ $hash->{'etgcode'} eq '00' && $hash->{'result'} eq 'Approved';
+ },
+ 'declined' => sub {
+ my $hash = shift;
+ $hash->{'etgcode'} ne '00' || $hash->{'result'} eq 'Declined';
+ },
+);
+
+%export_info = (
+ init => sub {
+ $conf = shift;
+ ($origid) = $conf->config("batchconfig-$name");
+ },
+ header => sub {
+ my $pay_batch = shift;
+ sprintf( '$$E-xactBatchFileV1.0$$%s:%03u$$%s',
+ sdate($pay_batch->download),
+ $pay_batch->batchnum,
+ $origid );
+ },
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+ my $payname = $cust_pay_batch->payname;
+ $payname =~ tr/",/ /;
+
+ join(',',
+ $cust_pay_batch->paybatchnum,
+ $cust_pay_batch->custnum,
+ $cust_pay_batch->invnum,
+ qq!"$payname"!,
+ '00',
+ $cust_pay_batch->payinfo,
+ $cust_pay_batch->amount,
+ expdate($cust_pay_batch->exp),
+ '',
+ ''
+ );
+ },
+ # no footer
+);
+
+sub sdate {
+ my (@date) = localtime(shift);
+ sprintf('%02d/%02d/%02d', $date[5] % 100, $date[4] + 1, $date[3]);
+}
+
+sub expdate {
+ my $exp = shift;
+ $exp =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ my ($mon, $y) = ($2, $1);
+ if($conf->exists('batch-increment_expiration')) {
+ my ($curmon, $curyear) = (localtime(time))[4,5];
+ $curmon++;
+ $curyear -= 100;
+ $y++ while $y < $curyear || ($y == $curyear && $mon < $curmon);
+ }
+ $mon = "0$mon" if $mon =~ /^\d$/;
+ $y = "0$y" if $y =~ /^\d$/;
+ return "$mon$y";
+}
+
+1;
diff --git a/FS/FS/pay_batch/paymentech.pm b/FS/FS/pay_batch/paymentech.pm
new file mode 100644
index 0000000..44fa78a
--- /dev/null
+++ b/FS/FS/pay_batch/paymentech.pm
@@ -0,0 +1,114 @@
+package FS::pay_batch::paymentech;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local;
+use Date::Format 'time2str';
+use Date::Parse 'str2time';
+use FS::Conf;
+
+my $conf;
+my ($bin, $merchantID, $terminalID, $username);
+$name = 'paymentech';
+
+%import_info = (
+ filetype => 'XML',
+ xmlrow => [ qw(transResponse newOrderResp) ],
+ fields => [
+ 'paybatchnum',
+ '_date',
+ 'approvalStatus',
+ ],
+ xmlkeys => [
+ 'orderID',
+ 'respDateTime',
+ 'approvalStatus',
+ ],
+ 'hook' => sub {
+ my ($hash, $oldhash) = @_;
+ my ($mon, $day, $year, $hour, $min, $sec) =
+ $hash->{'_date'} =~ /^(..)(..)(....)(..)(..)(..)$/;
+ $hash->{'_date'} = timelocal($sec, $min, $hour, $day, $mon-1, $year);
+ $hash->{'paid'} = $oldhash->{'amount'};
+ },
+ 'approved' => sub { my $hash = shift;
+ $hash->{'approvalStatus'}
+ },
+ 'declined' => sub { my $hash = shift;
+ ! $hash->{'approvalStatus'}
+ },
+);
+
+my %paytype = (
+ 'personal checking' => 'C',
+ 'personal savings' => 'S',
+ 'business checking' => 'X',
+ 'business savings' => 'X',
+ );
+
+%export_info = (
+ init => sub {
+# Load this at run time
+ eval "use XML::Simple";
+ die $@ if $@;
+ my $conf = shift;
+ ($bin, $terminalID, $merchantID, $username) =
+ $conf->config('batchconfig-paymentech');
+ },
+# Here we do all the work in the header function.
+ header => sub {
+ my $pay_batch = shift;
+ my @cust_pay_batch = @{(shift)};
+ my $count = 0;
+ XML::Simple::XMLout( {
+ transRequest => {
+ RequestCount => scalar(@cust_pay_batch),
+ batchFileID => {
+ userID => $username,
+ fileDateTime => time2str('%Y%m%d%H%M%s',time),
+ fileID => 'batch'.time2str('%Y%m%d',time),
+ },
+ newOrder => [ map { {
+ # $_ here refers to a cust_pay_batch record.
+ BatchRequestNo => $count++,
+ industryType => 'EC',
+ transType => 'AC',
+ bin => $bin,
+ merchantID => $merchantID,
+ terminalID => $terminalID,
+ ($_->payby eq 'CARD') ? (
+ # Credit card stuff
+ ccAccountNum => $_->payinfo,
+ ccExp => time2str('%y%m',str2time($_->exp)),
+ ) : (
+ # ECP (electronic check) stuff
+ ecpCheckRT => ($_->payinfo =~ /@(\d+)/),
+ ecpCheckDDA => ($_->payinfo =~ /(\d+)@/),
+ ecpBankAcctType => $paytype{lc($_->cust_main->paytype)},
+ ecpDelvMethod => 'B'
+ ),
+ avsZip => $_->zip,
+ avsAddress1 => $_->address1,
+ avsAddress2 => $_->address2,
+ avsCity => $_->city,
+ avsState => $_->state,
+ avsName => $_->first . ' ' . $_->last,
+ avsCountryCode => $_->country,
+ orderID => $_->paybatchnum,
+ amount => $_->amount * 100,
+ } } @cust_pay_batch
+ ],
+ endOfDay => {
+ BatchRequestNo => $count++,
+ bin => $bin,
+ merchantID => $merchantID,
+ terminalID => $terminalID
+ },
+ }
+ }, KeepRoot => 1, NoAttr => 1);
+ },
+ row => sub {},
+);
+
+1;
+
diff --git a/FS/FS/pay_batch/td_canada_trust.pm b/FS/FS/pay_batch/td_canada_trust.pm
new file mode 100644
index 0000000..43b9237
--- /dev/null
+++ b/FS/FS/pay_batch/td_canada_trust.pm
@@ -0,0 +1,104 @@
+package FS::pay_batch::td_canada_trust;
+
+# Formerly known as csv-td_canada_trust-merchant_pc_batch,
+# which I'm sure we can all agree is both a terrible name
+# and an illegal Perl identifier.
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Time::Local 'timelocal';
+use FS::Conf;
+
+my $conf;
+my ($origid, $datacenter, $typecode, $shortname, $longname, $mybank, $myacct);
+
+$name = 'csv-td_canada_trust-merchant_pc_batch';
+
+%import_info = (
+ 'filetype' => 'CSV',
+ 'fields' => [
+ 'paybatchnum',
+ 'paid',
+ '', # card type
+ '_date',
+ 'time',
+ 'payinfo',
+ '', # expiry date
+ '', # auth number
+ 'type', # transaction type
+ 'result', # processing result
+ '', # terminal ID
+ ],
+ 'hook' => sub {
+ my $hash = shift;
+ my $date = $hash->{'_date'};
+ my $time = $hash->{'time'};
+ $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100);
+ $hash->{'_date'} = timelocal( substr($time, 4, 2),
+ substr($time, 2, 2),
+ substr($time, 0, 2),
+ substr($date, 6, 2),
+ substr($date, 4, 2)-1,
+ substr($date, 0, 4)-1900 );
+ },
+ 'approved' => sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && $hash->{'result'} == 3
+ },
+ 'declined' => sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && ( $hash->{'result'} == 4
+ || $hash->{'result'} == 5 )
+ },
+ 'end_condition' => sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0BC';
+ },
+ 'end_hook' => sub {
+ my ($hash, $total) = @_;
+ $total = sprintf("%.2f", $total);
+ my $batch_total = sprintf("%.2f", $hash->{'paybatchnum'} / 100);
+ return "Our total $total does not match bank total $batch_total!"
+ if $total != $batch_total;
+ },
+);
+
+%export_info = (
+ init => sub {
+ $conf = shift;
+ },
+ # no header
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+
+ return join(',',
+ '',
+ '',
+ '',
+ '',
+ $cust_pay_batch->payinfo,
+ expdate($cust_pay_batch->exp),
+ $cust_pay_batch->amount,
+ $cust_pay_batch->paybatchnum
+ );
+ },
+# no footer
+);
+
+sub expdate {
+ my $exp = shift;
+ $exp =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ my ($mon, $y) = ($2, $1);
+ if($conf->exists('batch-increment_expiration')) {
+ my ($curmon, $curyear) = (localtime(time))[4,5];
+ $curmon++;
+ $curyear -= 100;
+ $y++ while $y < $curyear || ($y == $curyear && $mon < $curmon);
+ }
+ $mon = "0$mon" if $mon =~ /^\d$/;
+ $y = "0$y" if $y =~ /^\d$/;
+ return "$mon$y";
+}
+
+1;
+
diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm
index b54e5d9..30a03dd 100644
--- a/FS/FS/payby.pm
+++ b/FS/FS/payby.pm
@@ -48,28 +48,33 @@ tie %hash, 'Tie::IxHash',
tinyname => 'card',
shortname => 'Credit card',
longname => 'Credit card (automatic)',
+ realtime => 1,
},
'DCRD' => {
tinyname => 'card',
shortname => 'Credit card',
longname => 'Credit card (on-demand)',
cust_pay => 'CARD', #this is a customer type only, payments are CARD...
+ realtime => 1,
},
'CHEK' => {
tinyname => 'check',
shortname => 'Electronic check',
longname => 'Electronic check (automatic)',
+ realtime => 1,
},
'DCHK' => {
tinyname => 'check',
shortname => 'Electronic check',
longname => 'Electronic check (on-demand)',
cust_pay => 'CHEK', #this is a customer type only, payments are CHEK...
+ realtime => 1,
},
'LECB' => {
tinyname => 'phone bill',
shortname => 'Phone bill billing',
longname => 'Phone bill billing',
+ realtime => 1,
},
'BILL' => {
tinyname => 'billing',
@@ -131,6 +136,15 @@ sub can_payby {
return 1;
}
+sub realtime { # can use realtime payment facilities
+ my( $self, $payby ) = @_;
+
+ return 0 unless $hash{$payby};
+ return 0 unless exists( $hash{$payby}->{realtime} );
+
+ return $hash{$payby}->{realtime};
+}
+
sub payby2longname {
my $self = shift;
map { $_ => $hash{$_}->{longname} } $self->payby;
@@ -157,6 +171,7 @@ sub longname {
%payby2bop = (
'CARD' => 'CC',
'CHEK' => 'ECHECK',
+ 'MCRD' => 'CC',
);
sub payby2bop {
diff --git a/FS/FS/payment_gateway.pm b/FS/FS/payment_gateway.pm
index 35b4f08..bc8b875 100644
--- a/FS/FS/payment_gateway.pm
+++ b/FS/FS/payment_gateway.pm
@@ -1,12 +1,14 @@
package FS::payment_gateway;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $me $DEBUG );
use FS::Record qw( qsearch qsearchs dbh );
use FS::option_Common;
use FS::agent_payment_gateway;
@ISA = qw( FS::option_Common );
+$me = '[ FS::payment_gateway ]';
+$DEBUG=0;
=head1 NAME
@@ -37,6 +39,8 @@ currently supported:
=item gatewaynum - primary key
+=item gateway_namespace - Business::OnlinePayment or Business::OnlineThirdPartyPayment
+
=item gateway_module - Business::OnlinePayment:: module name
=item gateway_username - payment gateway username
@@ -110,8 +114,12 @@ sub check {
my $error =
$self->ut_numbern('gatewaynum')
|| $self->ut_alpha('gateway_module')
+ || $self->ut_enum('gateway_namespace', ['Business::OnlinePayment',
+ 'Business::OnlineThirdPartyPayment',
+ ] )
|| $self->ut_textn('gateway_username')
|| $self->ut_anything('gateway_password')
+ || $self->ut_textn('gateway_callback_url') # a bit too permissive
|| $self->ut_enum('disabled', [ '', 'Y' ] )
#|| $self->ut_textn('gateway_action')
;
@@ -131,6 +139,10 @@ sub check {
$self->gateway_action('Normal Authorization');
}
+ # this little kludge mimics FS::CGI::popurl
+ $self->gateway_callback_url($self->gateway_callback_url. '/')
+ if ( $self->gateway_callback_url && $self->gateway_callback_url !~ /\/$/ );
+
$self->SUPER::check;
}
@@ -186,6 +198,41 @@ sub disable {
}
+=item namespace_description
+
+returns a friendly name for the namespace
+
+=cut
+
+my %namespace2description = (
+ '' => 'Direct',
+ 'Business::OnlinePayment' => 'Direct',
+ 'Business::OnlineThirdPartyPayment' => 'Hosted',
+);
+
+sub namespace_description {
+ $namespace2description{shift->gateway_namespace} || 'Unknown';
+}
+
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+#
+#
+
+sub _upgrade_data {
+ my ($class, %opts) = @_;
+ my $dbh = dbh;
+
+ warn "$me upgrading $class\n" if $DEBUG;
+
+ foreach ( qsearch( 'payment_gateway', { 'gateway_namespace' => '' } ) ) {
+ $_->gateway_namespace('Business::OnlinePayment'); #defaulting
+ my $error = $_->replace;
+ die "$class had error during upgrade replacement: $error" if $error;
+ }
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/phone_device.pm b/FS/FS/phone_device.pm
new file mode 100644
index 0000000..1bdbc34
--- /dev/null
+++ b/FS/FS/phone_device.pm
@@ -0,0 +1,240 @@
+package FS::phone_device;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( dbh qsearchs ); # qsearch );
+use FS::part_device;
+use FS::svc_phone;
+
+=head1 NAME
+
+FS::phone_device - Object methods for phone_device records
+
+=head1 SYNOPSIS
+
+ use FS::phone_device;
+
+ $record = new FS::phone_device \%hash;
+ $record = new FS::phone_device { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::phone_device object represents a specific customer phone device, such as
+a SIP phone or ATA. FS::phone_device inherits from FS::Record. The following
+fields are currently supported:
+
+=over 4
+
+=item devicenum
+
+primary key
+
+=item devicepart
+
+devicepart
+
+=item svcnum
+
+svcnum
+
+=item mac_addr
+
+mac_addr
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'phone_device'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $self->svc_phone->export('device_insert', $self); #call device export
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+}
+
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ $self->svc_phone->export('device_delete', $self); #call device export
+
+ my $error = $self->SUPER::delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+}
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+sub replace {
+ my $new = shift;
+
+ my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
+ ? shift
+ : $new->replace_old;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $new->SUPER::replace($old);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $new->svc_phone->export('device_replace', $new, $old); #call device export
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+}
+
+=item check
+
+Checks all fields to make sure this is a valid record. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+ my $self = shift;
+
+ my $mac = $self->mac_addr;
+ $mac =~ s/\s+//g;
+ $mac =~ s/://g;
+ $self->mac_addr($mac);
+
+ my $error =
+ $self->ut_numbern('devicenum')
+ || $self->ut_foreign_key('devicepart', 'part_device', 'devicepart')
+ || $self->ut_foreign_key('svcnum', 'svc_phone', 'svcnum' ) #cust_svc?
+ || $self->ut_hexn('mac_addr')
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=item part_device
+
+Returns the device type record (see L<FS::part_device>) associated with this
+customer device.
+
+=cut
+
+sub part_device {
+ my $self = shift;
+ qsearchs( 'part_device', { 'devicepart' => $self->devicepart } );
+}
+
+=item svc_phone
+
+Returns the phone number (see L<FS::svc_phone>) associated with this customer
+device.
+
+=cut
+
+sub svc_phone {
+ my $self = shift;
+ qsearchs( 'svc_phone', { 'svcnum' => $self->svcnum } );
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/pkg_category.pm b/FS/FS/pkg_category.pm
index 69578c9..0beaf1c 100644
--- a/FS/FS/pkg_category.pm
+++ b/FS/FS/pkg_category.pm
@@ -1,11 +1,13 @@
package FS::pkg_category;
use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch );
+use vars qw( @ISA $me $DEBUG );
+use FS::Record qw( qsearch dbh );
use FS::part_pkg;
@ISA = qw( FS::Record );
+$DEBUG = 0;
+$me = '[FS::pkg_category]';
=head1 NAME
@@ -95,10 +97,39 @@ sub check {
$self->ut_numbern('categorynum')
or $self->ut_text('categoryname')
+ or $self->ut_snumber('weight')
or $self->SUPER::check;
}
+# _ upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+#
+#
+
+sub _upgrade_data {
+ my ($class, %opts) = @_;
+ my $dbh = dbh;
+
+ warn "$me upgrading $class\n" if $DEBUG;
+
+ my @pkg_category =
+ qsearch('pkg_category', { weight => { op => '!=', value => '' } } );
+
+ unless( scalar(@pkg_category) ) {
+ my @pkg_category = qsearch('pkg_category', {} );
+ my $weight = 0;
+ foreach ( sort { $a->description cmp $b->description } @pkg_category ) {
+ $_->weight($weight);
+ my $error = $_->replace;
+ die "error setting pkg_category weight: $error\n" if $error;
+ $weight += 10;
+ }
+ }
+ '';
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/queue.pm b/FS/FS/queue.pm
index 381e418..1f2abe3 100644
--- a/FS/FS/queue.pm
+++ b/FS/FS/queue.pm
@@ -3,6 +3,8 @@ package FS::queue;
use strict;
use vars qw( @ISA @EXPORT_OK $DEBUG $conf $jobnums);
use Exporter;
+use MIME::Base64;
+use Storable qw( nfreeze thaw );
use FS::UID qw(myconnect);
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
@@ -142,9 +144,11 @@ sub insert {
}
foreach my $arg ( @args ) {
+ my $freeze = ref($arg) ? 'Y' : '';
my $queue_arg = new FS::queue_arg ( {
'jobnum' => $self->jobnum,
- 'arg' => $arg,
+ 'frozen' => $freeze,
+ 'arg' => $freeze ? encode_base64(nfreeze($arg)) : $arg,# always freeze?
} );
$error = $queue_arg->insert;
if ( $error ) {
@@ -254,11 +258,12 @@ Returns a list of the arguments associated with this job.
sub args {
my $self = shift;
- map $_->arg, qsearch( 'queue_arg',
- { 'jobnum' => $self->jobnum },
- '',
- 'ORDER BY argnum'
- );
+ map { $_->frozen ? thaw(decode_base64($_->arg)) : $_->arg }
+ qsearch( 'queue_arg',
+ { 'jobnum' => $self->jobnum },
+ '',
+ 'ORDER BY argnum'
+ );
}
=item cust_svc
diff --git a/FS/FS/queue_arg.pm b/FS/FS/queue_arg.pm
index c96ff12..8e9a10d 100644
--- a/FS/FS/queue_arg.pm
+++ b/FS/FS/queue_arg.pm
@@ -36,6 +36,8 @@ FS::Record. The following fields are currently supported:
=item jobnum - see L<FS::queue>
+=item frozen - argument is frozen with Storable
+
=item arg - argument
=back
@@ -96,6 +98,7 @@ sub check {
my $error =
$self->ut_numbern('argnum')
|| $self->ut_numbern('jobnum')
+ || $self->ut_enum('frozen', [ '', 'Y' ])
|| $self->ut_anything('arg')
;
return $error if $error;
diff --git a/FS/FS/rate_detail.pm b/FS/FS/rate_detail.pm
index 62c0fa1..b7b23ba 100644
--- a/FS/FS/rate_detail.pm
+++ b/FS/FS/rate_detail.pm
@@ -1,14 +1,17 @@
package FS::rate_detail;
use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
+use vars qw( @ISA $DEBUG $me );
+use FS::Record qw( qsearch qsearchs dbh );
use FS::rate;
use FS::rate_region;
use Tie::IxHash;
@ISA = qw(FS::Record);
+$DEBUG = 0;
+$me = '[FS::rate_detail]';
+
=head1 NAME
FS::rate_detail - Object methods for rate_detail records
@@ -229,6 +232,344 @@ sub granularities {
%granularities;
}
+use Storable qw(thaw);
+use Data::Dumper;
+use MIME::Base64;
+sub process_edit_import {
+ my $job = shift;
+
+ #do we actually belong in rate_detail, like 'table' says? even though we
+ # can possible create new rate records, that's a side effect, mostly we
+ # do edit rate_detail records in batch...
+
+ my $opt = { 'table' => 'rate_detail',
+ 'params' => [], #required, apparantly
+ 'formats' => { 'default' => [
+ 'dest_regionnum',
+ '', #regionname
+ '', #country
+ '', #prefixes
+ #loop these
+ 'min_included',
+ 'min_charge',
+ sub {
+ my( $rate_detail, $g ) = @_;
+ $g = 0 if $g =~ /^\s*(per-)?call\s*$/i;
+ $g = 60 if $g =~ /^\s*minute\s*$/i;
+ $g =~ /^(\d+)/ or die "can't parse granularity: $g".
+ " for record ". Dumper($rate_detail);
+ $rate_detail->sec_granularity($1);
+ },
+ 'classnum',
+ ] },
+ 'format_headers' => { 'default' => 1, },
+ 'format_types' => { 'default' => 'xls' },
+ };
+
+ #false laziness w/
+ #FS::Record::process_batch_import( $job, $opt, @_ );
+
+ my $table = $opt->{table};
+ my @pass_params = @{ $opt->{params} };
+ my %formats = %{ $opt->{formats} };
+
+ my $param = thaw(decode_base64(shift));
+ warn Dumper($param) if $DEBUG;
+
+ my $files = $param->{'uploaded_files'}
+ or die "No files provided.\n";
+
+ my (%files) = map { /^(\w+):([\.\w]+)$/ ? ($1,$2):() } split /,/, $files;
+
+ my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc. '/';
+ my $file = $dir. $files{'file'};
+
+ my $error =
+ #false laziness w/
+ #FS::Record::batch_import( {
+ FS::rate_detail::edit_import( {
+ #class-static
+ table => $table,
+ formats => \%formats,
+ format_types => $opt->{format_types},
+ format_headers => $opt->{format_headers},
+ format_sep_chars => $opt->{format_sep_chars},
+ format_fixedlength_formats => $opt->{format_fixedlength_formats},
+ #per-import
+ job => $job,
+ file => $file,
+ #type => $type,
+ format => $param->{format},
+ params => { map { $_ => $param->{$_} } @pass_params },
+ #?
+ default_csv => $opt->{default_csv},
+ } );
+
+ unlink $file;
+
+ die "$error\n" if $error;
+
+}
+
+#false laziness w/ #FS::Record::batch_import, grep "edit_import" for differences
+#could be turned into callbacks or something
+use Text::CSV_XS;
+sub edit_import {
+ my $param = shift;
+
+ warn "$me edit_import call with params: \n". Dumper($param)
+ if $DEBUG;
+
+ my $table = $param->{table};
+ my $formats = $param->{formats};
+
+ my $job = $param->{job};
+ my $file = $param->{file};
+ my $format = $param->{'format'};
+ my $params = $param->{params} || {};
+
+ die "unknown format $format" unless exists $formats->{ $format };
+
+ my $type = $param->{'format_types'}
+ ? $param->{'format_types'}{ $format }
+ : $param->{type} || 'csv';
+
+ unless ( $type ) {
+ if ( $file =~ /\.(\w+)$/i ) {
+ $type = lc($1);
+ } else {
+ #or error out???
+ warn "can't parse file type from filename $file; defaulting to CSV";
+ $type = 'csv';
+ }
+ $type = 'csv'
+ if $param->{'default_csv'} && $type ne 'xls';
+ }
+
+ my $header = $param->{'format_headers'}
+ ? $param->{'format_headers'}{ $param->{'format'} }
+ : 0;
+
+ my $sep_char = $param->{'format_sep_chars'}
+ ? $param->{'format_sep_chars'}{ $param->{'format'} }
+ : ',';
+
+ my $fixedlength_format =
+ $param->{'format_fixedlength_formats'}
+ ? $param->{'format_fixedlength_formats'}{ $param->{'format'} }
+ : '';
+
+ my @fields = @{ $formats->{ $format } };
+
+ my $row = 0;
+ my $count;
+ my $parser;
+ my @buffer = ();
+ my @header = (); #edit_import
+ if ( $type eq 'csv' || $type eq 'fixedlength' ) {
+
+ if ( $type eq 'csv' ) {
+
+ my %attr = ();
+ $attr{sep_char} = $sep_char if $sep_char;
+ $parser = new Text::CSV_XS \%attr;
+
+ } elsif ( $type eq 'fixedlength' ) {
+
+ eval "use Parse::FixedLength;";
+ die $@ if $@;
+ $parser = new Parse::FixedLength $fixedlength_format;
+
+ } else {
+ die "Unknown file type $type\n";
+ }
+
+ @buffer = split(/\r?\n/, slurp($file) );
+ splice(@buffer, 0, ($header || 0) );
+ $count = scalar(@buffer);
+
+ } elsif ( $type eq 'xls' ) {
+
+ eval "use Spreadsheet::ParseExcel;";
+ die $@ if $@;
+
+ eval "use DateTime::Format::Excel;";
+ #for now, just let the error be thrown if it is used, since only CDR
+ # formats bill_west and troop use it, not other excel-parsing things
+ #die $@ if $@;
+
+ my $excel = Spreadsheet::ParseExcel::Workbook->new->Parse($file);
+
+ $parser = $excel->{Worksheet}[0]; #first sheet
+
+ $count = $parser->{MaxRow} || $parser->{MinRow};
+ $count++;
+
+ $row = $header || 0;
+
+ #edit_import - need some magic to parse the header
+ if ( $header ) {
+ my @header_row = @{ $parser->{Cells}[$0] };
+ @header = map $_->{Val}, @header_row;
+ }
+
+ } else {
+ die "Unknown file type $type\n";
+ }
+
+ #my $columns;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ #edit_import - use the header to setup looping over different rates
+ my @rate = ();
+ if ( @header ) {
+ splice(@header,0,4); # # Region Country Prefixes
+ while ( my @next = splice(@header,0,4) ) {
+ my $rate;
+ if ( $next[0] =~ /^(\d+):\s*([^:]+):/ ) {
+ $rate = qsearchs('rate', { 'ratenum' => $1 } )
+ or die "unknown ratenum $1";
+ } elsif ( $next[0] =~ /^(NEW:)?\s*([^:]+)/i ) {
+ $rate = new FS::rate { 'ratename' => $2 };
+ my $error = $rate->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error inserting new rate: $error\n";
+ }
+ }
+ push @rate, $rate;
+ }
+ }
+ die unless @rate;
+
+ my $line;
+ my $imported = 0;
+ my( $last, $min_sec ) = ( time, 5 ); #progressbar foo
+ while (1) {
+
+ my @columns = ();
+ if ( $type eq 'csv' ) {
+
+ last unless scalar(@buffer);
+ $line = shift(@buffer);
+
+ $parser->parse($line) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $parser->error_input();
+ };
+ @columns = $parser->fields();
+
+ } elsif ( $type eq 'fixedlength' ) {
+
+ @columns = $parser->parse($line);
+
+ } elsif ( $type eq 'xls' ) {
+
+ last if $row > ($parser->{MaxRow} || $parser->{MinRow})
+ || ! $parser->{Cells}[$row];
+
+ my @row = @{ $parser->{Cells}[$row] };
+ @columns = map $_->{Val}, @row;
+
+ #my $z = 'A';
+ #warn $z++. ": $_\n" for @columns;
+
+ } else {
+ die "Unknown file type $type\n";
+ }
+
+ #edit_import loop
+
+ my @repeat = @columns[0..3];
+
+ foreach my $rate ( @rate ) {
+
+ my @later = ();
+ my %hash = %$params;
+
+ foreach my $field ( @fields ) {
+
+ my $value = shift @columns;
+
+ if ( ref($field) eq 'CODE' ) {
+ #&{$field}(\%hash, $value);
+ push @later, $field, $value;
+ #} else {
+ } elsif ($field) { #edit_import
+ #??? $hash{$field} = $value if length($value);
+ $hash{$field} = $value if defined($value) && length($value);
+ }
+
+ }
+
+ unshift @columns, @repeat; #edit_import put these back on for next time
+
+ my $class = "FS::$table";
+
+ my $record = $class->new( \%hash );
+
+ $record->ratenum($rate->ratenum); #edit_import
+
+ #edit_improt n/a my $param = {};
+ while ( scalar(@later) ) {
+ my $sub = shift @later;
+ my $data = shift @later;
+ #&{$sub}($record, $data, $conf, $param);# $record->&{$sub}($data, $conf);
+ &{$sub}($record, $data); #edit_import - don't have $conf
+ #edit_import wrong loop last if exists( $param->{skiprow} );
+ }
+ #edit_import wrong loop next if exists( $param->{skiprow} );
+
+ #edit_import update or insert, not just insert
+ my $old = qsearchs({
+ 'table' => $table,
+ 'hashref' => { map { $_ => $record->$_() } qw(ratenum dest_regionnum) },
+ });
+
+ my $error;
+ if ( $old ) {
+ $record->ratedetailnum($old->ratedetailnum);
+ $error = $record->replace($old)
+ } else {
+ $record->insert;
+ }
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't insert record". ( $line ? " for $line" : '' ). ": $error";
+ }
+
+ }
+
+ $row++;
+ $imported++;
+
+ if ( $job && time - $min_sec > $last ) { #progress bar
+ $job->update_statustext( int(100 * $imported / $count) );
+ $last = time;
+ }
+
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;;
+
+ return "Empty file!" unless $imported || $param->{empty_ok};
+
+ ''; #no error
+
+}
+
+
=back
diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm
index da1cfe1..8fd5d0d 100644
--- a/FS/FS/svc_Common.pm
+++ b/FS/FS/svc_Common.pm
@@ -1,8 +1,9 @@
package FS::svc_Common;
use strict;
-use vars qw( @ISA $noexport_hack $DEBUG $me );
-use Carp qw( cluck carp croak ); #specify cluck have to specify them all..
+use vars qw( @ISA $noexport_hack $DEBUG $me
+ $overlimit_missing_cust_svc_nonfatal_kludge );
+use Carp qw( cluck carp croak confess ); #specify cluck have to specify them all
use Scalar::Util qw( blessed );
use FS::Record qw( qsearch qsearchs fields dbh );
use FS::cust_main_Mixin;
@@ -18,6 +19,8 @@ use FS::inventory_class;
$me = '[FS::svc_Common]';
$DEBUG = 0;
+$overlimit_missing_cust_svc_nonfatal_kludge = 0;
+
=head1 NAME
FS::svc_Common - Object method for all svc_ records
@@ -151,6 +154,11 @@ sub label {
$self->svcnum;
}
+sub label_long {
+ my $self = shift;
+ $self->label(@_);
+}
+
=item check
Checks the validity of fields in this record.
@@ -793,7 +801,19 @@ Sets or retrieves overlimit date.
sub overlimit {
my $self = shift;
- $self->cust_svc->overlimit(@_);
+ #$self->cust_svc->overlimit(@_);
+ my $cust_svc = $self->cust_svc;
+ unless ( $cust_svc ) { #wtf?
+ my $error = "$me overlimit: missing cust_svc record for svc_acct svcnum ".
+ $self->svcnum;
+ if ( $overlimit_missing_cust_svc_nonfatal_kludge ) {
+ cluck "$error; continuing anyway as requested";
+ return '';
+ } else {
+ confess $error;
+ }
+ }
+ $cust_svc->overlimit(@_);
}
=item cancel
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 6f11051..1b12654 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -6,7 +6,7 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
$usernamemax $passwordmin $passwordmax
$username_ampersand $username_letter $username_letterfirst
$username_noperiod $username_nounderscore $username_nodash
- $username_uppercase $username_percent
+ $username_uppercase $username_percent $username_colon
$password_noampersand $password_noexclamation
$warning_template $warning_from $warning_subject $warning_mimetype
$warning_cc
@@ -15,17 +15,20 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
$dirhash
@saltset @pw_set );
use Scalar::Util qw( blessed );
+use Math::BigInt;
use Carp;
use Fcntl qw(:flock);
use Date::Format;
use Crypt::PasswdMD5 1.2;
use Data::Dumper;
+use Text::Template;
use Authen::Passphrase;
use FS::UID qw( datasrc driver_name );
use FS::Conf;
use FS::Record qw( qsearch qsearchs fields dbh dbdef );
use FS::Msgcat qw(gettext);
use FS::UI::bytecount;
+use FS::part_pkg;
use FS::svc_Common;
use FS::cust_svc;
use FS::part_svc;
@@ -53,7 +56,11 @@ FS::UID->install_callback( sub {
@shells = $conf->config('shells');
$usernamemin = $conf->config('usernamemin') || 2;
$usernamemax = $conf->config('usernamemax');
- $passwordmin = $conf->config('passwordmin') || 6;
+ $passwordmin = $conf->config('passwordmin'); # || 6;
+ #blank->6, keep 0
+ $passwordmin = ( defined($passwordmin) && $passwordmin =~ /\d+/ )
+ ? $passwordmin
+ : 6;
$passwordmax = $conf->config('passwordmax') || 8;
$username_letter = $conf->exists('username-letter');
$username_letterfirst = $conf->exists('username-letterfirst');
@@ -63,6 +70,7 @@ FS::UID->install_callback( sub {
$username_uppercase = $conf->exists('username-uppercase');
$username_ampersand = $conf->exists('username-ampersand');
$username_percent = $conf->exists('username-percent');
+ $username_colon = $conf->exists('username-colon');
$password_noampersand = $conf->exists('password-noexclamation');
$password_noexclamation = $conf->exists('password-noexclamation');
$dirhash = $conf->config('dirhash') || 0;
@@ -212,9 +220,9 @@ sub table_info {
'fields' => {
'dir' => 'Home directory',
'uid' => {
- label => 'UID',
- def_label => 'UID (set to fixed and blank for no UIDs)',
- type => 'text',
+ label => 'UID',
+ def_info => 'set to fixed and blank for no UIDs',
+ type => 'text',
},
'slipip' => 'IP address',
# 'popnum' => qq!<A HREF="$p/browse/svc_acct_pop.cgi/">POP number</A>!,
@@ -241,24 +249,22 @@ sub table_info {
},
'_password' => 'Password',
'gid' => {
- label => 'GID',
- def_label => 'GID (when blank, defaults to UID)',
- type => 'text',
+ label => 'GID',
+ def_info => 'when blank, defaults to UID',
+ type => 'text',
},
'shell' => {
- #desc =>'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file, set to blank for no shell tracking)',
label => 'Shell',
- def_label=> 'Shell (set to blank for no shell tracking)',
- type =>'select',
+ def_info => 'set to blank for no shell tracking',
+ type => 'select',
#select_list => [ $conf->config('shells') ],
select_list => [ $conf ? $conf->config('shells') : () ],
disable_inventory => 1,
disable_select => 1,
},
- 'finger' => 'Real name (GECOS)',
+ 'finger' => 'Real name', # (GECOS)',
'domsvc' => {
label => 'Domain',
- #def_label => 'svcnum from svc_domain',
type => 'select',
select_table => 'svc_domain',
select_key => 'svcnum',
@@ -277,6 +283,7 @@ sub table_info {
type => 'text',
disable_inventory => 1,
disable_select => 1,
+ disable_part_svc_column => 1,
},
'upbytes' => { label => 'Upload',
type => 'text',
@@ -284,6 +291,7 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'downbytes' => { label => 'Download',
type => 'text',
@@ -291,6 +299,7 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'totalbytes'=> { label => 'Total up and download',
type => 'text',
@@ -298,11 +307,13 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'seconds_threshold' => { label => 'Seconds threshold',
type => 'text',
disable_inventory => 1,
disable_select => 1,
+ disable_part_svc_column => 1,
},
'upbytes_threshold' => { label => 'Upload threshold',
type => 'text',
@@ -310,6 +321,7 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'downbytes_threshold' => { label => 'Download threshold',
type => 'text',
@@ -317,6 +329,7 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'totalbytes_threshold'=> { label => 'Total up and download threshold',
type => 'text',
@@ -324,6 +337,7 @@ sub table_info {
disable_select => 1,
'format' => \&FS::UI::bytecount::display_bytecount,
'parse' => \&FS::UI::bytecount::parse_bytecount,
+ disable_part_svc_column => 1,
},
'last_login'=> {
label => 'Last login',
@@ -419,7 +433,13 @@ sub search_sql {
$class->search_sql_field('username', $string ).
' ) ';
} else {
- $class->search_sql_field('username', $string);
+ ' ( '.
+ $class->search_sql_field('username', $string).
+ ( $string =~ /^\d+$/
+ ? 'OR '. $class->search_sql_field('svcnum', $string)
+ : ''
+ ).
+ ' ) ';
}
}
@@ -437,8 +457,26 @@ sub label {
$self->email(@_);
}
+=item label_long [ END_TIMESTAMP [ START_TIMESTAMP ] ]
+
+Returns a longer string label for this acccount ("Real Name <username@domain>"
+if available, or "username@domain").
+
+END_TIMESTAMP and START_TIMESTAMP can optionally be passed when dealing with
+history records.
+
=cut
+sub label_long {
+ my $self = shift;
+ my $label = $self->label(@_);
+ my $finger = $self->finger;
+ return $label unless $finger =~ /\S/;
+ my $maxlen = 40 - length($label) - length($self->cust_svc->part_svc->svc);
+ $finger = substr($finger, 0, $maxlen-3).'...' if length($finger) > $maxlen;
+ "$finger <$label>";
+}
+
=item insert [ , OPTION => VALUE ... ]
Adds this account to the database. If there is an error, returns the error,
@@ -503,6 +541,27 @@ sub insert {
$self->svcpart($cust_svc->svcpart);
}
+ # set usage fields and thresholds if unset but set in a package def
+ if ( $self->pkgnum ) {
+ my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
+ my $part_pkg = $cust_pkg->part_pkg if $cust_pkg;
+ if ( $part_pkg && $part_pkg->can('usage_valuehash') ) {
+
+ my %values = $part_pkg->usage_valuehash;
+ my $multiplier = $conf->exists('svc_acct-usage_threshold')
+ ? 1 - $conf->config('svc_acct-usage_threshold')/100
+ : 0.20; #doesn't matter
+
+ foreach ( keys %values ) {
+ next if $self->getfield($_);
+ $self->setfield( $_, $values{$_} );
+ $self->setfield( $_. '_threshold', int( $values{$_} * $multiplier ) )
+ if $conf->exists('svc_acct-usage_threshold');
+ }
+
+ }
+ }
+
my @jobnums;
$error = $self->SUPER::insert(
'jobnums' => \@jobnums,
@@ -976,13 +1035,28 @@ sub check {
;
return $error if $error;
+ my $cust_pkg;
+ local $username_letter = $username_letter;
+ if ($self->svcnum) {
+ my $cust_svc = $self->cust_svc
+ or return "no cust_svc record found for svcnum ". $self->svcnum;
+ my $cust_pkg = $cust_svc->cust_pkg;
+ }
+ if ($self->pkgnum) {
+ $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $self->pkgnum } );#complain?
+ }
+ if ($cust_pkg) {
+ $username_letter =
+ $conf->exists('username-letter', $cust_pkg->cust_main->agentnum);
+ }
+
my $ulen = $usernamemax || $self->dbdef_table->column('username')->length;
if ( $username_uppercase ) {
- $recref->{username} =~ /^([a-z0-9_\-\.\&\%]{$usernamemin,$ulen})$/i
+ $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:]{$usernamemin,$ulen})$/i
or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
$recref->{username} = $1;
} else {
- $recref->{username} =~ /^([a-z0-9_\-\.\&\%]{$usernamemin,$ulen})$/
+ $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:]{$usernamemin,$ulen})$/
or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
$recref->{username} = $1;
}
@@ -1007,6 +1081,9 @@ sub check {
unless ( $username_percent ) {
$recref->{username} =~ /\%/ and return gettext('illegal_username');
}
+ unless ( $username_colon ) {
+ $recref->{username} =~ /\:/ and return gettext('illegal_username');
+ }
$recref->{popnum} =~ /^(\d*)$/ or return "Illegal popnum: ".$recref->{popnum};
$recref->{popnum} = $1;
@@ -1158,7 +1235,7 @@ sub check {
#carp "warning: _password_encoding unspecified\n";
#generate a password if it is blank
- unless ( length( $recref->{_password} ) ) {
+ unless ( length($recref->{_password}) || ! $passwordmin ) {
$recref->{_password} =
join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) );
@@ -1374,6 +1451,29 @@ sub radius_reply {
$reply{'Session-Timeout'} = $self->seconds;
}
+ if ( $conf->exists('radius-chillispot-max') ) {
+ #http://dev.coova.org/svn/coova-chilli/doc/dictionary.chillispot
+
+ #hmm. just because sqlradius.pm says so?
+ my %whatis = (
+ 'input' => 'up',
+ 'output' => 'down',
+ 'total' => 'total',
+ );
+
+ foreach my $what (qw( input output total )) {
+ my $is = $whatis{$what}.'bytes';
+ if ( $self->$is() =~ /\d/ ) {
+ my $big = new Math::BigInt $self->$is();
+ $big = new Math::BigInt '0' if $big->is_neg();
+ my $att = "Chillispot-Max-\u$what";
+ $reply{"$att-Octets"} = $big->copy->band(0xffffffff)->bstr;
+ $reply{"$att-Gigawords"} = $big->copy->brsft(32)->bstr;
+ }
+ }
+
+ }
+
%reply;
}
@@ -1407,11 +1507,15 @@ sub radius_check {
$check{$pw_attrib} = $password;
my $cust_svc = $self->cust_svc;
- die "FATAL: no cust_svc record for svc_acct.svcnum ". $self->svcnum. "\n"
- unless $cust_svc;
- my $cust_pkg = $cust_svc->cust_pkg;
- if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill ) {
- $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
+ if ( $cust_svc ) {
+ my $cust_pkg = $cust_svc->cust_pkg;
+ if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill ) {
+ $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
+ }
+ } else {
+ warn "WARNING: no cust_svc record for svc_acct.svcnum ". $self->svcnum.
+ "; can't set Expiration\n"
+ unless $cust_svc;
}
%check;
@@ -1659,7 +1763,7 @@ my %op2condition = (
$self->$column - $amount <= 0;
},
'+' => sub { my($self, $column, $amount) = @_;
- $self->$column + $amount > 0;
+ ($self->$column || 0) + $amount > 0;
},
);
my %op2warncondition = (
@@ -1668,7 +1772,7 @@ my %op2warncondition = (
$self->$column - $amount <= $self->$threshold + 0;
},
'+' => sub { my($self, $column, $amount) = @_;
- $self->$column + $amount > 0;
+ ($self->$column || 0) + $amount > 0;
},
);
@@ -1706,6 +1810,38 @@ sub _op_usage {
die "Can't update $column for svcnum". $self->svcnum
if $rv == 0;
+ #$self->snapshot; #not necessary, we retain the old values
+ #create an object with the updated usage values
+ my $new = qsearchs('svc_acct', { 'svcnum' => $self->svcnum });
+ #call exports
+ my $error = $new->replace($self);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error replacing: $error";
+ }
+
+ #overlimit_action eq 'cancel' handling
+ my $cust_pkg = $self->cust_svc->cust_pkg;
+ if ( $cust_pkg
+ && $cust_pkg->part_pkg->option('overlimit_action', 1) eq 'cancel'
+ && $op eq '-' && &{$op2condition{$op}}($self, $column, $amount)
+ )
+ {
+
+ my $error = $cust_pkg->cancel; #XXX should have a reason
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error cancelling: $error";
+ }
+
+ #nothing else is relevant if we're cancelling, so commit & return success
+ warn "$me update successful; committing\n"
+ if $DEBUG;
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return '';
+
+ }
+
my $action = $op2action{$op};
if ( &{$op2condition{$op}}($self, $column, $amount) &&
@@ -1777,7 +1913,7 @@ sub _op_usage {
}
sub set_usage {
- my( $self, $valueref ) = @_;
+ my( $self, $valueref, %options ) = @_;
warn "$me set_usage called for svcnum ". $self->svcnum.
' ('. $self->email. "): ".
@@ -1798,6 +1934,11 @@ sub set_usage {
my $reset = 0;
my %handyhash = ();
+ if ( $options{null} ) {
+ %handyhash = ( map { ( $_ => 'NULL', $_."_threshold" => 'NULL' ) }
+ qw( seconds upbytes downbytes totalbytes )
+ );
+ }
foreach my $field (keys %$valueref){
$reset = 1 if $valueref->{$field};
$self->setfield($field, $valueref->{$field});
@@ -1816,8 +1957,8 @@ sub set_usage {
#die $error if $error; #services not explicity changed via the UI
my $sql = "UPDATE svc_acct SET " .
- join (',', map { "$_ = ?" } (keys %handyhash) ).
- " WHERE svcnum = ?";
+ join (',', map { "$_ = $handyhash{$_}" } (keys %handyhash) ).
+ " WHERE svcnum = ". $self->svcnum;
warn "$me $sql\n"
if $DEBUG;
@@ -1825,13 +1966,23 @@ sub set_usage {
if (scalar(keys %handyhash)) {
my $sth = $dbh->prepare( $sql )
or die "Error preparing $sql: ". $dbh->errstr;
- my $rv = $sth->execute((values %handyhash), $self->svcnum);
+ my $rv = $sth->execute();
die "Error executing $sql: ". $sth->errstr
unless defined($rv);
die "Can't update usage for svcnum ". $self->svcnum
if $rv == 0;
}
+ #$self->snapshot; #not necessary, we retain the old values
+ #create an object with the updated usage values
+ my $new = qsearchs('svc_acct', { 'svcnum' => $self->svcnum });
+ #call exports
+ my $error = $new->replace($self);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error replacing: $error";
+ }
+
if ( $reset ) {
my $error;
@@ -2613,6 +2764,8 @@ probably live somewhere else...
insertion of RADIUS group stuff in insert could be done with child_objects now
(would probably clean up export of them too)
+_op_usage and set_usage bypass the history... maybe they shouldn't
+
=head1 SEE ALSO
L<FS::svc_Common>, edit/part_svc.cgi from an installed web interface,
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
index b808527..74cedfc 100755
--- a/FS/FS/svc_broadband.pm
+++ b/FS/FS/svc_broadband.pm
@@ -6,6 +6,7 @@ use FS::Record qw( qsearchs qsearch dbh );
use FS::svc_Common;
use FS::cust_svc;
use FS::addr_block;
+use FS::part_svc_router;
use NetAddr::IP;
@ISA = qw( FS::svc_Common );
@@ -110,6 +111,8 @@ sub table_info {
sub table { 'svc_broadband'; }
+sub table_dupcheck_fields { ( 'mac_addr' ); }
+
=item search_sql STRING
Class method which returns an SQL fragment to search for the given string.
@@ -243,7 +246,19 @@ sub check {
}
}
+ $error = $self->_check_ip_addr;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+sub _check_ip_addr {
+ my $self = shift;
+
if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') {
+
+ return '' if $conf->exists('svc_broadband-allow_null_ip_addr'); #&& !$self->blocknum
+
return "Must supply either address or block"
unless $self->blocknum;
my $next_addr = $self->addr_block->next_free_addr;
@@ -252,6 +267,7 @@ sub check {
} else {
return "No free addresses in addr_block (blocknum: ".$self->blocknum.")";
}
+
}
if (not($self->blocknum)) {
@@ -285,9 +301,21 @@ sub check {
return 'Router '.$router->routernum.' cannot provide svcpart '.$self->svcpart;
}
- $self->SUPER::check;
+ '';
}
+sub _check_duplicate {
+ my $self = shift;
+
+ return "MAC already in use"
+ if ( $self->mac_addr &&
+ scalar( qsearch( 'svc_broadband', { 'mac_addr', $self->mac_addr } ) )
+ );
+
+ '';
+}
+
+
=item NetAddr
Returns a NetAddr::IP object containing the IP address of this service. The netmask
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index 47aa8f3..3311ac5 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -140,8 +140,8 @@ otherwise returns false.
The additional fields I<pkgnum> and I<svcpart> (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
-The additional field I<action> should be set to I<N> for new domains or I<M>
-for transfers.
+The additional field I<action> should be set to I<N> for new domains, I<M>
+for transfers, or I<I> for no action (registered elsewhere).
A registration or transfer email will be submitted unless
$FS::svc_domain::whois_hack is true.
@@ -300,7 +300,7 @@ sub replace {
if $old->getfield('domain') ne $new->getfield('domain');
# Better to do it here than to force the caller to remember that svc_domain is weird.
- $new->setfield(action => 'M');
+ $new->setfield(action => 'I');
my $error = $new->SUPER::replace($old, @_);
return $error if $error;
}
@@ -388,7 +388,6 @@ sub check {
or $self->ut_numbern('setup_date')
or $self->ut_numbern('renewal_interval')
or $self->ut_numbern('expiration_date')
- or $self->ut_textn('purpose')
or $self->SUPER::check;
}
diff --git a/FS/FS/svc_external.pm b/FS/FS/svc_external.pm
index 0fb391f..aca7c1b 100644
--- a/FS/FS/svc_external.pm
+++ b/FS/FS/svc_external.pm
@@ -95,6 +95,7 @@ sub label {
substr('0000000000'.uc($self->title), -10);
} else {
#$self->SUPER::label;
+ return $self->id unless $self->title =~ /\S/;
$self->id. ' - '. $self->title;
}
}
diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm
index ce767d5..11a5a0e 100644
--- a/FS/FS/svc_phone.pm
+++ b/FS/FS/svc_phone.pm
@@ -3,10 +3,11 @@ package FS::svc_phone;
use strict;
use vars qw( @ISA @pw_set $conf );
use FS::Conf;
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( qsearch qsearchs dbh );
use FS::Msgcat qw(gettext);
use FS::svc_Common;
use FS::part_svc;
+use FS::phone_device;
@ISA = qw( FS::svc_Common );
@@ -102,7 +103,7 @@ sub table_info {
disable_select => 1,
},
'sip_password' => 'SIP password',
- 'name' => 'Name',
+ 'phone_name' => 'Name',
},
};
}
@@ -151,6 +152,39 @@ Delete this record from the database.
=cut
+sub delete {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $phone_device ( $self->phone_device ) {
+ my $error = $phone_device->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ my $error = $self->SUPER::delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
# the delete method can be inherited from FS::Record
=item replace OLD_RECORD
@@ -326,6 +360,17 @@ sub radius_groups {
();
}
+=item phone_device
+
+Returns any FS::phone_device records associated with this service.
+
+=cut
+
+sub phone_device {
+ my $self = shift;
+ qsearch('phone_device', { 'svcnum' => $self->svcnum } );
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/tax_class.pm b/FS/FS/tax_class.pm
index 480fa10..4f03969 100644
--- a/FS/FS/tax_class.pm
+++ b/FS/FS/tax_class.pm
@@ -246,7 +246,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax classes"
);
die $error if $error;
$last = time;
@@ -270,7 +270,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax classes"
);
die $error if $error;
$last = time;
@@ -319,7 +319,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax classes"
);
die $error if $error;
$last = time;
diff --git a/FS/FS/tax_rate.pm b/FS/FS/tax_rate.pm
index 0d9156b..d55b09b 100644
--- a/FS/FS/tax_rate.pm
+++ b/FS/FS/tax_rate.pm
@@ -3,15 +3,27 @@ package FS::tax_rate;
use strict;
use vars qw( @ISA $DEBUG $me
%tax_unittypes %tax_maxtypes %tax_basetypes %tax_authorities
- %tax_passtypes );
+ %tax_passtypes %GetInfoType );
use Date::Parse;
+use DateTime;
+use DateTime::Format::Strptime;
use Storable qw( thaw );
+use IO::File;
+use File::Temp;
+use LWP::UserAgent;
+use HTTP::Request;
+use HTTP::Response;
use MIME::Base64;
-use FS::Record qw( qsearch qsearchs dbh );
+use DBIx::DBSchema;
+use DBIx::DBSchema::Table;
+use DBIx::DBSchema::Column;
+use FS::Record qw( qsearch qsearchs dbh dbdef );
use FS::tax_class;
use FS::cust_bill_pkg;
use FS::cust_tax_location;
+use FS::tax_rate_location;
use FS::part_pkg_taxrate;
+use FS::part_pkg_taxproduct;
use FS::cust_main;
use FS::Misc qw( csv_from_fixed );
@@ -530,6 +542,26 @@ sub tax_on_tax {
}
+=item tax_rate_location
+
+Returns an object representing the location associated with this tax
+(see L<FS::tax_rate_location>)
+
+=cut
+
+sub tax_rate_location {
+ my $self = shift;
+
+ qsearchs({ 'table' => 'tax_rate_location',
+ 'hashref' => { 'data_vendor' => $self->data_vendor,
+ 'geocode' => $self->geocode,
+ 'disabled' => '',
+ },
+ }) ||
+ new FS::tax_rate_location;
+
+}
+
=back
=head1 SUBROUTINES
@@ -557,7 +589,7 @@ sub batch_import {
if ( $format eq 'cch-fixed' || $format eq 'cch-fixed-update' ) {
$format =~ s/-fixed//;
my $date_format = sub { my $r='';
- /^(\d{4})(\d{2})(\d{2})$/ && ($r="$1/$2/$3");
+ /^(\d{4})(\d{2})(\d{2})$/ && ($r="$3/$2/$1");
$r;
};
my $trim = sub { my $r = shift; $r =~ s/^\s*//; $r =~ s/\s*$//; $r };
@@ -588,7 +620,13 @@ sub batch_import {
$hash->{'actionflag'} ='I' if ($hash->{'data_vendor'} eq 'cch');
$hash->{'data_vendor'} ='cch';
- $hash->{'effective_date'} = str2time($hash->{'effective_date'});
+ my $parser = new DateTime::Format::Strptime( pattern => "%m/%d/%Y",
+ time_zone => 'floating',
+ );
+ my $dt = $parser->parse_datetime( $hash->{'effective_date'} );
+ $hash->{'effective_date'} = $dt ? $dt->epoch : '';
+
+ $hash->{$_} = sprintf("%.2f", $hash->{$_}) foreach qw( taxbase taxmax );
my $taxclassid =
join(':', map{ $hash->{$_} } qw(taxtype taxcat) );
@@ -675,7 +713,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax rates"
);
die $error if $error;
$last = time;
@@ -719,7 +757,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax rates"
);
die $error if $error;
$last = time;
@@ -743,7 +781,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax rates"
);
die $error if $error;
$last = time;
@@ -777,7 +815,7 @@ sub batch_import {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
- int( 100 * $imported / $count )
+ int( 100 * $imported / $count ). ",Importing tax rates"
);
die $error if $error;
$last = time;
@@ -837,7 +875,8 @@ sub process_batch_import {
my $error = '';
my $have_location = 0;
- my @list = ( 'CODE', 'codefile', \&FS::tax_class::batch_import,
+ my @list = ( 'GEOCODE', 'geofile', \&FS::tax_rate_location::batch_import,
+ 'CODE', 'codefile', \&FS::tax_class::batch_import,
'PLUS4', 'plus4file', \&FS::cust_tax_location::batch_import,
'ZIP', 'zipfile', \&FS::cust_tax_location::batch_import,
'TXMATRIX', 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
@@ -878,8 +917,10 @@ sub process_batch_import {
my $error = '';
my @insert_list = ();
my @delete_list = ();
+ my @predelete_list = ();
- my @list = ( 'CODE', 'codefile', \&FS::tax_class::batch_import,
+ my @list = ( 'GEOCODE', 'geofile', \&FS::tax_rate_location::batch_import,
+ 'CODE', 'codefile', \&FS::tax_class::batch_import,
'PLUS4', 'plus4file', \&FS::cust_tax_location::batch_import,
'ZIP', 'zipfile', \&FS::cust_tax_location::batch_import,
'TXMATRIX', 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
@@ -932,9 +973,26 @@ sub process_batch_import {
close $dfh;
push @insert_list, $name, $ifh->filename, $import_sub;
- unshift @delete_list, $name, $dfh->filename, $import_sub;
+ if ( $name eq 'GEOCODE' ) { #handle this whole ordering issue better
+ unshift @predelete_list, $name, $dfh->filename, $import_sub;
+ } else {
+ unshift @delete_list, $name, $dfh->filename, $import_sub;
+ }
+
+ }
+
+ while( scalar(@predelete_list) ) {
+ my ($name, $file, $import_sub) =
+ (shift @predelete_list, shift @predelete_list, shift @predelete_list);
+ my $fmt = $format. ( $name eq 'ZIP' ? '-zip' : '' );
+ open my $fh, "< $file" or $error ||= "Can't open $name file $file: $!";
+ $error ||=
+ &{$import_sub}({ 'filehandle' => $fh, 'format' => $fmt }, $job);
+ close $fh;
+ unlink $file or warn "Can't delete $file: $!";
}
+
while( scalar(@insert_list) ) {
my ($name, $file, $import_sub) =
(shift @insert_list, shift @insert_list, shift @insert_list);
@@ -983,6 +1041,541 @@ sub process_batch_import {
}
+=item process_download_and_reload
+
+Download and process a tax update as a queued JSRPC job after wiping the
+existing wipable tax data.
+
+=cut
+
+sub process_download_and_reload {
+ my $job = shift;
+
+ my $param = thaw(decode_base64($_[0]));
+ my $format = $param->{'format'}; #well... this is all cch specific
+
+ my ( $count, $last, $min_sec, $imported ) = (0, time, 5, 0); #progressbar
+ $count = 100;
+
+ if ( $job ) { # progress bar
+ my $error = $job->update_statustext( int( 100 * $imported / $count ) );
+ die $error if $error;
+ }
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+ my $error = '';
+
+ my $sql =
+ "SELECT count(*) FROM part_pkg_taxoverride JOIN tax_class ".
+ "USING (taxclassnum) WHERE data_vendor = '$format'";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute
+ or die "Unexpected error executing statement $sql: ". $sth->errstr;
+ die "Don't (yet) know how to handle part_pkg_taxoverride records."
+ if $sth->fetchrow_arrayref->[0];
+
+ # really should get a table EXCLUSIVE lock here
+
+ #remember disabled taxes
+ my %disabled_tax_rate = ();
+ foreach my $tax_rate ( qsearch( { table => 'tax_rate',
+ hashref => { disabled => 'Y',
+ data_vendor => $format,
+ },
+ select => 'geocode, taxclassnum',
+ }
+ )
+ )
+ {
+ my $tax_class =
+ qsearchs( 'tax_class', { taxclassnum => $tax_rate->taxclassnum } );
+ unless ( $tax_class ) {
+ warn "failed to find tax_class ". $tax_rate->taxclassnum;
+ next;
+ }
+ $disabled_tax_rate{$tax_rate->geocode. ':'. $tax_class->taxclass} = 1;
+ }
+
+ #remember tax products
+ # XXX FIXME this loop only works when cch is the only data provider
+ my %taxproduct = ();
+ my $extra_sql = "WHERE taxproductnum IS NOT NULL OR ".
+ "0 < ( SELECT count(*) from part_pkg_option WHERE ".
+ " part_pkg_option.pkgpart = part_pkg.pkgpart AND ".
+ " optionname LIKE 'usage_taxproductnum_%' AND ".
+ " optionvalue != '' )";
+ foreach my $part_pkg ( qsearch( { table => 'part_pkg',
+ select => 'DISTINCT pkgpart,taxproductnum',
+ hashref => {},
+ extra_sql => $extra_sql,
+ }
+ )
+ )
+ {
+ warn "working with package part ". $part_pkg->pkgpart.
+ "which has a taxproductnum of ". $part_pkg->taxproductnum. "\n" if $DEBUG;
+ my $part_pkg_taxproduct = $part_pkg->taxproduct('');
+ $taxproduct{$part_pkg->pkgpart}{''} = $part_pkg_taxproduct->taxproduct
+ if $part_pkg_taxproduct;
+
+ foreach my $option ( $part_pkg->part_pkg_option ) {
+ next unless $option->optionname =~ /^usage_taxproductnum_(\w)$/;
+ my $class = $1;
+
+ $part_pkg_taxproduct = $part_pkg->taxproduct($class);
+ $taxproduct{$part_pkg->pkgpart}{$class} = $part_pkg_taxproduct->taxproduct
+ if $part_pkg_taxproduct;
+ }
+ }
+
+ #wipe out the old data
+ foreach my $tax_rate_location ( qsearch( 'tax_rate_location',
+ { data_vendor => $format,
+ disabled => '',
+ }
+ )
+ )
+ {
+ $tax_rate_location->disabled('Y');
+ my $error = $tax_rate_location->replace;
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+
+ local $FS::part_pkg_taxproduct::delete_kludge = 1;
+ my @table = qw(
+ tax_rate part_pkg_taxrate part_pkg_taxproduct tax_class cust_tax_location
+ );
+ foreach my $table ( @table ) {
+ foreach my $row ( qsearch( $table, { data_vendor => $format } ) ) {
+ my $error = $row->delete;
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+ }
+
+ if ( $format eq 'cch' ) {
+ foreach my $cust_tax_location ( qsearch( 'cust_tax_location',
+ { data_vendor => "$format-zip" }
+ )
+ )
+ {
+ my $error = $cust_tax_location->delete;
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+ }
+
+ #import new data
+ process_download_and_update($job, @_);
+
+ #restore taxproducts
+ foreach my $pkgpart ( keys %taxproduct ) {
+ warn "restoring taxproductnums on pkgpart $pkgpart\n" if $DEBUG;
+
+ my $part_pkg = qsearchs('part_pkg', { pkgpart => $pkgpart } );
+ unless ( $part_pkg ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die "somehow failed to find part_pkg with pkgpart $pkgpart!\n";
+ }
+
+ my %options = $part_pkg->options;
+ my %pkg_svc = map { $_->svcpart => $_->quantity } $part_pkg->pkg_svc;
+ my $primary_svc = $part_pkg->svcpart;
+ my $new = new FS::part_pkg { $part_pkg->hash };
+
+ foreach my $class ( keys %{ $taxproduct{$pkgpart} } ) {
+ warn "working with class '$class'\n" if $DEBUG;
+ my $part_pkg_taxproduct =
+ qsearchs( 'part_pkg_taxproduct',
+ { taxproduct => $taxproduct{$pkgpart}{$class},
+ data_vendor => $format,
+ }
+ );
+
+ unless ( $part_pkg_taxproduct ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die "failed to find part_pkg_taxproduct ($taxproduct{pkgpart}{$class})".
+ " for pkgpart $pkgpart\n";
+ }
+
+ if ( $class eq '' ) {
+ $new->taxproductnum($part_pkg_taxproduct->taxproductnum);
+ next;
+ }
+
+ $options{"usage_taxproductnum_$class"} =
+ $part_pkg_taxproduct->taxproductnum;
+
+ }
+
+ my $error = $new->replace( $part_pkg,
+ 'pkg_svc' => \%pkg_svc,
+ 'primary_svc' => $primary_svc,
+ 'options' => \%options,
+ );
+
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+
+ #disable tax_rates
+ foreach my $key (keys %disabled_tax_rate) {
+ my ($geocode,$taxclass) = split /:/, $key, 2;
+ my @tax_class = qsearch( 'tax_class', { data_vendor => $format,
+ taxclass => $taxclass,
+ } );
+ if (scalar(@tax_class) > 1) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die "found multiple tax_class records for format $format class $taxclass";
+ }
+
+ unless (scalar(@tax_class)) {
+ warn "no tax_class for format $format class $taxclass\n";
+ next;
+ }
+
+ my @tax_rate =
+ qsearch('tax_rate', { data_vendor => $format,
+ geocode => $geocode,
+ taxclassnum => $tax_class[0]->taxclassnum,
+ }
+ );
+
+ if (scalar(@tax_rate) > 1) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die "found multiple tax_rate records for format $format geocode $geocode".
+ " and taxclass $taxclass ( taxclassnum ". $tax_class[0]->taxclassnum.
+ " )";
+ }
+
+ if (scalar(@tax_rate)) {
+ $tax_rate[0]->disabled('Y');
+ my $error = $tax_rate[0]->replace;
+ if ( $error ) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }
+ }
+ }
+
+ #success!
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+}
+
+=item process_download_and_update
+
+Download and process a tax update as a queued JSRPC job
+
+=cut
+
+sub process_download_and_update {
+ my $job = shift;
+
+ my $param = thaw(decode_base64(shift));
+ my $format = $param->{'format'}; #well... this is all cch specific
+
+ my ( $count, $last, $min_sec, $imported ) = (0, time, 5, 0); #progressbar
+ $count = 100;
+
+ if ( $job ) { # progress bar
+ my $error = $job->update_statustext( int( 100 * $imported / $count ) );
+ die $error if $error;
+ }
+
+ my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc. '/taxdata';
+ unless (-d $dir) {
+ mkdir $dir or die "can't create $dir: $!\n";
+ }
+
+ if ($format eq 'cch') {
+
+ eval "use Text::CSV_XS;";
+ die $@ if $@;
+
+ eval "use XBase;";
+ die $@ if $@;
+
+ my $conffile = '%%%FREESIDE_CONF%%%/cchconf';
+ my $conffh = new IO::File "<$conffile" or die "can't open $conffile: $!\n";
+ my ( $urls, $secret, $states ) =
+ map { /^(.*)$/ or die "bad config line in $conffile: $_\n"; $1 }
+ <$conffh>;
+
+ $dir .= '/cch';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+ my $error = '';
+
+ # really should get a table EXCLUSIVE lock here
+ # check if initial import or update
+
+ my $sql = "SELECT count(*) from tax_rate WHERE data_vendor='$format'";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute() or die $sth->errstr;
+ my $upgrade = $sth->fetchrow_arrayref->[0];
+
+ # create cache and/or rotate old tax data
+
+ if (-d $dir) {
+
+ if (-d "$dir.4") {
+ opendir(my $dirh, "$dir.4") or die "failed to open $dir.4: $!\n";
+ foreach my $file (readdir($dirh)) {
+ unlink "$dir.4/$file" if (-f "$dir.4/$file");
+ }
+ closedir($dirh);
+ rmdir "$dir.4";
+ }
+
+ for (3, 2, 1) {
+ if ( -e "$dir.$_" ) {
+ rename "$dir.$_", "$dir.". ($_+1) or die "can't rename $dir.$_: $!\n";
+ }
+ }
+ rename "$dir", "$dir.1" or die "can't rename $dir: $!\n";
+
+ } else {
+
+ die "can't find previous tax data\n" if $upgrade;
+
+ }
+
+ mkdir "$dir.new" or die "can't create $dir.new: $!\n";
+
+ # fetch and unpack the zip files
+
+ my $ua = new LWP::UserAgent;
+ foreach my $url (split ',', $urls) {
+ my @name = split '/', $url; #somewhat restrictive
+ my $name = pop @name;
+ $name =~ /(.*)/; # untaint that which we trust;
+ $name = $1;
+
+ open my $taxfh, ">$dir.new/$name" or die "Can't open $dir.new/$name: $!\n";
+
+ my $res = $ua->request(
+ new HTTP::Request( GET => $url),
+ sub { #my ($data, $response_object) = @_;
+ print $taxfh $_[0] or die "Can't write to $dir.new/$name: $!\n";
+ my $content_length = $_[1]->content_length;
+ $imported += length($_[0]);
+ if ( time - $min_sec > $last ) {
+ my $error = $job->update_statustext(
+ ($content_length ? int(100 * $imported/$content_length) : 0 ).
+ ",Downloading data from CCH"
+ );
+ die $error if $error;
+ $last = time;
+ }
+ },
+ );
+ die "download of $url failed: ". $res->status_line
+ unless $res->is_success;
+
+ close $taxfh;
+ my $error = $job->update_statustext( "0,Unpacking data" );
+ die $error if $error;
+ $secret =~ /(.*)/; # untaint that which we trust;
+ $secret = $1;
+ system('unzip', "-P", $secret, "-d", "$dir.new", "$dir.new/$name") == 0
+ or die "unzip -P $secret -d $dir.new $dir.new/$name failed";
+ #unlink "$dir.new/$name";
+ }
+
+ # extract csv files from the dbf files
+
+ foreach my $name ( qw( code detail geocode plus4 txmatrix zip ) ) {
+ my $error = $job->update_statustext( "0,Unpacking $name" );
+ die $error if $error;
+ warn "opening $dir.new/$name.dbf\n" if $DEBUG;
+ my $table = new XBase 'name' => "$dir.new/$name.dbf";
+ die "failed to access $dir.new/$name.dbf: ". XBase->errstr
+ unless defined($table);
+ $count = $table->last_record; # approximately;
+ $imported = 0;
+ open my $csvfh, ">$dir.new/$name.txt"
+ or die "failed to open $dir.new/$name.txt: $!\n";
+
+ my $csv = new Text::CSV_XS { 'always_quote' => 1 };
+ my @fields = $table->field_names;
+ my $cursor = $table->prepare_select;
+ my $format_date =
+ sub { my $date = shift;
+ $date =~ /^(\d{4})(\d{2})(\d{2})$/ && ($date = "$2/$3/$1");
+ $date;
+ };
+ while (my $row = $cursor->fetch_hashref) {
+ $csv->combine( map { ($table->field_type($_) eq 'D')
+ ? &{$format_date}($row->{$_})
+ : $row->{$_}
+ }
+ @fields
+ );
+ print $csvfh $csv->string, "\n";
+ $imported++;
+ if ( time - $min_sec > $last ) {
+ my $error = $job->update_statustext(
+ int(100 * $imported/$count). ",Unpacking $name"
+ );
+ die $error if $error;
+ $last = time;
+ }
+ }
+ $table->close;
+ close $csvfh;
+ }
+
+ # generate the diff files
+
+ my @insert_list = ();
+ my @delete_list = ();
+ my @predelete_list = ();
+
+ my @list = (
+ 'geocode', \&FS::tax_rate_location::batch_import,
+ 'code', \&FS::tax_class::batch_import,
+ 'plus4', \&FS::cust_tax_location::batch_import,
+ 'zip', \&FS::cust_tax_location::batch_import,
+ 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
+ 'detail', \&FS::tax_rate::batch_import,
+ );
+
+ while( scalar(@list) ) {
+ my ( $name, $method ) = ( shift @list, shift @list );
+ my %oldlines = ();
+
+ my $error = $job->update_statustext( "0,Comparing to previous $name" );
+ die $error if $error;
+
+ warn "processing $dir.new/$name.txt\n" if $DEBUG;
+
+ if ($upgrade) {
+ open my $oldcsvfh, "$dir.1/$name.txt"
+ or die "failed to open $dir.1/$name.txt: $!\n";
+
+ while(<$oldcsvfh>) {
+ chomp;
+ $oldlines{$_} = 1;
+ }
+ close $oldcsvfh;
+ }
+
+ open my $newcsvfh, "$dir.new/$name.txt"
+ or die "failed to open $dir.new/$name.txt: $!\n";
+
+ my $ifh = new File::Temp( TEMPLATE => "$name.insert.XXXXXXXX",
+ DIR => "$dir.new",
+ UNLINK => 0, #meh
+ ) or die "can't open temp file: $!\n";
+
+ my $dfh = new File::Temp( TEMPLATE => "$name.delete.XXXXXXXX",
+ DIR => "$dir.new",
+ UNLINK => 0, #meh
+ ) or die "can't open temp file: $!\n";
+
+ while(<$newcsvfh>) {
+ chomp;
+ if (exists($oldlines{$_})) {
+ $oldlines{$_} = 0;
+ } else {
+ print $ifh $_, ',"I"', "\n";
+ }
+ }
+ close $newcsvfh;
+
+ if ($name eq 'detail') {
+ for (keys %oldlines) { # one file for rate details
+ print $ifh $_, ',"D"', "\n" if $oldlines{$_};
+ }
+ } else {
+ for (keys %oldlines) {
+ print $dfh $_, ',"D"', "\n" if $oldlines{$_};
+ }
+ }
+ %oldlines = ();
+
+ push @insert_list, $name, $ifh->filename, $method;
+ if ( $name eq 'geocode' ) {
+ unshift @predelete_list, $name, $dfh->filename, $method
+ unless $name eq 'detail';
+ } else {
+ unshift @delete_list, $name, $dfh->filename, $method
+ unless $name eq 'detail';
+ }
+
+ close $dfh;
+ close $ifh;
+ }
+
+ while( scalar(@predelete_list) ) {
+ my ($name, $file, $method) =
+ (shift @predelete_list, shift @predelete_list, shift @predelete_list);
+
+ my $fmt = "$format-update";
+ $fmt = $fmt. ( $name eq 'zip' ? '-zip' : '' );
+ open my $fh, "< $file" or $error ||= "Can't open $name file $file: $!";
+ $error ||=
+ &{$method}({ 'filehandle' => $fh, 'format' => $fmt }, $job);
+ close $fh;
+ #unlink $file or warn "Can't delete $file: $!";
+ }
+
+ while( scalar(@insert_list) ) {
+ my ($name, $file, $method) =
+ (shift @insert_list, shift @insert_list, shift @insert_list);
+
+ my $fmt = "$format-update";
+ $fmt = $fmt. ( $name eq 'zip' ? '-zip' : '' );
+ open my $fh, "< $file" or $error ||= "Can't open $name file $file: $!";
+ $error ||=
+ &{$method}({ 'filehandle' => $fh, 'format' => $fmt }, $job);
+ close $fh;
+ #unlink $file or warn "Can't delete $file: $!";
+ }
+
+ while( scalar(@delete_list) ) {
+ my ($name, $file, $method) =
+ (shift @delete_list, shift @delete_list, shift @delete_list);
+
+ my $fmt = "$format-update";
+ $fmt = $fmt. ( $name eq 'zip' ? '-zip' : '' );
+ open my $fh, "< $file" or $error ||= "Can't open $name file $file: $!";
+ $error ||=
+ &{$method}({ 'filehandle' => $fh, 'format' => $fmt }, $job);
+ close $fh;
+ #unlink $file or warn "Can't delete $file: $!";
+ }
+
+ if ($error) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ die $error;
+ }else{
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ }
+
+ rename "$dir.new", "$dir"
+ or die "cch tax update processed, but can't rename $dir.new: $!\n";
+
+ }else{
+ die "Unknown format: $format";
+ }
+}
+
=item browse_queries PARAMS
Returns a list consisting of a hashref suited for use as the argument
@@ -1063,6 +1656,111 @@ sub browse_queries {
return ($query, "SELECT COUNT(*) FROM tax_rate $extra_sql");
}
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+#
+#
+
+sub _upgrade_data { # class method
+ my ($self, %opts) = @_;
+ my $dbh = dbh;
+
+ warn "$me upgrading $self\n" if $DEBUG;
+
+ my @column = qw ( tax excessrate usetax useexcessrate fee excessfee
+ feebase feemax );
+
+ if ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+
+ eval "use DBI::Const::GetInfoType;";
+ die $@ if $@;
+
+ my $major_version = 0;
+ $dbh->get_info( $GetInfoType{SQL_DBMS_VER} ) =~ /^(\d{2})/
+ && ( $major_version = sprintf("%d", $1) );
+
+ if ( $major_version > 7 ) {
+
+ # ideally this would be supported in DBIx-DBSchema and friends
+
+ foreach my $column ( @column ) {
+ my $columndef = dbdef->table($self->table)->column($column);
+ unless ($columndef->type eq 'numeric') {
+
+ warn "updating tax_rate column $column to numeric\n" if $DEBUG;
+ my $sql = "ALTER TABLE tax_rate ALTER $column TYPE numeric(14,8)";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ warn "updating h_tax_rate column $column to numeric\n" if $DEBUG;
+ $sql = "ALTER TABLE h_tax_rate ALTER $column TYPE numeric(14,8)";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+ }
+
+ } elsif ( $dbh->{pg_server_version} =~ /^704/ ) {
+
+ # ideally this would be supported in DBIx-DBSchema and friends
+
+ foreach my $column ( @column ) {
+ my $columndef = dbdef->table($self->table)->column($column);
+ unless ($columndef->type eq 'numeric') {
+
+ warn "updating tax_rate column $column to numeric\n" if $DEBUG;
+
+ foreach my $table ( qw( tax_rate h_tax_rate ) ) {
+
+ my $sql = "ALTER TABLE $table RENAME $column TO old_$column";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ my $def = dbdef->table($table)->column($column);
+ $def->type('numeric');
+ $def->length('14,8');
+ my $null = $def->null;
+ $def->null('NULL');
+
+ $sql = "ALTER TABLE $table ADD COLUMN ". $def->line($dbh);
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ $sql = "UPDATE $table SET $column = CAST( old_$column AS numeric )";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ unless ( $null eq 'NULL' ) {
+ $sql = "ALTER TABLE $table ALTER $column SET NOT NULL";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ }
+
+ $sql = "ALTER TABLE $table DROP old_$column";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+ }
+ }
+
+ } else {
+
+ warn "WARNING: tax_rate table upgrade unsupported for this Pg version\n";
+
+ }
+
+ } else {
+
+ warn "WARNING: tax_rate table upgrade only supported for Pg 8+\n";
+
+ }
+
+ '';
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/tax_rate_location.pm b/FS/FS/tax_rate_location.pm
new file mode 100644
index 0000000..218ed97
--- /dev/null
+++ b/FS/FS/tax_rate_location.pm
@@ -0,0 +1,317 @@
+package FS::tax_rate_location;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs dbh );
+use FS::Misc qw( csv_from_fixed );
+
+=head1 NAME
+
+FS::tax_rate_location - Object methods for tax_rate_location records
+
+=head1 SYNOPSIS
+
+ use FS::tax_rate_location;
+
+ $record = new FS::tax_rate_location \%hash;
+ $record = new FS::tax_rate_location { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::tax_rate_location object represents an example. FS::tax_rate_location inherits from
+FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item taxratelocationnum
+
+Primary key (assigned automatically for new tax_rate_locations)
+
+=item data_vendor
+
+The tax data vendor
+
+=item geocode
+
+A unique geographic location code provided by the data vendor
+
+=item city
+
+City
+
+=item county
+
+County
+
+=item state
+
+State
+
+=item disabled
+
+If 'Y' this record is no longer active.
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new tax rate location. To add the record to the database, see
+ L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'tax_rate_location'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete {
+ return "Can't delete tax rate locations. Set disable to 'Y' instead.";
+ # check that it is unused in any cust_bill_pkg_tax_location records instead?
+}
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+=item check
+
+Checks all fields to make sure this is a valid tax rate location. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('taxratelocationnum')
+ || $self->ut_textn('data_vendor')
+ || $self->ut_alpha('geocode')
+ || $self->ut_textn('city')
+ || $self->ut_textn('county')
+ || $self->ut_textn('state')
+ || $self->ut_enum('disabled', [ '', 'Y' ])
+ ;
+ return $error if $error;
+
+ my $t;
+ $t = qsearchs( 'tax_rate_location',
+ { disabled => '',
+ ( map { $_ => $self->$_ } qw( data_vendor geocode ) ),
+ },
+ )
+ unless $self->disabled;
+
+ $t = $self->by_key( $self->taxratelocationnum )
+ if ( !$t && $self->taxratelocationnum );
+
+ return "geocode ". $self->geocode. " already in use for this vendor"
+ if ( $t && $t->taxratelocationnum != $self->taxratelocationnum );
+
+ return "may only be disabled"
+ if ( $t && scalar( grep { $t->$_ ne $self->$_ }
+ grep { $_ ne 'disabled' }
+ $self->fields
+ )
+ );
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item batch_import
+
+=cut
+
+sub batch_import {
+ my ($param, $job) = @_;
+
+ my $fh = $param->{filehandle};
+ my $format = $param->{'format'};
+
+ my %insert = ();
+ my %delete = ();
+
+ my @fields;
+ my $hook;
+
+ my @column_lengths = ();
+ my @column_callbacks = ();
+ if ( $format eq 'cch-fixed' || $format eq 'cch-fixed-update' ) {
+ $format =~ s/-fixed//;
+ my $trim = sub { my $r = shift; $r =~ s/^\s*//; $r =~ s/\s*$//; $r };
+ push @column_lengths, qw( 28 25 2 10 );
+ push @column_lengths, 1 if $format eq 'cch-update';
+ push @column_callbacks, $trim foreach (@column_lengths);
+ }
+
+ my $line;
+ my ( $count, $last, $min_sec ) = (0, time, 5); #progressbar
+ if ( $job || scalar(@column_callbacks) ) {
+ my $error =
+ csv_from_fixed(\$fh, \$count, \@column_lengths, \@column_callbacks);
+ return $error if $error;
+ }
+
+ if ( $format eq 'cch' || $format eq 'cch-update' ) {
+ @fields = qw( city county state geocode );
+ push @fields, 'actionflag' if $format eq 'cch-update';
+
+ $hook = sub {
+ my $hash = shift;
+
+ $hash->{'data_vendor'} ='cch';
+
+ if (exists($hash->{'actionflag'}) && $hash->{'actionflag'} eq 'D') {
+ delete($hash->{actionflag});
+
+ $hash->{disabled} = '';
+ my $tax_rate_location = qsearchs('tax_rate_location', $hash);
+ return "Can't find tax_rate_location to delete: ".
+ join(" ", map { "$_ => ". $hash->{$_} } @fields)
+ unless $tax_rate_location;
+
+ $tax_rate_location->disabled('Y');
+ my $error = $tax_rate_location->replace;
+ return $error if $error;
+
+ delete($hash->{$_}) foreach (keys %$hash);
+ }
+
+ delete($hash->{'actionflag'});
+
+ '';
+
+ };
+
+ } elsif ( $format eq 'extended' ) {
+ die "unimplemented\n";
+ @fields = qw( );
+ $hook = sub {};
+ } else {
+ die "unknown format $format";
+ }
+
+ eval "use Text::CSV_XS;";
+ die $@ if $@;
+
+ my $csv = new Text::CSV_XS;
+
+ my $imported = 0;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ while ( defined($line=<$fh>) ) {
+ $csv->parse($line) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $csv->error_input();
+ };
+
+ if ( $job ) { # progress bar
+ if ( time - $min_sec > $last ) {
+ my $error = $job->update_statustext(
+ int( 100 * $imported / $count )
+ );
+ die $error if $error;
+ $last = time;
+ }
+ }
+
+ my @columns = $csv->fields();
+
+ my %tax_rate_location = ();
+ foreach my $field ( @fields ) {
+ $tax_rate_location{$field} = shift @columns;
+ }
+ if ( scalar( @columns ) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Unexpected trailing columns in line (wrong format?): $line";
+ }
+
+ my $error = &{$hook}(\%tax_rate_location);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ if (scalar(keys %tax_rate_location)) { #inserts only
+
+ my $tax_rate_location = new FS::tax_rate_location( \%tax_rate_location );
+ $error = $tax_rate_location->insert;
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't insert tax_rate_location for $line: $error";
+ }
+
+ }
+
+ $imported++;
+
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ return "Empty file!" unless ($imported || $format eq 'cch-update');
+
+ ''; #no error
+
+}
+
+=head1 BUGS
+
+Currently somewhat specific to CCH supplied data.
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 4b9fd91..f5511f0 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -13,7 +13,6 @@ bin/freeside-deloutsource
bin/freeside-deloutsourceuser
bin/freeside-deluser
bin/freeside-email
-bin/freeside-expiration-alerter
bin/freeside-queued
bin/freeside-radgroup
bin/freeside-reexport
@@ -335,8 +334,6 @@ FS/inventory_class.pm
t/inventory_class.t
FS/inventory_item.pm
t/inventory_item.t
-FS/cdr_upstream_rate.pm
-t/cdr_upstream_rate.t
FS/access_user.pm
t/access_user.t
FS/access_user_pref.pm
@@ -434,3 +431,25 @@ FS/cust_location.pm
t/cust_location.t
FS/cust_bill_pkg_tax_location.pm
t/cust_bill_pkg_tax_location.t
+FS/tax_rate_location.pm
+t/tax_rate_location.t
+FS/cust_bill_pkg_tax_rate_location.pm
+t/cust_bill_pkg_tax_rate_location.t
+FS/cust_recon.pm
+t/cust_recon.t
+FS/part_pkg_report_option.pm
+t/part_pkg_report_option.t
+FS/cust_main_exemption.pm
+t/cust_main_exemption.t
+FS/cust_tax_adjustment.pm
+t/cust_tax_adjustment.t
+FS/phone_device.pm
+t/phone_device.t
+FS/part_device.pm
+t/part_device.t
+FS/cdr_termination.pm
+t/cdr_termination.t
+FS/cust_attachment.pm
+t/cust_attachment.t
+FS/cust_statement.pm
+t/cust_statement.t
diff --git a/FS/bin/freeside-addgroup b/FS/bin/freeside-addgroup
index 7b30f7d..25c2345 100755
--- a/FS/bin/freeside-addgroup
+++ b/FS/bin/freeside-addgroup
@@ -24,7 +24,7 @@ my $error = $access_group->insert;
die $error if $error;
if ( $opt_s ) {
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => $access_group->groupnum,
diff --git a/FS/bin/freeside-apply_payments_and_credits b/FS/bin/freeside-apply_payments_and_credits
new file mode 100755
index 0000000..d789c6c
--- /dev/null
+++ b/FS/bin/freeside-apply_payments_and_credits
@@ -0,0 +1,79 @@
+#!/usr/bin/perl -w
+
+use strict;
+use vars qw( $DEBUG );
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearch qsearchs);
+use FS::cust_main;
+use DBI;
+
+$DEBUG = 1;
+
+my $user = shift or die &usage;
+my $dbh = adminsuidsetup $user;
+
+my $unapplied_payments_sql = <<EOF;
+SELECT custnum FROM cust_pay WHERE paid >
+ ( ( SELECT coalesce(sum(amount),0) FROM cust_bill_pay
+ WHERE cust_pay.paynum = cust_bill_pay.paynum )
+ + ( SELECT coalesce(sum(amount),0) FROM cust_pay_refund
+ WHERE cust_pay.paynum = cust_pay_refund.paynum)
+ )
+EOF
+
+my $unapplied_credits_sql = <<EOF;
+SELECT custnum FROM cust_credit WHERE cust_credit.amount >
+ ( ( SELECT coalesce(sum(cust_credit_bill.amount),0) FROM cust_credit_bill
+ WHERE cust_credit.crednum = cust_credit_bill.crednum )
+ + ( SELECT coalesce(sum(cust_Credit_refund.amount),0) FROM cust_credit_refund
+ WHERE cust_credit.crednum = cust_credit_refund.crednum)
+ )
+EOF
+
+my %custnum = ();
+
+my $sth = $dbh->prepare($unapplied_payments_sql) or die $dbh->errstr;
+$sth->execute or die "unapplied payment search failed: ". $sth->errstr;
+
+map { $custnum{$_->[0]} = 1 } @{ $sth->fetchall_arrayref };
+
+$sth = $dbh->prepare($unapplied_credits_sql) or die $dbh->errstr;
+$sth->execute or die "unapplied credit search failed: ". $sth->errstr;
+
+map { $custnum{$_->[0]} = 1 } @{ $sth->fetchall_arrayref };
+
+foreach my $custnum ( keys %custnum ) {
+
+ warn "processing customer $custnum\n" if $DEBUG;
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or die "customer $custnum no longer exists!\n";
+
+ my $error = $cust_main->apply_payments_and_credits;
+ die $error if $error;
+
+}
+
+sub usage {
+ die "Usage:\n\n freeside-apply_payments_and_credits user\n";
+}
+
+=head1 NAME
+
+freeside-apply_payments_and_credits - Command line interface to apply payments and credits to invoice
+
+=head1 SYNOPSIS
+
+ freeside-apply_payments_and_credits username
+
+=head1 DESCRIPTION
+
+Finds unapplied payment and credit amounts and applies them to any outstanding
+uncovered invoice amounts.
+
+B<username> is a username added by freeside-adduser.
+
+=cut
+
+
+
diff --git a/FS/bin/freeside-cdr-sftp_and_import b/FS/bin/freeside-cdr-sftp_and_import
new file mode 100755
index 0000000..e87698f
--- /dev/null
+++ b/FS/bin/freeside-cdr-sftp_and_import
@@ -0,0 +1,187 @@
+#!/usr/bin/perl
+
+use strict;
+use Getopt::Std;
+use Net::SFTP::Foreign::Compat;
+use Net::FTP;
+use FS::UID qw(adminsuidsetup datasrc);
+use FS::cdr;
+
+###
+# parse command line
+###
+
+use vars qw( $opt_m $opt_p $opt_r $opt_e $opt_d $opt_v );
+getopts('m:p:r:e:d:v');
+
+$opt_e ||= 'csv';
+#$opt_e = ".$opt_e" unless $opt_e =~ /^\./;
+$opt_e =~ s/^\.//;
+
+$opt_p ||= '';
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+# %%%FREESIDE_CACHE%%%
+my $cachedir = '/usr/local/etc/freeside/cache.'. datasrc. '/cdrs';
+mkdir $cachedir unless -d $cachedir;
+
+my $format = shift or die &usage;
+
+use vars qw( $servername );
+$servername = shift or die &usage;
+
+###
+# get the file list
+###
+
+warn "Retrieving directory listing\n" if $opt_v;
+
+$opt_m = 'sftp' if !defined($opt_m);
+$opt_m = lc($opt_m);
+
+my $ls;
+
+if($opt_m eq 'ftp') {
+ my $ls_ftp = ftp();
+
+ $ls = [ grep { /^$opt_p.*\.$opt_e$/i } $ls_ftp->ls ];
+}
+elsif($opt_m eq 'sftp') {
+ my $ls_sftp = sftp();
+
+ $ls_sftp->setcwd($opt_r) or die "can't chdir to $opt_r\n"
+ if $opt_r;
+
+ $ls = $ls_sftp->ls('.', wanted => qr/^$opt_p.*\.$opt_e$/i,
+ names_only => 1 );
+}
+else {
+ die "Method '$opt_m' not supported; must be ftp or sftp\n";
+}
+
+###
+# import each file
+###
+
+foreach my $filename ( @$ls ) {
+
+ warn "Downloading $filename\n" if $opt_v;
+
+ #get the file
+ if($opt_m eq 'ftp') {
+ my $ftp = ftp();
+ $ftp->get($filename, "$cachedir/$filename")
+ or die "Can't get $filename: ". $ftp->message . "\n";
+ }
+ else {
+ my $sftp = sftp();
+ $sftp->get($filename, "$cachedir/$filename")
+ or die "Can't get $filename: ". $sftp->error . "\n";
+ }
+
+ warn "Processing $filename\n" if $opt_v;
+
+ my $error = FS::cdr::batch_import( {
+ 'file' => "$cachedir/$filename",
+ 'format' => $format,
+ 'params' => { 'cdrbatch' => $filename, },
+ 'empty_ok' => 1,
+ } );
+ die $error if $error;
+
+ if ( $opt_d ) {
+ if($opt_m eq 'ftp') {
+ my $ftp = ftp();
+ $ftp->rename($filename, "$opt_d/$filename")
+ or die "Can't move $filename to $opt_d: ".$ftp->message . "\n";
+ }
+ else {
+ my $sftp = sftp();
+ $sftp->rename($filename, "$opt_d/$filename")
+ or die "can't move $filename to $opt_d: ". $sftp->error . "\n";
+ }
+ }
+
+ unlink "$cachedir/$filename";
+
+}
+
+###
+# subs
+###
+
+sub usage {
+ "Usage: \n cdr.import user format servername\n";
+}
+
+use vars qw( $sftp $ftp );
+
+sub ftp {
+ return $ftp if $ftp && $ftp->pwd;
+
+ my ($hostname, $user) = reverse split('@', $servername);
+ my ($user, $pass) = split(':', $user);
+
+ my $ftp = Net::FTP->new($hostname) or die "FTP connection to '$hostname' failed.";
+ $ftp->login($user, $pass) or die "FTP login failed: ".$ftp->message;
+ $ftp->cwd($opt_r) or die "can't chdir to $opt_r\n" if $opt_r;
+ return $ftp;
+}
+
+sub sftp {
+
+ #reuse connections
+ return $sftp if $sftp && $sftp->cwd;
+
+ my %sftp = ( host => $servername );
+
+ $sftp = Net::SFTP::Foreign->new(%sftp);
+ $sftp->error and die "SFTP connection failed: ". $sftp->error;
+
+ $sftp;
+}
+
+=head1 NAME
+
+cdr.sftp_and_import - Download CDR files from a remote server via SFTP
+
+=head1 SYNOPSIS
+
+ cdr.sftp_and_import [ -m method ][ -p prefix ] [ -e extension ] [ -r remotefolder ] [ -d donefolder ] [ -v ] user format [sftpuser@]servername
+
+=head1 DESCRIPTION
+
+Command line tool to download CDR files from a remote server via SFTP or FTP and then
+import them into the database.
+
+-m: transfer method (sftp or ftp), defaults to sftp
+
+-p: file prefix, if specified
+
+-e: file extension, defaults to .csv
+
+-r: if specified, changes into this remote folder before starting
+
+-d: if specified, moves files to the specified folder when done
+
+-v: verbose
+
+user: freeside username
+
+format: CDR format name
+
+[sftpuser@]servername: remote server
+(or ftpuser:ftppass@servername)
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cdr>
+
+=cut
+
+1;
+
diff --git a/FS/bin/freeside-check b/FS/bin/freeside-check
new file mode 100644
index 0000000..9930aae
--- /dev/null
+++ b/FS/bin/freeside-check
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+#!/usr/bin/perl -w
+
+use strict;
+use FS::UID qw( adminsuidsetup );
+use FS::Cron::check qw(
+ check_queued check_selfservice check_apache check_bop_failures
+ check_sg check_sg_login check_sgng
+ alert error_msg
+);
+
+my $user = shift or die &usage;
+my @emails = @ARGV;
+#die "no notification email given" unless @emails;
+
+eval { adminsuidsetup $user };
+
+if ( $@ ) { alert("Database down: $@", @emails); exit; }
+
+check_queued or alert('Queue daemon not running', @emails);
+check_selfservice or alert(error_msg(), @emails);
+check_apache or alert('Apache not running: '. error_msg(), @emails);
+
+#no-ops unless you are sg
+my $sg = 'FS::ClientAPI::SG';
+check_sg or alert("$sg not responding: ". error_msg(), @emails);
+check_sg_login or alert("$sg login errort: ". error_msg(), @emails);
+check_sgng or alert("${sg}NG not responding: ". error_msg(), @emails);
+
+check_bop_failures or alert(error_msg(), @emails);
+
diff --git a/FS/bin/freeside-daily b/FS/bin/freeside-daily
index 13079b4..728fa96 100755
--- a/FS/bin/freeside-daily
+++ b/FS/bin/freeside-daily
@@ -3,10 +3,11 @@
use strict;
use Getopt::Std;
use FS::UID qw(adminsuidsetup);
+use FS::Conf;
&untaint_argv; #what it sounds like (eww)
use vars qw(%opt);
-getopts("p:a:d:vl:sy:nm", \%opt);
+getopts("p:a:d:vl:sy:nmrkg:", \%opt);
my $user = shift or die &usage;
adminsuidsetup $user;
@@ -14,17 +15,33 @@ adminsuidsetup $user;
use FS::Cron::bill qw(bill);
bill(%opt);
-#what to do about the below when using -m? that is the question.
+#you can skip this just by not having the config
+use FS::Cron::upload qw(upload);
+upload(%opt);
+
+# Send alerts about upcoming credit card expiration.
+use FS::Cron::alert_expiration qw(alert_expiration);
+my $conf = new FS::Conf;
+alert_expiration(%opt) if($conf->exists('alert_expiration'));
-use FS::Cron::notify qw(notify_flat_delay);
-notify_flat_delay(%opt);
+#what to do about the below when using -m? that is the question.
+#you don't want to skip this, besides, it should be cheap
use FS::Cron::expire_user_pref qw(expire_user_pref);
expire_user_pref();
-use FS::Cron::vacuum qw(vacuum);
-vacuum();
+unless ( $opt{k} ) {
+
+ use FS::Cron::notify qw(notify_flat_delay);
+ notify_flat_delay(%opt);
+
+ #Pg 8.1+ auto-vaccums, 7.4 w/postgresql-contrib
+ #use FS::Cron::vacuum qw(vacuum);
+ #vacuum();
+}
+
+#you can skip this just by not having the config
use FS::Cron::backup qw(backup_scp);
backup_scp();
@@ -42,7 +59,7 @@ sub untaint_argv {
}
sub usage {
- die "Usage:\n\n freeside-daily [ -d 'date' ] user [ custnum custnum ... ]\n";
+ die "Usage:\n\n freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] [ -v ] [ -l level ] [ -m ] [ -k ] user [ custnum custnum ... ]\n";
}
###
@@ -55,7 +72,7 @@ freeside-daily - Run daily billing and invoice collection events.
=head1 SYNOPSIS
- freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] [ -v ] [ -l level ] [ -m ] user [ custnum custnum ... ]
+ freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] [ -v ] [ -l level ] [ -m ] [ -r ] [ -k ] user [ custnum custnum ... ]
=head1 DESCRIPTION
@@ -81,6 +98,9 @@ the bill and collect methods of a cust_main object. See L<FS::cust_main>.
-a: Only process customers with the specified agentnum
+ -g: Don't process the provided pkgpart (or pkgparts, specified as a comma-
+ separated list).
+
-s: re-charge setup fees
-v: enable debugging
@@ -89,6 +109,10 @@ the bill and collect methods of a cust_main object. See L<FS::cust_main>.
-m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+ -r: Multi-process mode dry run option
+
+ -k: skip notify_flat_delay and vacuum
+
user: From the mapsecrets file - see config.html from the base documentation
custnum: if one or more customer numbers are specified, only bills those
diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter
deleted file mode 100755
index 0bb61db..0000000
--- a/FS/bin/freeside-expiration-alerter
+++ /dev/null
@@ -1,241 +0,0 @@
-#!/usr/bin/perl -Tw
-
-use strict;
-use Date::Format;
-use Time::Local;
-use Text::Template;
-use Getopt::Std;
-use Net::SMTP;
-use Mail::Header;
-use Mail::Internet;
-use FS::Conf;
-use FS::UID qw(adminsuidsetup);
-use FS::Record qw(qsearch);
-use FS::cust_main;
-
-use vars qw($smtpmachine %agent_failure_body);
-
-#hush, perl!
-$FS::alerter::_template::first = "";
-$FS::alerter::_template::last = "";
-$FS::alerter::_template::company = "";
-$FS::alerter::_template::payby = "";
-$FS::alerter::_template::expdate = "";
-
-# Set the mail program and other variables
-my $mail_sender = "billing\@mydomain.tld"; # or invoice_from if available
-my $failure_recipient = "postmaster"; # or invoice_from if available
-my $warning_time = 30 * 24 * 60 * 60;
-my $urgent_time = 15 * 24 * 60 * 60;
-my $panic_time = 5 * 24 * 60 * 60;
-my $window_time = 24 * 60 * 60;
-
-&untaint_argv; #what it sounds like (eww)
-
-#we're at now now (and later).
-my($_date)= $^T;
-
-# Get the current month
-my ($sec,$min,$hour,$mday,$mon,$year) =
- (localtime($_date) )[0,1,2,3,4,5];
-$mon++;
-
-# Login to the database
-my $user = shift or die &usage;
-adminsuidsetup $user;
-
-# Get the needed configuration files
-my $conf = new FS::Conf;
-$smtpmachine = $conf->config('smtpmachine');
-
-my(@customers)=qsearch('cust_main',{});
-if (scalar(@customers) == 0)
-{
- exit 1;
-}
-
-# Now I can start looping
-foreach my $customer (@customers)
-{
- my $paydate = $customer->getfield('paydate');
- next if $paydate =~ /^\s*$/; #skip empty expiration dates
-
- my $custnum = $customer->getfield('custnum');
- my $first = $customer->getfield('first');
- my $last = $customer->getfield('last');
- my $company = $customer->getfield('company');
- my $payby = $customer->getfield('payby');
- my $payinfo = $customer->getfield('payinfo');
- my $daytime = $customer->getfield('daytime');
- my $night = $customer->getfield('night');
-
- my ($payyear,$paymonth,$payday) = split (/-/,$paydate);
-
- my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear);
-
- #credit cards expire at the end of the month/year of their exp date
- if ($payby eq 'CARD' || $payby eq 'DCRD') {
- ($paymonth < 11) ? $paymonth++ : ($paymonth=0, $payyear++);
- $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear);
- $expire_time--;
- }
-
- if (($expire_time < $_date + $warning_time &&
- $expire_time > $_date + $warning_time - $window_time) ||
- ($expire_time < $_date + $urgent_time &&
- $expire_time > $_date + $urgent_time - $window_time) ||
- ($expire_time < $_date + $panic_time &&
- $expire_time > $_date + $panic_time - $window_time)) {
-
- # Prepare for sending email, now inside the customer loop so i can be agent
- # virtualized
-
- my $agentnum = $customer->agentnum;
-
- $mail_sender = $conf->config('invoice_from', $agentnum )
- if $conf->exists('invoice_from', $agentnum);
- $failure_recipient = $conf->config('invoice_from', $agentnum)
- if $conf->exists('invoice_from', $agentnum);
-
- $ENV{MAILADDRESS} = $mail_sender;
-
- my @alerter_template = $conf->config('alerter_template', $agentnum)
- or die "cannot load config file alerter_template";
-
- my $alerter = new Text::Template TYPE => 'ARRAY',
- SOURCE => [ map "$_\n", @alerter_template ]
- or die "can't create new Text::Template object: $Text::Template::ERROR";
-
- $alerter->compile() or die "can't compile template: $Text::Template::ERROR";
-
- my @packages = $customer->ncancelled_pkgs;
- if (scalar(@packages) != 0) {
- my @invoicing_list = $customer->invoicing_list;
- if ( grep { $_ ne 'POST' } @invoicing_list ) {
- my $header = new Mail::Header ( [
- "From: $mail_sender",
- "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ),
- "Sender: $mail_sender",
- "Reply-To: $mail_sender",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: Billing Arrangement Expiration",
- ] );
- $FS::alerter::_template::first = $first;
- $FS::alerter::_template::last = $last;
- $FS::alerter::_template::company = $company;
- if ($payby eq 'CARD' || $payby eq 'DCRD') {
- $FS::alerter::_template::payby = "credit card (" .
- substr($payinfo, 0, 2) . "xxxxxxxxxx" .
- substr($payinfo, -4) . ")";
- }elsif ($payby eq 'COMP') {
- $FS::alerter::_template::payby = "complimentary account";
- }else{
- $FS::alerter::_template::payby = "current method";
- }
- $FS::alerter::_template::expdate = $expire_time;
-
- $FS::alerter::_template::company_name =
- $conf->config('company_name', $agentnum);
- $FS::alerter::_template::company_address =
- join("\n", $conf->config('company_address', $agentnum) ). "\n";
-
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ $alerter->fill_in( PACKAGE => 'FS::alerter::_template' ) ],
- );
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or die "Can't send expiration email: $!";
-
- } elsif ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) {
- push @{$agent_failure_body{$customer->agentnum}},
- sprintf(qq{%5d %-32.32s %4s %10s %12s %12s},
- $custnum,
- $first . " " . $last . " " . $company,
- $payby,
- $paydate,
- $daytime,
- $night
- );
- }
- }
- }
-}
-
-# Now I need to send failure EMAIL
-
-foreach my $agentnum ( keys %agent_failure_body ) {
-
- $mail_sender = $conf->config('invoice_from', $agentnum )
- if $conf->exists('invoice_from', $agentnum);
- $failure_recipient = $conf->config('invoice_from', $agentnum)
- if $conf->exists('invoice_from', $agentnum);
-
- $ENV{MAILADDRESS} = $mail_sender;
- my $header = new Mail::Header ( [
- "From: Account Processor",
- "To: $failure_recipient",
- "Sender: $mail_sender",
- "Reply-To: $mail_sender",
- "Subject: Unnotified Billing Arrangement Expirations",
- ] );
-
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ @{$agent_failure_body{$agentnum}} ],
- );
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or die "can't send alerter failure email to $failure_recipient".
- " via server $smtpmachine with SMTP: $!";
-}
-
-# subroutines
-sub untaint_argv {
- foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
- $ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal argument \"$ARGV[$_]\"";
- $ARGV[$_]=$1;
- }
-}
-
-sub usage {
- die "Usage:\n\n freeside-expiration-alerter user\n";
-}
-
-=head1 NAME
-
-freeside-expiration-alerter - Emails notifications of credit card expirations.
-
-=head1 SYNOPSIS
-
- freeside-expiration-alerter user
-
-=head1 DESCRIPTION
-
-Emails customers notice that their credit card or other billing arrangement
-is about to expire. Usually run as a cron job.
-
-user: From the mapsecrets file - see config.html from the base documentation
-
-=head1 BUGS
-
-Yes..... Use at your own risk. No guarantees or warrantees of any
-kind apply to this program. Parts of this program are hacked from
-other GNU licensed software created mainly by Ivan Kohler.
-
-This is released under the GNU Public License. See www.gnu.org
-for more information regarding this license.
-
-=head1 SEE ALSO
-
-L<FS::cust_main>, config.html from the base documentation
-
-=head1 AUTHOR
-
-Jeff Finucane <jeff@cmh.net>
-
-=cut
-
-
diff --git a/FS/bin/freeside-monthly b/FS/bin/freeside-monthly
index 1e41b78..a81e3e9 100755
--- a/FS/bin/freeside-monthly
+++ b/FS/bin/freeside-monthly
@@ -15,6 +15,9 @@ adminsuidsetup $user;
use FS::Cron::bill qw(bill);
bill(%opt, 'check_freq'=>'1m' );
+use FS::Cron::upload qw(upload);
+upload(%opt);
+
###
# subroutines
###
diff --git a/FS/bin/freeside-queued b/FS/bin/freeside-queued
index d4f09c1..e97a52c 100644
--- a/FS/bin/freeside-queued
+++ b/FS/bin/freeside-queued
@@ -4,9 +4,11 @@ use strict;
use vars qw( $DEBUG $kids $max_kids %kids );
use POSIX qw(:sys_wait_h);
use IO::File;
+use Getopt::Std;
use FS::UID qw(adminsuidsetup forksuidsetup driver_name dbh myconnect);
use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
-use FS::Record qw(qsearch qsearchs);
+use FS::Conf;
+use FS::Record qw(qsearch);
use FS::queue;
use FS::queue_depend;
@@ -15,9 +17,12 @@ use Net::SSH 0.07;
$DEBUG = 0;
-$max_kids = '10'; #guess it should be a config file...
$kids = 0;
+&untaint_argv; #what it sounds like (eww)
+use vars qw(%opt);
+getopts('sn', \%opt );
+
my $user = shift or die &usage;
warn "starting daemonization (forking)\n" if $DEBUG;
@@ -27,7 +32,6 @@ daemonize1('freeside-queued');
warn "dropping privledges\n" if $DEBUG;
drop_root();
-
$ENV{HOME} = (getpwuid($>))[7]; #for ssh
warn "connecting to database\n" if $DEBUG;
@@ -48,6 +52,9 @@ daemonize2();
#--
+my $conf = new FS::Conf;
+$max_kids = $conf->config('queued-max_kids') || 10;
+
my $warnkids=0;
while (1) {
@@ -81,114 +88,135 @@ while (1) {
# local $FS::UID::AutoCommit = 0;
$FS::UID::AutoCommit = 0;
- my $nodepend = 'AND 0 = ( SELECT COUNT(*) FROM queue_depend'.
+ my $nodepend = 'AND NOT EXISTS( SELECT 1 FROM queue_depend'.
' WHERE queue_depend.jobnum = queue.jobnum )';
- my $order_by = "ORDER BY jobnum ". ( driver_name eq 'mysql'
- ? 'LIMIT 1 FOR UPDATE'
- : 'FOR UPDATE LIMIT 1' );
+ #anything with a priority goes after stuff without one
+ my $order_by = ' ORDER BY COALESCE(priority,0) ASC, jobnum ASC ';
+
+ my $limit = $max_kids - $kids;
+
+ $order_by .= ( driver_name eq 'mysql'
+ ? " LIMIT $limit FOR UPDATE "
+ : " FOR UPDATE LIMIT $limit " );
- my $job = qsearchs({
+ my $hashref = { 'status' => 'new' };
+ if ( $opt{'s'} ) {
+ $hashref->{'secure'} = 'Y';
+ } elsif ( $opt{'n'} ) {
+ $hashref->{'secure'} = '';
+ }
+
+ my @jobs = qsearch({
'table' => 'queue',
- 'hashref' => { 'status' => 'new' },
+ 'hashref' => $hashref,
'extra_sql' => $nodepend,
'order_by' => $order_by,
- }) or do {
- # if $oldAutoCommit {
+ });
+
+ unless ( @jobs ) {
dbh->commit or do {
warn "WARNING: database error, closing connection: ". dbh->errstr;
undef $FS::UID::dbh;
next;
};
- # }
sleep 1;
next;
- };
-
- my %hash = $job->hash;
- $hash{'status'} = 'locked';
- my $ljob = new FS::queue ( \%hash );
- my $error = $ljob->replace($job);
- if ( $error ) {
- warn "WARNING: database error locking job, closing connection: ".
- dbh->errstr;
- undef $FS::UID::dbh;
- next;
}
- # if $oldAutoCommit {
- dbh->commit or do {
- warn "WARNING: database error, closing connection: ". dbh->errstr;
- undef $FS::UID::dbh;
- next;
- };
- # }
-
- $FS::UID::AutoCommit = 1;
- #}
-
- my @args = $ljob->args;
- splice @args, 0, 1, $ljob if $args[0] eq '_JOB';
+ foreach my $job ( @jobs ) {
- defined( my $pid = fork ) or do {
- warn "WARNING: can't fork: $!\n";
my %hash = $job->hash;
- $hash{'status'} = 'failed';
- $hash{'statustext'} = "[freeside-queued] can't fork: $!";
+ $hash{'status'} = 'locked';
my $ljob = new FS::queue ( \%hash );
my $error = $ljob->replace($job);
- die $error if $error;
- next; #don't increment the kid counter
- };
-
- if ( $pid ) {
- $kids++;
- $kids{$pid} = 1;
- } else { #kid time
-
- #get new db handle
- $FS::UID::dbh->{InactiveDestroy} = 1;
-
- forksuidsetup($user);
-
- #auto-use classes...
- #if ( $ljob->job =~ /(FS::part_export::\w+)::/ ) {
- if ( $ljob->job =~ /(FS::(part_export|cust_main)::\w+)::/
- || $ljob->job =~ /(FS::\w+)::/
- )
- {
- my $class = $1;
- eval "use $class;";
+ if ( $error ) {
+ warn "WARNING: database error locking job, closing connection: ".
+ dbh->errstr;
+ undef $FS::UID::dbh;
+ next;
+ }
+
+ dbh->commit or do {
+ warn "WARNING: database error, closing connection: ". dbh->errstr;
+ undef $FS::UID::dbh;
+ next;
+ };
+
+ $FS::UID::AutoCommit = 1;
+
+ my @args = $ljob->args;
+ splice @args, 0, 1, $ljob if $args[0] eq '_JOB';
+
+ defined( my $pid = fork ) or do {
+ warn "WARNING: can't fork: $!\n";
+ my %hash = $job->hash;
+ $hash{'status'} = 'failed';
+ $hash{'statustext'} = "[freeside-queued] can't fork: $!";
+ my $ljob = new FS::queue ( \%hash );
+ my $error = $ljob->replace($job);
+ die $error if $error;
+ next; #don't increment the kid counter
+ };
+
+ if ( $pid ) {
+ $kids++;
+ $kids{$pid} = 1;
+ } else { #kid time
+
+ #get new db handle
+ $FS::UID::dbh->{InactiveDestroy} = 1;
+
+ forksuidsetup($user);
+
+ dbh->{'private_profile'} = {} if UNIVERSAL::can(dbh, 'sprintProfile');
+
+ #auto-use classes...
+ if ( $ljob->job =~ /(FS::(part_export|cust_main)::\w+)::/
+ || $ljob->job =~ /(FS::\w+)::/
+ )
+ {
+ my $class = $1;
+ eval "use $class;";
+ if ( $@ ) {
+ warn "job use $class failed";
+ my %hash = $ljob->hash;
+ $hash{'status'} = 'failed';
+ $hash{'statustext'} = $@;
+ my $fjob = new FS::queue( \%hash );
+ my $error = $fjob->replace($ljob);
+ die $error if $error;
+ exit; #end-of-kid
+ };
+ }
+
+ my $eval = "&". $ljob->job. '(@args);';
+ warn 'running "&'. $ljob->job. '('. join(', ', @args). ")\n" if $DEBUG;
+ eval $eval; #throw away return value? suppose so
if ( $@ ) {
- warn "job use $class failed";
+ warn "job $eval failed";
my %hash = $ljob->hash;
$hash{'status'} = 'failed';
$hash{'statustext'} = $@;
my $fjob = new FS::queue( \%hash );
my $error = $fjob->replace($ljob);
die $error if $error;
- exit; #end-of-kid
- };
- }
-
- my $eval = "&". $ljob->job. '(@args);';
- warn 'running "&'. $ljob->job. '('. join(', ', @args). ")\n" if $DEBUG;
- eval $eval; #throw away return value? suppose so
- if ( $@ ) {
- warn "job $eval failed";
- my %hash = $ljob->hash;
- $hash{'status'} = 'failed';
- $hash{'statustext'} = $@;
- my $fjob = new FS::queue( \%hash );
- my $error = $fjob->replace($ljob);
- die $error if $error;
- } else {
- $ljob->delete;
+ } else {
+ $ljob->delete;
+ }
+
+ if ( UNIVERSAL::can(dbh, 'sprintProfile') ) {
+ open(PROFILE,">%%%FREESIDE_LOG%%%/queueprofile.$$.".time)
+ or die "can't open profile file: $!";
+ print PROFILE dbh->sprintProfile();
+ close PROFILE or die "can't close profile file: $!";
+ }
+
+ exit;
+ #end-of-kid
}
- exit;
- #end-of-kid
- }
+ } #foreach my $job
} continue {
if ( sigterm() ) {
@@ -201,6 +229,15 @@ while (1) {
}
}
+sub untaint_argv {
+ foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
+ #$ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ # Date::Parse
+ $ARGV[$_] =~ /^(.*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ $ARGV[$_]=$1;
+ }
+}
+
sub usage {
die "Usage:\n\n freeside-queued user\n";
}
@@ -221,12 +258,16 @@ freeside-queued - Job queue daemon
=head1 SYNOPSIS
- freeside-queued user
+ freeside-queued [ -s | -n ] user
=head1 DESCRIPTION
Job queue daemon. Should be running at all times.
+-s: "secure" jobs only (queued billing jobs)
+
+-n: non-"secure" jobs only (other jobs)
+
user: from the mapsecrets file - see config.html from the base documentation
=head1 VERSION
diff --git a/FS/bin/freeside-selfservice-server b/FS/bin/freeside-selfservice-server
index 2087e71..544f307 100644
--- a/FS/bin/freeside-selfservice-server
+++ b/FS/bin/freeside-selfservice-server
@@ -15,9 +15,11 @@ use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
use FS::UID qw(adminsuidsetup forksuidsetup);
use FS::ClientAPI;
use FS::ClientAPI_SessionCache;
+use FS::Record qw( qsearch qsearchs );
use FS::Conf;
use FS::cust_svc;
+use FS::agent;
$FREESIDE_LOG = "%%%FREESIDE_LOG%%%";
$FREESIDE_LOCK = "%%%FREESIDE_LOCK%%%";
@@ -97,7 +99,28 @@ while (1) {
if ( $keepalives && $keepalive_count++ > 10 ) {
$keepalive_count = 0;
lock_write;
+
nstore_fd( { _token => '_keepalive' }, $writer );
+ foreach my $agent ( qsearch( 'agent', { disabled => '' } ) ) {
+ my $config = qsearchs( 'conf', { name => 'selfservice-bulk_ftp_dir',
+ agentnum => $agent->agentnum,
+ } )
+ or next;
+
+ my $session =
+ FS::ClientAPI->dispatch( 'Agent/agent_login',
+ { username => $agent->username,
+ password => $agent->_password,
+ }
+ );
+
+ nstore_fd( { _token => '_ftp_scan',
+ dir => $config->value,
+ session_id => $session->{session_id},
+ },
+ $writer
+ );
+ }
unlock_write;
}
next;
diff --git a/FS/bin/freeside-sqlradius-reset b/FS/bin/freeside-sqlradius-reset
index 7d1d343..a77bad6 100755
--- a/FS/bin/freeside-sqlradius-reset
+++ b/FS/bin/freeside-sqlradius-reset
@@ -42,6 +42,10 @@ unless ( $opt_n ) {
}
}
+use FS::svc_Common;
+$FS::svc_Common::overlimit_missing_cust_svc_nonfatal_kludge = 1;
+$FS::svc_Common::overlimit_missing_cust_svc_nonfatal_kludge = 1;
+
foreach my $export ( @exports ) {
#my @svcparts = map { $_->svcpart } $export->export_svc;
@@ -49,14 +53,25 @@ foreach my $export ( @exports ) {
my @svc_x =
map { $_->svc_x }
- map { qsearch('cust_svc', { 'svcpart' => $_->svcpart } ) }
- grep { qsearch('cust_svc', { 'svcpart' => $_->svcpart } ) }
+ #map { qsearch('cust_svc', { 'svcpart' => $_->svcpart } ) }
+ #grep { qsearch('cust_svc', { 'svcpart' => $_->svcpart } ) }
+ # $export->export_svc;
+ map { @{ $_->[1] } }
+ grep { scalar( @{ $_->[1] } ) }
+ map { [ $_, [ qsearch('cust_svc', { 'svcpart' => $_->svcpart } ) ] ] }
$export->export_svc;
+
foreach my $svc_x ( @svc_x ) {
- $svc_x->check; #set any fixed usergroup so it'll export even if all
- #svc_acct records don't have the group yet
+ #$svc_x->check; #set any fixed usergroup so it'll export even if all
+ # #svc_acct records don't have the group yet
+ #more efficient?
+ my $x = $svc_x->setfixed( $svc_x->_fieldhandlers);
+ unless ( ref($x) ) {
+ warn "WARNING: can't set fixed usergroups for svcnum ". $svc_x->svcnum.
+ "\n";
+ }
if ($overlimit_groups && $svc_x->overlimit) {
$svc_x->usergroup( &{ $svc_x->_fieldhandlers->{'usergroup'} }
diff --git a/FS/bin/freeside-upgrade b/FS/bin/freeside-upgrade
index c988e13..6ced372 100755
--- a/FS/bin/freeside-upgrade
+++ b/FS/bin/freeside-upgrade
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
use strict;
-use vars qw($opt_d $opt_s $opt_q $opt_v);
+use vars qw($opt_d $opt_s $opt_q $opt_v $opt_r);
use vars qw($DEBUG $DRY_RUN);
use Getopt::Std;
use DBIx::DBSchema 0.31;
@@ -17,7 +17,7 @@ my $start = time;
die "Not running uid freeside!" unless checkeuid();
-getopts("dqs");
+getopts("dqrs");
$DEBUG = !$opt_q;
#$DEBUG = $opt_v;
@@ -60,20 +60,24 @@ if (dbdef->table('cust_main')->column('agent_custid') && ! $opt_s) {
#from 1.3 to 1.4... if not, it needs to be hooked into -upgrade here or
#you'll lose all the part_svc settings it migrates to part_svc_column
+my @statements =
+ grep { $_ !~ /^CREATE +INDEX +h_queue/ } #useless, holds up queue insertion
+ dbdef->sql_update_schema( dbdef_dist(datasrc), $dbh );
+
if ( $DRY_RUN ) {
print
- join(";\n", @bugfix, dbdef->sql_update_schema( dbdef_dist(datasrc), $dbh ) ). ";\n";
+ join(";\n", @bugfix, @statements ). ";\n";
exit;
} else {
- foreach my $statement ( @bugfix ) {
+ foreach my $statement ( @bugfix, @statements ) {
$dbh->do( $statement )
or die "Error: ". $dbh->errstr. "\n executing: $statement";
}
- warn "Pre-schema change upgrades completed in ". (time-$start). " seconds\n"; # if $DEBUG;
- $start = time;
+# warn "Pre-schema change upgrades completed in ". (time-$start). " seconds\n"; # if $DEBUG;
+# $start = time;
- dbdef->update_schema( dbdef_dist(datasrc), $dbh );
+# dbdef->update_schema( dbdef_dist(datasrc), $dbh );
}
warn "Schema upgrade completed in ". (time-$start). " seconds\n"; # if $DEBUG;
@@ -127,7 +131,7 @@ $FS::UID::AutoCommit = 0;
$FS::UID::callback_hack = 1;
$dbh = adminsuidsetup($user);
$FS::UID::callback_hack = 0;
-unless ( $DRY_RUN ) {
+unless ( $DRY_RUN || $opt_s ) {
my $dir = "%%%FREESIDE_CONF%%%/conf.". datasrc;
if (!scalar(qsearch('conf', {}))) {
my $error = FS::Conf::init_config($dir);
@@ -149,11 +153,13 @@ $start = time;
upgrade()
unless $DRY_RUN || $opt_s;
+$dbh->commit or die $dbh->errstr;
+
warn "Table updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
$start = time;
upgrade_sqlradius()
- unless $DRY_RUN || $opt_s;
+ unless $DRY_RUN || $opt_s || $opt_r;
warn "SQL RADIUS updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
$start = time;
@@ -161,7 +167,7 @@ $start = time;
$dbh->commit or die $dbh->errstr;
$dbh->disconnect or die $dbh->errstr;
-warn "Commit and disconnection completed in ". (time-$start). " seconds; upgrade done!\n"; # if $DEBUG;
+warn "Final commit and disconnection completed in ". (time-$start). " seconds; upgrade done!\n"; # if $DEBUG;
###
@@ -172,7 +178,7 @@ sub dbdef_create { # reverse engineer the schema from the DB and save to file
}
sub usage {
- die "Usage:\n freeside-upgrade [ -d ] [ -s ] [ -q | -v ] user\n";
+ die "Usage:\n freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ] user\n";
}
=head1 NAME
@@ -181,7 +187,7 @@ freeside-upgrade - Upgrades database schema for new freeside verisons.
=head1 SYNOPSIS
- freeside-upgrade [ -d ] [ -s ] [ -q | -v ]
+ freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ]
=head1 DESCRIPTION
@@ -203,6 +209,9 @@ Also performs other upgrade functions:
[ -q ]: Run quietly. This may become the default at some point.
+ [ -r ]: Skip sqlradius updates. Useful for occassions where the sqlradius
+ databases may be inaccessible.
+
[ -v ]: Run verbosely, sending debugging information to STDERR. This is the
current default.
diff --git a/FS/bin/freeside-void-payments b/FS/bin/freeside-void-payments
new file mode 100755
index 0000000..412033c
--- /dev/null
+++ b/FS/bin/freeside-void-payments
@@ -0,0 +1,222 @@
+#!/usr/bin/perl -w
+
+use strict;
+use vars qw( $user $cust_main @customers );
+use Getopt::Std;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearchs);
+use FS::Conf;
+use FS::cust_main;
+use FS::cust_pay;
+use FS::cust_pay_void;
+use Business::OnlinePayment; # For retrieving the void list only.
+use Time::Local;
+use Date::Parse 'str2time';
+use Date::Format 'time2str';
+
+my %opt;
+getopts("r:f:ca:g:s:e:vnX:", \%opt);
+
+$user = shift or die &usage;
+&adminsuidsetup( $user );
+
+# The -g and -a options need to override this.
+my $method = $opt{'c'} ? 'ECHECK' : 'CARD';
+my $gateway;
+if($opt{'g'}) {
+ $gateway = FS::payment_gateway->by_key($opt{'g'})
+ or die "Payment gateway not found: '".$opt{'g'}."'.";
+}
+elsif($opt{'a'}) {
+ my $agent = FS::agent->by_key($opt{'a'})
+ or die "Agent not found: '".$opt{'a'}."'.";
+ $gateway = $agent->payment_gateway(method => $method)
+ or die "Agent has no payment gateway for method '$method'.";
+}
+
+if(defined($opt{'X'})) {
+ die "Cancellation reason not found: '".$opt{'X'}."'"
+ if(! qsearchs('reason', { reasonnum => $opt{'X'} } ) );
+}
+
+my ($processor, $login, $password, $action, @bop_options) =
+ FS::cust_main->default_payment_gateway($method);
+my $gatewaynum = '';
+
+if($gateway) {
+# override the default gateway
+ $gatewaynum = $gateway->gatewaynum . '-' if $gateway->gatewaynum;
+ $processor = $gateway->gateway_module;
+ $login = $gateway->gateway_username;
+ $password = $gateway->gateway_password;
+ $action = $gateway->gateway_action;
+ @bop_options = $gateway->options;
+}
+
+my @auths;
+if($opt{'f'}) {
+# Read the list of authorization numbers from a file.
+ my $in;
+ open($in, '< '. $opt{'f'}) or die "Unable to open file: '".$opt{'f'}."'.";
+ @auths = grep /^\d+$/, <$in>;
+ chomp @auths;
+}
+else {
+# Get the list from the processor. This requires the processor module to
+# support get_returns.
+ my $transaction = new Business::OnlinePayment ( $processor, @bop_options );
+ if(! $transaction->can('get_returns')) {
+ die "'$processor' does not provide an automated void list.";
+ }
+ my @local = localtime;
+# Start and end dates for this can be set via -s and -e. If they're not,
+# end defaults to midnight today and start defaults to one day before end.
+ my $end = defined($opt{'e'}) ?
+ str2time($opt{'e'}) : timelocal(0, 0, 0, @local[3,4,5]);
+ my $start = defined($opt{'s'}) ?
+ str2time($opt{'s'}) : $end - 86400;
+ die "Invalid date range: '$start'-'$end'" if not ($start and $end);
+ $transaction->content (
+ login => $login,
+ password => $password,
+ start => time2str("%Y-%m-%d",$start),
+ end => time2str("%Y-%m-%d",$end),
+ );
+ @auths = $transaction->get_returns;
+}
+
+$opt{'r'} ||= 'freeside-void-payments';
+my $success = 0;
+my $notfound = 0;
+my $canceled = 0;
+print "Voiding ".scalar(@auths)." transactions:\n" if $opt{'v'};
+foreach my $authnum (@auths) {
+ my $paybatch = $gatewaynum . $processor . ':' . $authnum;
+ my $cust_pay = qsearchs('cust_pay', { paybatch => $paybatch } );
+ my $error;
+ my $cancel_error;
+ if($cust_pay) {
+ $error = $cust_pay->void($opt{'r'});
+ $success++ if not $error;
+ if($opt{'X'} and not $error) {
+ $cancel_error = join(';',$cust_pay->cust_main->cancel('reason' => $opt{'X'}));
+ $canceled++ if !$cancel_error;
+ }
+ }
+ else {
+ my $cpv = qsearchs('cust_pay_void', { paybatch => $paybatch });
+ if($cpv) {
+ $error = 'already voided '.time2str('%Y-%m-%d', $cpv->void_date) .
+ ' by ' . $cpv->otaker;
+ }
+ else {
+ $error = 'not found';
+ $notfound++;
+ }
+ }
+ if($opt{'v'}) {
+ print $authnum;
+ if($error) {
+ print "\t($error)";
+ }
+ elsif($opt{'X'}) {
+ print "\t(canceled service)" if !$cancel_error;
+ print "\n\t(cancellation failed: $cancel_error)" if $cancel_error;
+ }
+ print "\n";
+ }
+}
+
+if($opt{'v'}) {
+ print scalar(@auths)." transactions: $success voided, $notfound not found\n";
+ print "$canceled customer".($canceled == 1 ? '' : 's')." canceled\n" if $opt{'X'};
+}
+
+sub usage {
+ die "Usage:\n\n freeside-void-payments [ -f file | [ -s start-date ] [ -e end-date ] ] [ -r 'reason' ] [ -g gatewaynum | -a agentnum ] [ -c ] [ -v ] [ -n ] [-X reasonnum ] user\n";
+}
+
+__END__
+
+# Documentation
+
+=head1 NAME
+
+freeside-void-payments - Automatically void a list of returned payments.
+
+=head1 SYNOPSIS
+
+ freeside-void-payments [ -f file | [ -s start-date ] [ -e end-date ] ] [ -r 'reason' ] [ -g gatewaynum | -a agentnum ] [ -c ] [ -v ] [ -n ] user
+
+=head1 DESCRIPTION
+
+Voids payments that were returned by the payment processor. Can be
+run periodically from crontab or manually after receiving a list of
+returned payments. Normally this is a meaningful operation only for
+electronic checks.
+
+This script voids payments based on the combination of gateway (see
+L<FS::payment_gateway>) and authorization number, since this is
+generally how the processor will identify them later.
+
+ -f: Read the list of authorization numbers from the specified file.
+ If they are not from the default payment gateway, -g or -a
+ must be given to identify the gateway.
+
+ If -f is not given, the script will attempt to contact the gateway
+ and download a list of returned transactions. To support this,
+ the Business::OnlinePayment module for the processor must implement
+ the I<get_returns()> method. For an example, see
+ L<Business::OnlinePayment::WesternACH>.
+
+ -s, -e: Specify the starting and ending dates for the void list.
+ This has no effect if -f is given. The end date defaults to
+ today, and the start date defaults to one day before the end date.
+
+ -r: The reason for voiding the payments, to be stored in the database.
+
+ -g: The L<FS::payment_gateway> number for the gateway that handled
+ these payments. If -f is not given, this determines which
+ gateway will be contacted. This overrides -a.
+
+ -a: The agentnum whose default gateway will be used. If neither -a
+ nor -g is given, the system default gateway will be used.
+
+ -c: Use the default gateway for check transactions rather than
+ credit cards.
+
+ -v: Be verbose.
+
+ -X: Automatically cancel all packages belonging to customers whose payments
+ were returned. Requires a cancellation reasonnum (from L<FS::reason>).
+
+A warning will be emitted for each transaction that can't be found.
+This may happen if it's already been voided, or if the gateway
+doesn't match.
+
+=head1 EXAMPLE
+
+Given 'returns.txt', which contains one authorization number on each
+line, provided by your default e-check processor:
+
+ freeside-void-payments -f returns.txt -c -r 'Returned check'
+
+If your default processor is Western ACH, which supports automated
+returns processing, this voids all returned payments since 2009-06-01:
+
+ freeside-void-payments -r 'Returned check' -s 2009-06-01
+
+This, in your crontab, will void returned payments for the last
+day at 8:30 every morning:
+
+ 30 8 * * * /usr/local/bin/freeside-void-payments -r 'Returned check'
+
+=head1 BUGS
+
+Most payment gateways don't support it, making the script largely useless.
+
+=head1 SEE ALSO
+
+L<Business::OnlinePayment>, L<FS::cust_pay>
+
+=cut
diff --git a/FS/t/cdr_upstream_rate.t b/FS/t/cdr_termination.t
index f9458c5..7167bf2 100644
--- a/FS/t/cdr_upstream_rate.t
+++ b/FS/t/cdr_termination.t
@@ -1,5 +1,5 @@
BEGIN { $| = 1; print "1..1\n" }
END {print "not ok 1\n" unless $loaded;}
-use FS::cdr_upstream_rate;
+use FS::cdr_termination;
$loaded=1;
print "ok 1\n";
diff --git a/FS/t/cust_attachment.t b/FS/t/cust_attachment.t
new file mode 100644
index 0000000..5986204
--- /dev/null
+++ b/FS/t/cust_attachment.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_attachment;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/cust_bill_pkg_tax_rate_location.t b/FS/t/cust_bill_pkg_tax_rate_location.t
new file mode 100644
index 0000000..3250db9
--- /dev/null
+++ b/FS/t/cust_bill_pkg_tax_rate_location.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_bill_pkg_tax_rate_location;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/cust_main_exemption.t b/FS/t/cust_main_exemption.t
new file mode 100644
index 0000000..fec6d19
--- /dev/null
+++ b/FS/t/cust_main_exemption.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_main_exemption;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/cust_recon.t b/FS/t/cust_recon.t
new file mode 100644
index 0000000..3724736
--- /dev/null
+++ b/FS/t/cust_recon.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_recon;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/cust_statement.t b/FS/t/cust_statement.t
new file mode 100644
index 0000000..c57d94c
--- /dev/null
+++ b/FS/t/cust_statement.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_statement;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/cust_tax_adjustment.t b/FS/t/cust_tax_adjustment.t
new file mode 100644
index 0000000..cc5719a
--- /dev/null
+++ b/FS/t/cust_tax_adjustment.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_tax_adjustment;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/part_device.t b/FS/t/part_device.t
new file mode 100644
index 0000000..5696868
--- /dev/null
+++ b/FS/t/part_device.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_device;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/part_pkg_report_option.t b/FS/t/part_pkg_report_option.t
new file mode 100644
index 0000000..622bb38
--- /dev/null
+++ b/FS/t/part_pkg_report_option.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_pkg_report_option;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/phone_device.t b/FS/t/phone_device.t
new file mode 100644
index 0000000..3070314
--- /dev/null
+++ b/FS/t/phone_device.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::phone_device;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/tax_rate_location.t b/FS/t/tax_rate_location.t
new file mode 100644
index 0000000..f4ee910
--- /dev/null
+++ b/FS/t/tax_rate_location.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::tax_rate_location;
+$loaded=1;
+print "ok 1\n";
diff --git a/Makefile b/Makefile
index 8df079c..82e6cb2 100644
--- a/Makefile
+++ b/Makefile
@@ -121,10 +121,10 @@ RT_PATH = /opt/rt3
#only used for dev kludge now, not a big deal
FREESIDE_PATH = `pwd`
-PERL_INC_DEV_KLUDGE = /usr/local/share/perl/5.8.8/
+PERL_INC_DEV_KLUDGE = /usr/local/share/perl/5.10.0/
-VERSION=1.9.0cvs
-TAG=freeside_1_9_0
+VERSION=1.9.1
+TAG=freeside_1_9_1
DEBVERSION = `echo ${VERSION} | perl -pe 's/(\d)([a-z])/\1~\2/'`-1
@@ -140,7 +140,7 @@ help:
@echo
@echo " install-docs install-perl-modules"
@echo " install-init install-apache"
- @echo " install-rt"
+ @echo " install-rt install-texmf"
@echo " install-selfservice update-selfservice"
@echo
@echo " dev dev-docs dev-perl-modules"
@@ -198,7 +198,13 @@ perl-modules:
s'%%%MASONDATA%%%'${MASONDATA}'g;\
" blib/lib/FS/*.pm;\
perl -p -i -e "\
+ s/%%%SELFSERVICE_USER%%%/${SELFSERVICE_USER}/g;\
+ s/%%%SELFSERVICE_MACHINES%%%/${SELFSERVICE_MACHINES}/g;\
s|%%%FREESIDE_EXPORT%%%|${FREESIDE_EXPORT}|g;\
+ " blib/lib/FS/Cron/*.pm;\
+ perl -p -i -e "\
+ s|%%%FREESIDE_EXPORT%%%|${FREESIDE_EXPORT}|g;\
+ s|%%%FREESIDE_LOG%%%|${FREESIDE_LOG}|g;\
" blib/lib/FS/part_export/*.pm;\
perl -p -i -e "\
s|%%%FREESIDE_CACHE%%%|${FREESIDE_CACHE}|g;\
@@ -383,12 +389,13 @@ clean:
.PHONY: release
release:
# Update the changelog
- ./CVS2CL
+ ./bin/cvs2cl
cvs commit -m "Updated for ${VERSION}" ChangeLog
# Update the RPM specfile
cvs edit ${RPM_SPECFILE}
perl -p -i -e "s/\d+[^\}]+/${VERSION}/ if /%define\s+version\s+(\d+[^\}]+)\}/;" ${RPM_SPECFILE}
+ perl -p -i -e "s/\d+[^\}]+/1/ if /%define\s+release\s+(\d+[^\}]+)\}/;" ${RPM_SPECFILE}
cvs commit -m "Updated for ${VERSION}" ${RPM_SPECFILE}
# Update the Debian changelog
diff --git a/bin/billco-upload b/bin/billco-upload
deleted file mode 100644
index ce4a43d..0000000
--- a/bin/billco-upload
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-AGENTNUMS="1 2 3"
-
-date=`date +"%Y%m%d"`
-dir="/usr/local/etc/freeside/export.DBI:Pg:dbname=freeside/cust_bill"
-cd "$dir"
-
-for AGENTNUM in $AGENTNUMS; do
-
- for a in header detail; do
- mv agentnum$AGENTNUM-$a.csv agentnum$AGENTNUM-$date-$a.csv
- done
-
- zip agentnum$AGENTNUM-$date.zip agentnum$AGENTNUM-$date-header.csv agentnum$AGENTNUM-$date-detail.csv
-
- echo $dir/agentnum$AGENTNUM-$date.zip
-
-done
-
diff --git a/bin/cdr-netsapiens.import b/bin/cdr-netsapiens.import
new file mode 100755
index 0000000..8092255
--- /dev/null
+++ b/bin/cdr-netsapiens.import
@@ -0,0 +1,207 @@
+#!/usr/bin/perl
+#
+# */5 * * * /home/ivan/freeside/bin/cdr-netsapiens.import ivan exportnum
+
+use strict;
+use vars qw( $DEBUG );
+use REST::Client;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearchs);
+use FS::part_export;
+use FS::cdr;
+
+$DEBUG = 2;
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+my $exportnum = shift or die &usage;
+my $part_export = qsearchs('part_export', { 'exportnum' => $exportnum } )
+ or die "unknown exportnum $exportnum\n";
+
+#find max time_release
+#SELECT MAX(
+#2009-02-19 20:17:37
+my $time_release = '2009-01-01 00:00:00';
+
+#retreive CDRs >= this time
+#XXX (in pages, this tops out at 20) _start=>0, _limit=>20
+
+my $ns = $part_export->ns_command( 'GET', '/cdr/',
+ 'time_release' => '$time_release,',
+ '_sort' => '+time_release',
+ );
+
+#loop over them, double check duplicates, insert the rest
+
+my $content = $ns->responseContent;
+
+#<a href="/tac2/cdr/20090219201719000016%40SkyNet360.Com">20090219201719000016@SkyNet360.Com</a>
+# <form method="post" action="/tac2/cdr/20090219201719000016%40SkyNet360.Com">
+while ( $content =~
+ s/^.*?<form method="post" action="\/tac2\/cdr\/(\d+)\%40[^"]*">//is )
+{
+
+ my $accountcode = $1;
+ warn "$accountcode\n" if $DEBUG;
+
+ $content =~ s/(.*?)<\/form>//is;
+ my $cdr_content = $1;
+
+ while ( $cdr_content =~
+ s/.*?<input name="(\w+)" type="\w+" value="([^"]+)" \/>//is )
+ {
+ warn " $1 => $2\n" if $DEBUG > 1;
+
+ my $cdr = new FS::cdr {
+ #'src' =>
+ #'dst' =>
+# 'startdate' => 'time_start', #XXX needs parsing
+# 'enddate' => 'time_release', #XXX needs parsing
+ 'duration' => 'duration',
+ 'billsec' => 'time_talking',
+ #'disposition' =>
+ 'accountcode' => $accountcode,
+ #'charged_party'
+ };
+
+
+ }
+
+}
+
+sub usage {
+ "Usage: \n cdr-netsapiens.import user exportnum\n";
+}
+
+__END__
+
+ rly_prt_0 => 23946
+ orig_req_host => residential.skynet360.com
+ batch_dura => 0
+ orig_from_host => 63.251.149.5
+ batch_tim_beg => 2009-02-19 20:17:19
+ term_match => sip:7865457300@residential.skynet360.com
+ term_domain => residential.skynet360.com
+ term_sub => 7865457300
+ orig_req_user => 7865457300
+ orig_callid => 5D1164E6-44E011D6-8C84C368-EA5A0BC4@63.251.149.5
+ term_ip => 63.251.148.137:1453
+ term_to_uri => sip:7865457300@residential.skynet360.com
+ release_code => end
+ time_start => 2009-02-19 20:17:19.0
+ batch_hold => 0
+ orig_from_user => 9046384544
+ time_holding => 0
+ term_logi_uri => sip:7865457300@residential.skynet360.com
+ time_talking => 0
+ orig_from_uri => sip:9046384544@63.251.149.5
+ duration => 0
+ orig_logi_uri => sip:9046384544@63.251.149.5
+ rly_cnt_b => 0
+ time_insert => 2009-02-19 15:17:38.0
+ orig_to_user => 7865457300
+ rly_prt_a => 63.251.149.18:21972
+ cdr_index => 0
+ orig_to_host => 63.251.149.18
+ orig_match => sip:*@63.251.149.5
+ time_release => 2009-02-19 20:17:37
+ codec => G.711 u-law
+ orig_req_uri => sip:7865457300@residential.skynet360.com
+ orig_to_uri => sip:7865457300@63.251.149.18
+ rly_cnt_a => 13
+ orig_ip => 63.251.149.5:57326
+ release_text => Orig: Cancel
+ time_disp => 0
+ time_ringing => 2009-02-19 20:17:19
+ _method => put
+prt_0 => 23946
+ orig_req_host => residential.skynet360.com
+ batch_dura => 0
+ orig_from_host => 63.251.149.5
+ batch_tim_beg => 2009-02-19 20:17:19
+ term_match => sip:7865457300@residential.skynet360.com
+ term_domain => residential.skynet360.com
+ time_start => 2009-02-19 20:17:19.0
+ term_sub => 7865457300
+ orig_req_user => 7865457300
+ orig_callid => 5D1164E6-44E011D6-8C84C368-EA5A0BC4@63.251.149.5
+ term_ip => 63.251.148.137:1453
+ term_to_uri => sip:7865457300@residential.skynet360.com
+ release_code => end
+ time_start => 2009-02-19 20:17:19.0
+ batch_hold => 0
+ orig_from_user => 9046384544
+ time_holding => 0
+ term_logi_uri => sip:7865457300@residential.skynet360.com
+ time_talking => 0
+ orig_from_uri => sip:9046384544@63.251.149.5
+ duration => 0
+ orig_logi_uri => sip:9046384544@63.251.149.5
+ rly_cnt_b => 0
+ time_insert => 2009-02-19 15:17:38.0
+ orig_to_user => 7865457300
+ rly_prt_a => 63.251.149.18:21972
+ cdr_index => 0
+ orig_to_host => 63.251.149.18
+ orig_match => sip:*@63.251.149.5
+ time_release => 2009-02-19 20:17:37
+ codec => G.711 u-law
+ orig_req_uri => sip:7865457300@residential.skynet360.com
+ orig_to_uri => sip:7865457300@63.251.149.18
+ rly_cnt_a => 13
+ orig_ip => 63.251.149.5:57326
+ release_text => Orig: Cancel
+ time_disp => 0
+ time_ringing => 2009-02-19 20:17:19
+ _method => put
+
+list of freeside CDR fields, useful ones marked with *
+
+ acctid - primary key
+*[1] calldate - Call timestamp (SQL timestamp)
+ clid - Caller*ID with text
+* src - Caller*ID number / Source number
+* dst - Destination extension
+ dcontext - Destination context
+ channel - Channel used
+ dstchannel - Destination channel if appropriate
+ lastapp - Last application if appropriate
+ lastdata - Last application data
+* startdate - Start of call (UNIX-style integer timestamp)
+ answerdate - Answer time of call (UNIX-style integer timestamp)
+* enddate - End time of call (UNIX-style integer timestamp)
+* duration - Total time in system, in seconds
+* billsec - Total time call is up, in seconds
+*[2] disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
+ amaflags - What flags to use: BILL, IGNORE etc, specified on a per
+ channel basis like accountcode.
+*[3] accountcode - CDR account number to use: account
+ uniqueid - Unique channel identifier (Unitel/RSLCOM Event ID)
+ userfield - CDR user-defined field
+ cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
+*[4] charged_party - Service number to be billed
+ upstream_currency - Wholesale currency from upstream
+*[5] upstream_price - Wholesale price from upstream
+ upstream_rateplanid - Upstream rate plan ID
+ rated_price - Rated (or re-rated) price
+ distance - km (need units field?)
+ islocal - Local - 1, Non Local = 0
+*[6] calltypenum - Type of call - see FS::cdr_calltype
+ description - Description (cdr_type 7&8 only) (used for
+ cust_bill_pkg.itemdesc)
+ quantity - Number of items (cdr_type 7&8 only)
+ carrierid - Upstream Carrier ID (see FS::cdr_carrier)
+ upstream_rateid - Upstream Rate ID
+ svcnum - Link to customer service (see FS::cust_svc)
+ freesidestatus - NULL, done (or something)
+
+[1] Auto-populated from startdate if not present
+[2] Package options available to ignore calls without a specific disposition
+[3] When using 'cdr-charged_party-accountcode' config
+[4] Auto-populated from src (normal calls) or dst (toll free calls) if not present
+[5] When using 'upstream_simple' rating method.
+[6] Set to usage class classnum when using pre-rated CDRs and usage class-based
+ taxation (local/intrastate/interstate/international)
+
+
diff --git a/bin/cdr-transnexus.import b/bin/cdr-transnexus.import
new file mode 100755
index 0000000..9686f7d
--- /dev/null
+++ b/bin/cdr-transnexus.import
@@ -0,0 +1,143 @@
+#!/usr/bin/perl
+
+use strict;
+use Getopt::Std;
+use Net::SFTP::Foreign;
+use FS::UID qw(adminsuidsetup datasrc);
+use FS::cdr;
+
+###
+# parse command line
+###
+
+use vars qw( $opt_p $opt_d $opt_v );
+getopts('v');
+
+$opt_p = 'last';
+$opt_d = 'done';
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+# %%%FREESIDE_CACHE%%%
+my $cachedir = '/usr/local/etc/freeside/cache.'. datasrc. '/cdrs';
+mkdir $cachedir unless -d $cachedir;
+
+#my $format = shift or die &usage;
+my $format = 'transnexus';
+
+use vars qw( $servername );
+$servername = shift or die &usage;
+
+my $DIR = '/home/ossadmin/OSS/nexoss/CDR_ARCHIVE_BY_ACCOUNT';
+
+###
+# get the file list
+###
+
+warn "Retreiving directory listing\n" if $opt_v;
+
+my $ls_sftp = sftp();
+
+my $lsdir = $ls_sftp->ls($DIR);
+
+###
+# import each file in each dir
+###
+
+foreach my $dir ( @$lsdir ) {
+
+ my $dirname = $dir->{filename};
+ warn "Scanning dir $dirname\n" if $opt_v;
+
+ #my $ls = $ls_sftp->ls("$DIR/$dirname", wanted => qr/^$opt_p.*-CDRs$/i );
+ my $ls = $ls_sftp->ls("$DIR/$dirname", wanted => qr/^$opt_p.*Customer-CDRs$/i );
+
+ foreach my $file ( @$ls ) {
+
+ my $filename = $file->{filename};
+ warn "Downloading $filename\n" if $opt_v;
+
+ #get the file
+ my $get_sftp = sftp();
+ $get_sftp->get("$DIR/$dirname/$filename", "$cachedir/$filename")
+ or die "Can't get $filename: ". $get_sftp->error;
+
+ warn "Processing $filename\n" if $opt_v;
+
+ my $error = FS::cdr::batch_import( {
+ 'file' => "$cachedir/$filename",
+ 'format' => $format,
+ 'params' => { 'cdrbatch' => $filename, },
+ 'empty_ok' => 1,
+ } );
+ die $error if $error;
+
+ if ( $opt_d ) {
+ my $mv_sftp = sftp();
+ $mv_sftp->mkdir("$DIR/$dirname/$opt_d");
+ $mv_sftp->rename( "$DIR/$dirname/$filename",
+ "$DIR/$dirname/$opt_d/$filename" )
+ or die "can't move $filename to $opt_d: ". $mv_sftp->error;
+ }
+
+ unlink "$cachedir/$filename";
+
+ }
+
+}
+
+###
+# subs
+###
+
+sub usage {
+ "Usage: \n cdr-transnexus.import [ -v ] user [sftpuser@]servername\n";
+}
+
+use vars qw( $sftp );
+
+sub sftp {
+
+ #reuse connections
+ return $sftp if $sftp && $sftp->cwd;
+
+ my %sftp = ( host => $servername );
+
+ $sftp = Net::SFTP::Foreign->new(%sftp);
+ $sftp->error and die "SFTP connection failed: ". $sftp->error;
+
+ $sftp;
+}
+
+=head1 NAME
+
+cdr.sftp_and_import - Download CDR files from a remote server via SFTP
+
+=head1 SYNOPSIS
+
+ cdr-transnexus.import [ -v ] user [sftpuser@]servername
+
+=head1 DESCRIPTION
+
+Command line tool to download CDR files from a remote server via SFTP and then
+import them into the database.
+
+-v: verbose
+
+user: freeside username
+
+[sftpuser@]servername: remote server
+
+=head1 BUGS
+
+Hacked up copy of freeside-cdr-sftp_and_import
+
+=head1 SEE ALSO
+
+L<FS::cdr>
+
+=cut
+
+1;
+
diff --git a/bin/cdr.sftp_and_import b/bin/cdr.sftp_and_import
deleted file mode 100755
index 79e743f..0000000
--- a/bin/cdr.sftp_and_import
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/perl
-#
-# Usage:
-# cdr.sftp_and_import [ -e extension ] [ -d donefolder ] [ -v ] user format [sftpuser@]servername
-#
-# -e: file extension, defaults to .csv
-# -d: if specified, moves files to the specified folder when done
-
-use strict;
-use Getopt::Std;
-use Net::SFTP::Foreign;
-use FS::UID qw(adminsuidsetup datasrc);
-use FS::cdr;
-
-###
-# parse command line
-###
-
-use vars qw( $opt_e $opt_d $opt_v );
-getopts('e:d:v');
-
-$opt_e ||= 'csv';
-#$opt_e = ".$opt_e" unless $opt_e =~ /^\./;
-$opt_e =~ s/^\.//;
-
-my $user = shift or die &usage;
-adminsuidsetup $user;
-
-# %%%FREESIDE_CACHE%%%
-my $cachedir = '/usr/local/etc/freeside/cache.'. datasrc. '/cdrs';
-mkdir $cachedir unless -d $cachedir;
-
-my $format = shift or die &usage;
-
-use vars qw( $servername );
-$servername = shift or die &usage;
-
-###
-# get the file list
-###
-
-warn "Retreiving directory listing\n" if $opt_v;
-
-my $ls_sftp = sftp();
-
-my $ls = $ls_sftp->ls('.', wanted => qr/\.*$opt_e$/i );
-
-###
-# import each file
-###
-
-foreach my $file ( @$ls ) {
-
- my $filename = $file->{filename};
- warn "Downloading $filename\n" if $opt_v;
-
- #get the file
- my $get_sftp = sftp();
- $get_sftp->get($filename, "$cachedir/$filename")
- or die "Can't get $filename: ". $get_sftp->error;
-
- warn "Processing $filename\n" if $opt_v;
-
- my $error = FS::cdr::batch_import( {
- 'file' => "$cachedir/$filename"
- 'format' => $format,
- 'params' => { 'cdrbatch' => $filename, },
- 'empty_ok' => 1,
- } );
- die $error if $error;
-
- close FILE;
-
- if ( $opt_d ) {
- my $mv_sftp = sftp();
- $mv_sftp->rename($filename, "$opt_d/$filename")
- or die "can't move $filename to $opt_d: ". $mv_sftp->error;
- }
-
- unlink "$cachedir/$filename";
-
-}
-
-1;
-
-###
-# sub
-###
-
-sub usage {
- "Usage: \n cdr.import user format servername\n";
-}
-
-use vars qw( $sftp );
-
-sub sftp {
-
- #reuse connections
- return $sftp if $sftp && $sftp->cwd;
-
- my %sftp = ( host => $servername );
-
- #XXX remove these
- $sftp{port} = 10022;
- #$sftp{more} = '-v';
-
- $sftp = Net::SFTP::Foreign->new(%sftp);
- $sftp->error and die "SFTP connection failed: ". $sftp->error;
-
- $sftp;
-}
-
diff --git a/bin/confdiff b/bin/confdiff
new file mode 100755
index 0000000..5b6af85
--- /dev/null
+++ b/bin/confdiff
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+use FS::UID qw(adminsuidsetup);
+use FS::Conf;
+
+adminsuidsetup('ivan');
+
+my $conf = new FS::Conf;
+
+my $file2 = pop @ARGV;
+my $file1 = pop @ARGV;
+
+open(FILE1, ">/tmp/$file1") or die "can't open /tmp/$file1: $!";
+print FILE1 $conf->config($file1);
+print FILE1 "\n";
+close FILE1 or die $!;
+
+open(FILE2, ">/tmp/$file2") or die "can't open /tmp/$file2: $!";
+print FILE2 $conf->config($file2);
+print FILE2 "\n";
+close FILE2 or die $!;
+
+my @opt = @ARGV;
+
+system('diff', @opt, "/tmp/$file1", "/tmp/$file2");
+
+#unlink("/tmp/$file1', "/tmp/$file2");
diff --git a/bin/countdeclines b/bin/countdeclines
new file mode 100755
index 0000000..bbc3925
--- /dev/null
+++ b/bin/countdeclines
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use Date::Parse;
+
+my $e = 'PlugnPay error: 97: Declined for CVV failure';
+my @y = (2008,2009);
+
+my $p = 0;
+
+foreach my $y (@y) {
+ foreach my $m (1..12) {
+ my $d = "$m/1/$y";
+ my $t = str2time($d);
+
+ #print "$pd-$d: SELECT count(*) from cust_bill_event where statustext = '$e' and _date >= $p and _date < $t;\n"
+ print "SELECT count(*) from cust_bill_event where statustext = '$e' and _date >= $p and _date < $t;\n"
+ if $p;
+
+ $p = $t;
+ $pd = $d;
+ }
+}
diff --git a/bin/cust_main_special.pm b/bin/cust_main_special.pm
new file mode 100644
index 0000000..967b6be
--- /dev/null
+++ b/bin/cust_main_special.pm
@@ -0,0 +1,608 @@
+package cust_main_special;
+
+require 5.006;
+use strict;
+use vars qw( @ISA $DEBUG $me $conf );
+use Safe;
+use Carp;
+use Data::Dumper;
+use Date::Format;
+use FS::UID qw( dbh );
+use FS::Record qw( qsearchs qsearch );
+use FS::payby;
+use FS::cust_pkg;
+use FS::cust_bill;
+use FS::cust_bill_pkg;
+use FS::cust_bill_pkg_display;
+use FS::cust_bill_pkg_tax_location;
+use FS::cust_main_county;
+use FS::cust_location;
+use FS::tax_rate;
+use FS::cust_tax_location;
+use FS::part_pkg_taxrate;
+use FS::queue;
+use FS::part_pkg;
+
+@ISA = qw ( FS::cust_main );
+
+$DEBUG = 0;
+$me = '[emergency billing program]';
+
+$conf = new FS::Conf;
+
+=head1 METHODS
+
+=over 4
+
+=item bill OPTIONS
+
+Generates invoices (see L<FS::cust_bill>) for this customer. Usually used in
+conjunction with the collect method by calling B<bill_and_collect>.
+
+If there is an error, returns the error, otherwise returns false.
+
+Options are passed as name-value pairs. Currently available options are:
+
+=over 4
+
+=item resetup
+
+If set true, re-charges setup fees.
+
+=item time
+
+Bills the customer as if it were that time. Specified as a UNIX timestamp; see L<perlfunc/"time">). Also see L<Time::Local> and L<Date::Parse> for conversion functions. For example:
+
+ use Date::Parse;
+ ...
+ $cust_main->bill( 'time' => str2time('April 20th, 2001') );
+
+=item pkg_list
+
+An array ref of specific packages (objects) to attempt billing, instead trying all of them.
+
+ $cust_main->bill( pkg_list => [$pkg1, $pkg2] );
+
+=item invoice_time
+
+Used in conjunction with the I<time> option, this option specifies the date of for the generated invoices. Other calculations, such as whether or not to generate the invoice in the first place, are not affected.
+
+=item backbill
+
+Used to specify the period starting date and preventing normal billing. Instead all outstanding cdrs/usage are processed as if from the unix timestamp in backbill and without changing the dates in the customer packages. Useful in those situations when cdrs were not imported before a billing run
+
+=back
+
+=cut
+
+sub bill {
+ my( $self, %options ) = @_;
+
+ bless $self, 'cust_main_special';
+ return '' if $self->payby eq 'COMP';
+ warn "$me backbill usage for customer ". $self->custnum. "\n"
+ if $DEBUG;
+
+ my $time = $options{'time'} || time;
+ my $invoice_time = $options{'invoice_time'} || $time;
+
+ #put below somehow?
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ $self->select_for_update; #mutex
+
+ my @cust_bill_pkg = ();
+
+ ###
+ # find the packages which are due for billing, find out how much they are
+ # & generate invoice database.
+ ###
+
+ my( $total_setup, $total_recur, $postal_charge ) = ( 0, 0, 0 );
+ my %taxlisthash;
+ my @precommit_hooks = ();
+
+ my @cust_pkgs = qsearch('cust_pkg', { 'custnum' => $self->custnum } );
+ foreach my $cust_pkg (@cust_pkgs) {
+
+ #NO!! next if $cust_pkg->cancel;
+ next if $cust_pkg->getfield('cancel');
+
+ warn " bill package ". $cust_pkg->pkgnum. "\n" if $DEBUG > 1;
+
+ #? to avoid use of uninitialized value errors... ?
+ $cust_pkg->setfield('bill', '')
+ unless defined($cust_pkg->bill);
+
+ #my $part_pkg = $cust_pkg->part_pkg;
+
+ my $real_pkgpart = $cust_pkg->pkgpart;
+ my %hash = $cust_pkg->hash;
+
+ foreach my $part_pkg ( $cust_pkg->part_pkg->self_and_bill_linked ) {
+
+ $cust_pkg->set($_, $hash{$_}) foreach qw ( setup last_bill bill );
+
+ my $error =
+ $self->_make_lines( 'part_pkg' => $part_pkg,
+ 'cust_pkg' => $cust_pkg,
+ 'precommit_hooks' => \@precommit_hooks,
+ 'line_items' => \@cust_bill_pkg,
+ 'setup' => \$total_setup,
+ 'recur' => \$total_recur,
+ 'tax_matrix' => \%taxlisthash,
+ 'time' => $time,
+ 'options' => \%options,
+ );
+ if ($error) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ } #foreach my $part_pkg
+
+ } #foreach my $cust_pkg
+
+ unless ( @cust_bill_pkg ) { #don't create an invoice w/o line items
+ unless ( $options{backbill} ) {
+ #but do commit any package date cycling that happened
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ } else {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+ }
+ return '';
+ }
+
+ my $postal_pkg = $self->charge_postal_fee();
+ if ( $postal_pkg && !ref( $postal_pkg ) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't charge postal invoice fee for customer ".
+ $self->custnum. ": $postal_pkg";
+ }
+ if ( !$options{backbill} && $postal_pkg &&
+ ( scalar( grep { $_->recur && $_->recur > 0 } @cust_bill_pkg) ||
+ !$conf->exists('postal_invoice-recurring_only')
+ )
+ )
+ {
+ foreach my $part_pkg ( $postal_pkg->part_pkg->self_and_bill_linked ) {
+ my $error =
+ $self->_make_lines( 'part_pkg' => $part_pkg,
+ 'cust_pkg' => $postal_pkg,
+ 'precommit_hooks' => \@precommit_hooks,
+ 'line_items' => \@cust_bill_pkg,
+ 'setup' => \$total_setup,
+ 'recur' => \$total_recur,
+ 'tax_matrix' => \%taxlisthash,
+ 'time' => $time,
+ 'options' => \%options,
+ );
+ if ($error) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+ }
+
+ warn "having a look at the taxes we found...\n" if $DEBUG > 2;
+
+ # keys are tax names (as printed on invoices / itemdesc )
+ # values are listrefs of taxlisthash keys (internal identifiers)
+ my %taxname = ();
+
+ # keys are taxlisthash keys (internal identifiers)
+ # values are (cumulative) amounts
+ my %tax = ();
+
+ # keys are taxlisthash keys (internal identifiers)
+ # values are listrefs of cust_bill_pkg_tax_location hashrefs
+ my %tax_location = ();
+
+ foreach my $tax ( keys %taxlisthash ) {
+ my $tax_object = shift @{ $taxlisthash{$tax} };
+ warn "found ". $tax_object->taxname. " as $tax\n" if $DEBUG > 2;
+ warn " ". join('/', @{ $taxlisthash{$tax} } ). "\n" if $DEBUG > 2;
+ my $hashref_or_error =
+ $tax_object->taxline( $taxlisthash{$tax},
+ 'custnum' => $self->custnum,
+ 'invoice_time' => $invoice_time
+ );
+ unless ( ref($hashref_or_error) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $hashref_or_error;
+ }
+ unshift @{ $taxlisthash{$tax} }, $tax_object;
+
+ my $name = $hashref_or_error->{'name'};
+ my $amount = $hashref_or_error->{'amount'};
+
+ #warn "adding $amount as $name\n";
+ $taxname{ $name } ||= [];
+ push @{ $taxname{ $name } }, $tax;
+
+ $tax{ $tax } += $amount;
+
+ $tax_location{ $tax } ||= [];
+ if ( $tax_object->get('pkgnum') || $tax_object->get('locationnum') ) {
+ push @{ $tax_location{ $tax } },
+ {
+ 'taxnum' => $tax_object->taxnum,
+ 'taxtype' => ref($tax_object),
+ 'pkgnum' => $tax_object->get('pkgnum'),
+ 'locationnum' => $tax_object->get('locationnum'),
+ 'amount' => sprintf('%.2f', $amount ),
+ };
+ }
+
+ }
+
+ #move the cust_tax_exempt_pkg records to the cust_bill_pkgs we will commit
+ my %packagemap = map { $_->pkgnum => $_ } @cust_bill_pkg;
+ foreach my $tax ( keys %taxlisthash ) {
+ foreach ( @{ $taxlisthash{$tax} }[1 ... scalar(@{ $taxlisthash{$tax} })] ) {
+ next unless ref($_) eq 'FS::cust_bill_pkg';
+
+ push @{ $packagemap{$_->pkgnum}->_cust_tax_exempt_pkg },
+ splice( @{ $_->_cust_tax_exempt_pkg } );
+ }
+ }
+
+ #consolidate and create tax line items
+ warn "consolidating and generating...\n" if $DEBUG > 2;
+ foreach my $taxname ( keys %taxname ) {
+ my $tax = 0;
+ my %seen = ();
+ my @cust_bill_pkg_tax_location = ();
+ warn "adding $taxname\n" if $DEBUG > 1;
+ foreach my $taxitem ( @{ $taxname{$taxname} } ) {
+ next if $seen{$taxitem}++;
+ warn "adding $tax{$taxitem}\n" if $DEBUG > 1;
+ $tax += $tax{$taxitem};
+ push @cust_bill_pkg_tax_location,
+ map { new FS::cust_bill_pkg_tax_location $_ }
+ @{ $tax_location{ $taxitem } };
+ }
+ next unless $tax;
+
+ $tax = sprintf('%.2f', $tax );
+ $total_setup = sprintf('%.2f', $total_setup+$tax );
+
+ push @cust_bill_pkg, new FS::cust_bill_pkg {
+ 'pkgnum' => 0,
+ 'setup' => $tax,
+ 'recur' => 0,
+ 'sdate' => '',
+ 'edate' => '',
+ 'itemdesc' => $taxname,
+ 'cust_bill_pkg_tax_location' => \@cust_bill_pkg_tax_location,
+ };
+
+ }
+
+ my $charged = sprintf('%.2f', $total_setup + $total_recur );
+
+ #create the new invoice
+ my $cust_bill = new FS::cust_bill ( {
+ 'custnum' => $self->custnum,
+ '_date' => ( $invoice_time ),
+ 'charged' => $charged,
+ } );
+ my $error = $cust_bill->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't create invoice for customer #". $self->custnum. ": $error";
+ }
+
+ foreach my $cust_bill_pkg ( @cust_bill_pkg ) {
+ $cust_bill_pkg->invnum($cust_bill->invnum);
+ my $error = $cust_bill_pkg->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't create invoice line item: $error";
+ }
+ }
+
+
+ #foreach my $hook ( @precommit_hooks ) {
+ # eval {
+ # &{$hook}; #($self) ?
+ # };
+ # if ( $@ ) {
+ # $dbh->rollback if $oldAutoCommit;
+ # return "$@ running precommit hook $hook\n";
+ # }
+ #}
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ ''; #no error
+}
+
+
+sub _make_lines {
+ my ($self, %params) = @_;
+
+ warn " making lines\n" if $DEBUG > 1;
+ my $part_pkg = $params{part_pkg} or die "no part_pkg specified";
+ my $cust_pkg = $params{cust_pkg} or die "no cust_pkg specified";
+ my $precommit_hooks = $params{precommit_hooks} or die "no package specified";
+ my $cust_bill_pkgs = $params{line_items} or die "no line buffer specified";
+ my $total_setup = $params{setup} or die "no setup accumulator specified";
+ my $total_recur = $params{recur} or die "no recur accumulator specified";
+ my $taxlisthash = $params{tax_matrix} or die "no tax accumulator specified";
+ my $time = $params{'time'} or die "no time specified";
+ my (%options) = %{$params{options}};
+
+ my $dbh = dbh;
+ my $real_pkgpart = $cust_pkg->pkgpart;
+ my %hash = $cust_pkg->hash;
+ my $old_cust_pkg = new FS::cust_pkg \%hash;
+ my $backbill = $options{backbill} || 0;
+
+ my @details = ();
+
+ my $lineitems = 0;
+
+ $cust_pkg->pkgpart($part_pkg->pkgpart);
+
+ ###
+ # bill setup
+ ###
+
+ my $setup = 0;
+ my $unitsetup = 0;
+ if ( ! $cust_pkg->setup &&
+ (
+ ( $conf->exists('disable_setup_suspended_pkgs') &&
+ ! $cust_pkg->getfield('susp')
+ ) || ! $conf->exists('disable_setup_suspended_pkgs')
+ )
+ || $options{'resetup'}
+ ) {
+
+ warn " bill setup\n" if $DEBUG > 1;
+ $lineitems++;
+
+ $setup = eval { $cust_pkg->calc_setup( $time, \@details ) };
+ return "$@ running calc_setup for $cust_pkg\n"
+ if $@;
+
+ $unitsetup = $cust_pkg->part_pkg->unit_setup || $setup; #XXX uuh
+
+ $cust_pkg->setfield('setup', $time)
+ unless $cust_pkg->setup;
+ #do need it, but it won't get written to the db
+ #|| $cust_pkg->pkgpart != $real_pkgpart;
+
+ }
+
+ ###
+ # bill recurring fee
+ ###
+
+ #XXX unit stuff here too
+ my $recur = 0;
+ my $unitrecur = 0;
+ my $sdate;
+ if ( ! $cust_pkg->getfield('susp') and
+ ( $part_pkg->getfield('freq') ne '0' &&
+ ( $cust_pkg->getfield('bill') || 0 ) <= $time
+ )
+ || ( $part_pkg->plan eq 'voip_cdr'
+ && $part_pkg->option('bill_every_call')
+ )
+ || $backbill
+ ) {
+
+ # XXX should this be a package event? probably. events are called
+ # at collection time at the moment, though...
+ $part_pkg->reset_usage($cust_pkg, 'debug'=>$DEBUG)
+ if $part_pkg->can('reset_usage');
+ #don't want to reset usage just cause we want a line item??
+ #&& $part_pkg->pkgpart == $real_pkgpart;
+
+ warn " bill recur\n" if $DEBUG > 1;
+ $lineitems++;
+
+ # XXX shared with $recur_prog
+ $sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
+ $sdate = $cust_pkg->lastbill || $backbill if $backbill;
+
+ #over two params! lets at least switch to a hashref for the rest...
+ my $increment_next_bill = ( $part_pkg->freq ne '0'
+ && ( $cust_pkg->getfield('bill') || 0 ) <= $time
+ );
+ my %param = ( 'precommit_hooks' => $precommit_hooks,
+ 'increment_next_bill' => $increment_next_bill,
+ );
+
+ $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details, \%param ) };
+ return "$@ running calc_recur for $cust_pkg\n"
+ if ( $@ );
+
+
+ warn "details is now: \n" if $DEBUG > 2;
+ warn Dumper(\@details) if $DEBUG > 2;
+
+ if ( $increment_next_bill ) {
+
+ my $next_bill = $part_pkg->add_freq($sdate);
+ return "unparsable frequency: ". $part_pkg->freq
+ if $next_bill == -1;
+
+ #pro-rating magic - if $recur_prog fiddled $sdate, want to use that
+ # only for figuring next bill date, nothing else, so, reset $sdate again
+ # here
+ $sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
+ $sdate = $cust_pkg->lastbill || $backbill if $backbill;
+ #no need, its in $hash{last_bill}# my $last_bill = $cust_pkg->last_bill;
+ $cust_pkg->last_bill($sdate);
+
+ $cust_pkg->setfield('bill', $next_bill );
+
+ }
+
+ }
+
+ warn "\$setup is undefined" unless defined($setup);
+ warn "\$recur is undefined" unless defined($recur);
+ warn "\$cust_pkg->bill is undefined" unless defined($cust_pkg->bill);
+
+ ###
+ # If there's line items, create em cust_bill_pkg records
+ # If $cust_pkg has been modified, update it (if we're a real pkgpart)
+ ###
+
+ if ( $lineitems ) {
+
+ if ( !$backbill && $cust_pkg->modified && $cust_pkg->pkgpart == $real_pkgpart ) {
+ # hmm.. and if just the options are modified in some weird price plan?
+
+ warn " package ". $cust_pkg->pkgnum. " modified; updating\n"
+ if $DEBUG >1;
+
+ my $error = $cust_pkg->replace( $old_cust_pkg,
+ 'options' => { $cust_pkg->options },
+ );
+ return "Error modifying pkgnum ". $cust_pkg->pkgnum. ": $error"
+ if $error; #just in case
+ }
+
+ my @cust_pkg_detail = map { $_->detail } $cust_pkg->cust_pkg_detail('I');
+ if ( $DEBUG > 1 ) {
+ warn " tentatively adding customer package invoice detail: $_\n"
+ foreach @cust_pkg_detail;
+ }
+ push @details, @cust_pkg_detail;
+
+ $setup = sprintf( "%.2f", $setup );
+ $recur = sprintf( "%.2f", $recur );
+ my $cust_bill_pkg = new FS::cust_bill_pkg {
+ 'pkgnum' => $cust_pkg->pkgnum,
+ 'setup' => $setup,
+ 'unitsetup' => $unitsetup,
+ 'recur' => $recur,
+ 'unitrecur' => $unitrecur,
+ 'quantity' => $cust_pkg->quantity,
+ 'details' => \@details,
+ };
+
+ warn "created cust_bill_pkg which looks like:\n" if $DEBUG > 2;
+ warn Dumper($cust_bill_pkg) if $DEBUG > 2;
+ if ($backbill) {
+ my %usage_cust_bill_pkg = $cust_bill_pkg->disintegrate;
+ $recur = 0;
+ foreach my $key (keys %usage_cust_bill_pkg) {
+ next if ($key eq 'setup' || $key eq 'recur');
+ $recur += $usage_cust_bill_pkg{$key}->recur;
+ }
+ $setup = 0;
+ }
+
+ $setup = sprintf( "%.2f", $setup );
+ $recur = sprintf( "%.2f", $recur );
+ if ( $setup < 0 && ! $conf->exists('allow_negative_charges') ) {
+ return "negative setup $setup for pkgnum ". $cust_pkg->pkgnum;
+ }
+ if ( $recur < 0 && ! $conf->exists('allow_negative_charges') ) {
+ return "negative recur $recur for pkgnum ". $cust_pkg->pkgnum;
+ }
+
+
+ if ( $setup != 0 || $recur != 0 ) {
+
+ warn " charges (setup=$setup, recur=$recur); adding line items\n"
+ if $DEBUG > 1;
+
+ $cust_bill_pkg->setup($setup);
+ $cust_bill_pkg->recur($recur);
+
+ warn "cust_bill_pkg now looks like:\n" if $DEBUG > 2;
+ warn Dumper($cust_bill_pkg) if $DEBUG > 2;
+
+ if ( $part_pkg->option('recur_temporality', 1) eq 'preceding' ) {
+ $cust_bill_pkg->sdate( $hash{last_bill} );
+ $cust_bill_pkg->edate( $sdate - 86399 ); #60s*60m*24h-1
+ } else { #if ( $part_pkg->option('recur_temporality', 1) eq 'upcoming' ) {
+ $cust_bill_pkg->sdate( $sdate );
+ $cust_bill_pkg->edate( $cust_pkg->bill );
+ }
+
+ $cust_bill_pkg->pkgpart_override($part_pkg->pkgpart)
+ unless $part_pkg->pkgpart == $real_pkgpart;
+
+ $$total_setup += $setup;
+ $$total_recur += $recur;
+
+ ###
+ # handle taxes
+ ###
+
+ my $error =
+ $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg, $options{invoice_time});
+ return $error if $error;
+
+ push @$cust_bill_pkgs, $cust_bill_pkg;
+
+ } #if $setup != 0 || $recur != 0
+
+ } #if $line_items
+
+ '';
+
+}
+
+
+sub _gather_taxes {
+ my $self = shift;
+ my $part_pkg = shift;
+ my $class = shift;
+
+ my @taxes = ();
+ my $geocode = $self->geocode('cch');
+
+ my @taxclassnums = map { $_->taxclassnum }
+ $part_pkg->part_pkg_taxoverride($class);
+
+ unless (@taxclassnums) {
+ @taxclassnums = map { $_->taxclassnum }
+ $part_pkg->part_pkg_taxrate('cch', $geocode, $class);
+ }
+ warn "Found taxclassnum values of ". join(',', @taxclassnums)
+ if $DEBUG;
+
+ my $extra_sql =
+ "AND (".
+ join(' OR ', map { "taxclassnum = $_" } @taxclassnums ). ")";
+
+ @taxes = grep { ($_->fee || 0 ) == 0 } #ignore unit based taxes
+ qsearch({ 'table' => 'tax_rate',
+ 'hashref' => { 'geocode' => $geocode, },
+ 'extra_sql' => $extra_sql,
+ })
+ if scalar(@taxclassnums);
+
+ warn "Found taxes ".
+ join(',', map{ ref($_). " ". $_->get($_->primary_key) } @taxes). "\n"
+ if $DEBUG;
+
+ [ @taxes ];
+
+}
+
+
+=back
+
+
+=cut
+
+1;
+
diff --git a/bin/cust_pay_histogram b/bin/cust_pay_histogram
new file mode 100755
index 0000000..714b321
--- /dev/null
+++ b/bin/cust_pay_histogram
@@ -0,0 +1,115 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Std;
+use Date::Parse;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw( qsearch );
+use FS::cust_pay;
+
+&untaint_argv; #what it sounds like (eww)
+use vars qw(%opt);
+getopts("p:a:b:e:", \%opt);
+
+my $user = shift or die &usage;
+my $dbh = adminsuidsetup $user;
+
+my @where = ();
+
+push @where, 'agentnum = '. $dbh->quote($opt{a}) if $opt{a};
+push @where, 'cust_pay.payby = '. $dbh->quote($opt{p}) if $opt{p};
+push @where, 'cust_pay._date > '. $dbh->quote(str2time($opt{b})) if $opt{b};
+push @where, 'cust_pay._date < '. $dbh->quote(str2time($opt{e})) if $opt{e};
+
+my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : '';
+my $addl_from = 'LEFT JOIN cust_main USING( custnum )';
+
+my @payrow = qsearch( { table => 'cust_pay',
+ hashref => {},
+ select => 'count(*) AS quantity, paid',
+ addl_from => $addl_from,
+ extra_sql => $extra_sql,
+ order_by => 'GROUP BY paid',
+ }
+ );
+
+my $max = 0;
+my $sum = 0;
+foreach (@payrow) {
+ $sum += $_->quantity;
+ $max = $_->quantity if $_->quantity > $max;
+}
+my $scale = int($max/60) + 1;
+
+print "\n PAYMENTS RECEIVED";
+print " AFTER $opt{b}" if $opt{b};
+print " UNTIL $opt{e}" if $opt{e};
+print " VIA $opt{p}" if $opt{p};
+print " BY AGENT $opt{a}" if $opt{a};
+print "\n\n";
+print "Total number of payments: $sum\n\n";
+print "(each * represents $scale)\n\n" if $scale > 1;
+
+foreach my $payrow ( @payrow ) {
+ print sprintf("%10.2f", $payrow->paid),
+ ": ",
+ sprintf("%6d", $payrow->quantity),
+ "| ",
+ '*' x($payrow->quantity/$scale),
+ "\n";
+}
+
+print "\n";
+
+
+###
+# subroutines
+###
+
+sub untaint_argv {
+ foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
+ #$ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ # Date::Parse
+ $ARGV[$_] =~ /^(.*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ $ARGV[$_]=$1;
+ }
+}
+
+sub usage {
+ die "Usage:\n\n cust_pay_histogram [ -b 'begin_date' ] [ -e 'end_date' ] [ -p 'payby' ] [ -a agentnum ] user\n";
+}
+
+###
+# documentation
+###
+
+=head1 NAME
+
+cust_pay_histogram - Show a histogram of payments made for a date range.
+
+=head1 SYNOPSIS
+
+ freeside-daily [ -b 'begin_date' ] [ -e 'end_date'] [ -p 'payby' ] [ -a agentnum ] user
+
+=head1 DESCRIPTION
+
+Displays a histogram of cust_pay records in the database.
+
+ -b: Include only payments since 'begin_date'. Date is in any format Date::Parse is happy with, but be careful.
+
+ -e: Include only payments before 'end_date'. Date is in any format Date::Parse is happy with, but be careful.
+
+ -p: Only process payments with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
+
+ -a: Only process payments of customers with the specified agentnum
+
+user: From the mapsecrets file - see config.html from the base documentation
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_pay>
+
+=cut
+
diff --git a/bin/cvs2cl b/bin/cvs2cl
new file mode 100755
index 0000000..1c1bfb0
--- /dev/null
+++ b/bin/cvs2cl
@@ -0,0 +1,2 @@
+#!/bin/sh
+cvs2cl -F trunk
diff --git a/bin/drop_slony.slonik b/bin/drop_slony.slonik
new file mode 100644
index 0000000..04ffaca
--- /dev/null
+++ b/bin/drop_slony.slonik
@@ -0,0 +1,9 @@
+cluster name = freeside;
+
+node 1 admin conninfo = 'dbname=freeside host=XXX user=postgres';
+node 2 admin conninfo = 'dbname=freeside host=XXX user=postgres';
+
+drop set (id=1, origin=1);
+
+uninstall node ( id=1 );
+
diff --git a/bin/freeside-migrate-events b/bin/freeside-migrate-events
index 76643b8..3e8a6b2 100644
--- a/bin/freeside-migrate-events
+++ b/bin/freeside-migrate-events
@@ -1,14 +1,17 @@
#!/usr/bin/perl -w
use strict;
-
-use FS::UID qw(adminsuidsetup);
+#use Getopt::Std;
+use FS::UID qw( adminsuidsetup dbh );
use FS::Record qw( qsearch );
use FS::part_bill_event;
use FS::part_event;
use FS::cust_bill_event;
use FS::cust_event;
+#use vars qw( $opt_m );
+#getopts('m');
+
my $user = shift or die &usage;
adminsuidsetup($user);
@@ -16,20 +19,20 @@ my %plan2action = (
'fee' => 'fee',
'fee_percent' => 'NOTYET', #XXX need fee_percent action
'suspend' => 'suspend',
- 'suspend-if-balance' => 'NOTYET', #XXX "if balance" becomes a balance condition
+ 'suspend-if-balance' => 'suspend', #"if balance" becomes the balance cond
'suspend-if-pkgpart' => 'suspend_if_pkgpart',
'suspend-unless-pkgpart' => 'suspend_unless_pkgpart',
'cancel' => 'cancel',
'addpost' => 'addpost',
'comp' => 'NOTYET', #XXX or N/A or something
- 'credit' => 'NOTYET',
+ 'credit' => 'writeoff',
'realtime-card' => 'cust_bill_realtime_card',
'realtime-check' => 'cust_bill_realtime_check',
'realtime-lec' => 'cust_bill_realtime_lec',
'batch-card' => 'cust_bill_batch',
#?'retriable' =>
'send' => 'cust_bill_send',
- 'send_email' => 'NOTYET',
+ 'send_email' => 'cust_bill_email',
'send_alternate' => 'cust_bill_send_alternate',
'send_if_newest' => 'cust_bill_send_if_newest',
'send_agent' => 'cust_bill_send_agent',
@@ -64,7 +67,15 @@ foreach my $part_bill_event (
my %plandata = map { /^(\w+) (.*)$/; ($1, $2); }
split(/\n/, $part_bill_event->plandata);
- #XXX may need to fudge some plandata2option names!!!
+ #XXX may need to fudge some other plandata2option names
+
+ my $balanceover = 0;
+ my $honor_dundate = 0;
+
+ if ( $part_bill_event->plan eq 'suspend-if-balance' ) {
+ $balanceover = delete $plandata{'balanceover'};
+ $honor_dundate = ( (delete $plandata{'balance_honor_dundate'}) =~ /1/ );
+ }
my $part_event = new FS::part_event {
'event' => $part_bill_event->event,
@@ -86,12 +97,12 @@ foreach my $part_bill_event (
};
$error = $once->insert;
die $error if $error;
-
+
my $balance = new FS::part_event_condition {
'eventpart' => $part_event->eventpart,
'conditionname' => 'balance'
};
- $error = $balance->insert( 'balance' => 0 );
+ $error = $balance->insert( 'balance' => $balanceover );
die $error if $error;
my $cust_bill_owed = new FS::part_event_condition {
@@ -118,35 +129,59 @@ foreach my $part_bill_event (
die $error if $error;
}
+
+ if ( $honor_dundate ) {
+ my $dundate = new FS::part_event_condition {
+ 'eventpart' => $part_event->eventpart,
+ 'conditionname' => 'dundate'
+ };
+ $error = $dundate->insert();
+ die $error if $error;
+ }
#my $derror = $part_bill_event->delete;
#die "error removing part_bill_event: $derror\n" if $derror;
- foreach my $cust_bill_event (
- qsearch({
- 'table' => 'cust_bill_event',
- 'hashref' => { 'eventpart' => $part_bill_event->eventpart, },
- })
- ) {
-
- my $cust_event = new FS::cust_event {
- 'eventpart' => $part_event->eventpart,
- 'tablenum' => $cust_bill_event->invnum,
- '_date' => $cust_bill_event->_date,
- 'status' => $cust_bill_event->status,
- 'statustext' => $cust_bill_event->statustext,
- };
+# if ( $opt_m ) {
- my $cerror = $cust_event->insert;
- #die "error inserting cust_event: $cerror\n" if $cerror;
- warn "error inserting cust_event: $cerror\n" if $cerror;
-
- #my $dcerror = $cust_bill_event->delete;
- #die "error removing cust_bill_event: $dcerror\n" if $dcerror;
+ my $sth = dbh->prepare('
+ INSERT INTO cust_event ( eventpart, tablenum, _date, status, statustext )
+ SELECT ? , invnum , _date, status, statustext
+ FROM cust_bill_event WHERE eventpart = ?
+ ') or die dbh->errstr;
- print ".";
+ $sth->execute( $part_event->eventpart, $part_bill_event->eventpart )
+ or die $sth->errstr;
- }
+# } else {
+#
+# foreach my $cust_bill_event (
+# qsearch({
+# 'table' => 'cust_bill_event',
+# 'hashref' => { 'eventpart' => $part_bill_event->eventpart, },
+# })
+# ) {
+#
+# my $cust_event = new FS::cust_event {
+# 'eventpart' => $part_event->eventpart,
+# 'tablenum' => $cust_bill_event->invnum,
+# '_date' => $cust_bill_event->_date,
+# 'status' => $cust_bill_event->status,
+# 'statustext' => $cust_bill_event->statustext,
+# };
+#
+# my $cerror = $cust_event->insert;
+# #die "error inserting cust_event: $cerror\n" if $cerror;
+# warn "error inserting cust_event: $cerror\n" if $cerror;
+#
+# #my $dcerror = $cust_bill_event->delete;
+# #die "error removing cust_bill_event: $dcerror\n" if $dcerror;
+#
+# print ".";
+#
+# }
+#
+# }
print "\n";
@@ -181,6 +216,8 @@ Doesn't migrate reasons.
Doesn't delete the old events (which is not a big deal, since the new code
won't run them...)
+Can take lots of memory for large databases.
+
=head1 SEE ALSO
=cut
diff --git a/bin/fs-migrate-cust_tax_exempt b/bin/fs-migrate-cust_tax_exempt
index ede80b0..35c74ff 100755
--- a/bin/fs-migrate-cust_tax_exempt
+++ b/bin/fs-migrate-cust_tax_exempt
@@ -23,7 +23,7 @@ my $fuz = 7; #seconds
#site-specific rewrites
my %rewrite = (
#cust_tax_exempt.exemptnum => { 'field' => 'newvalue', ... },
- '23' => { month=>10, year=>2005, invnum=>1640 },
+# '23' => { month=>10, year=>2005, invnum=>1640 },
#etc.
);
diff --git a/bin/generate-table-module b/bin/generate-table-module
index 509feed..16a23e5 100755
--- a/bin/generate-table-module
+++ b/bin/generate-table-module
@@ -66,6 +66,17 @@ close SRC;
close DEST;
###
+# add to FS/FS/Mason.pm
+###
+
+# it needs to be:
+# 1. disablable (have an option to turn it off)
+# 2. documented in the schema change docs
+#
+#my $magic = '# Sammath Naur';
+#system("perl -pi -e 's/$magic/use FS::$table;\n $magic/' FS/FS/Mason.pm");
+
+###
# add FS/t/table.t
###
diff --git a/bin/h_cust_main-wipe_paycvv b/bin/h_cust_main-wipe_paycvv
new file mode 100755
index 0000000..d34c15f
--- /dev/null
+++ b/bin/h_cust_main-wipe_paycvv
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+
+use strict;
+use FS::UID qw(adminsuidsetup dbh);
+use FS::Record; #buh?
+
+my $user = shift or die 'usage';
+adminsuidsetup $user;
+
+while (1) {
+
+ my $sql = ' UPDATE h_cust_main SET paycvv = NULL
+ WHERE historynum IN ( SELECT historynum FROM h_cust_main
+ WHERE paycvv IS NOT NULL LIMIT 8192 )';
+# WHERE paycvv IS NOT NULL LIMIT 1 )';
+
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+
+ print '.'; $|=1;
+
+ my $rv = $sth->execute;
+
+ dbh->commit or die dbh->errstr;
+
+ last if $rv == 0;
+
+}
+
+print "\n";
+
diff --git a/bin/make-pkg-fruit b/bin/make-pkg-fruit
new file mode 100755
index 0000000..61d707f
--- /dev/null
+++ b/bin/make-pkg-fruit
@@ -0,0 +1,172 @@
+#!/usr/bin/perl -w
+
+use strict;
+use FS::UID qw( adminsuidsetup );
+use FS::Record qw( qsearch qsearchs );
+use FS::part_export;
+use FS::export_svc;
+use FS::pkg_svc;
+use FS::part_svc;
+use FS::part_pkg;
+use FS::cust_svc;
+use FS::svc_Common;
+use FS::svc_broadband;
+use FS::part_svc_router;
+
+my $exporttype = 'prizm';
+my $pkg_property = 'pkg';
+my $svc_property = 'performance_profile';
+
+my $user = shift or die &usage;
+
+$FS::svc_Common::noexport_hack = 1;
+$FS::cust_svc::ignore_quantity = 1;
+$FS::UID::AutoCommit = 0;
+
+my $DEBUG = 0;
+
+my $dbh = adminsuidsetup($user);
+
+my @exportnum = map { $_->exportnum }
+ qsearch( 'part_export', { 'exporttype' => $exporttype } );
+
+die "no $exporttype exports found\n" unless scalar(@exportnum);
+
+my %pkg_svc_map = ();
+
+my @old_svcpart = ();
+push @old_svcpart, map { $_->svcpart }
+ qsearch ( 'export_svc', { 'exportnum' => $_ } )
+ foreach @exportnum;
+
+die "no svcparts found\n" unless scalar(@old_svcpart);
+
+foreach (@old_svcpart) {
+ foreach my $pkg_svc ( qsearch( 'pkg_svc',
+ { 'svcpart' => $_,
+ 'quantity' => { 'op' => '>',
+ 'value' => '0',
+ },
+ }
+ )
+ )
+ {
+ warn "updating package ". $pkg_svc->pkgpart. "\n" if $DEBUG;
+ my $pkg_from = $pkg_svc->part_pkg->$pkg_property;
+ unless ( $pkg_svc_map{ $pkg_from }{ $pkg_svc->svcpart } ) {
+ my $old_part_svc = $pkg_svc->part_svc;
+ my $part_svc = new FS::part_svc( { $old_part_svc->hash } );
+ $part_svc->svcpart('');
+
+ my $svcdb = $part_svc->svcdb;
+ foreach ( $old_part_svc->all_part_svc_column ) {
+ my $formatter = FS::part_svc->svc_table_fields($svcdb)->{$_}->{format}
+ || sub { shift };
+
+ $part_svc->setfield( $svcdb.'__'.$_->columnname.'_flag', $_->columnflag);
+ $part_svc->setfield( $svcdb.'__'.$_->columnname,
+ &$formatter($_->columnvalue)
+ );
+ }
+
+ my $formatter =
+ FS::part_svc->svc_table_fields($svcdb)->{$svc_property}->{format}
+ || sub { shift };
+ $part_svc->setfield( $svcdb.'__'.$svc_property.'_flag', 'F');
+ $part_svc->setfield( $svcdb.'__'.$svc_property,
+ &$formatter($pkg_svc->part_pkg->$pkg_property)
+ );
+ my $error = $part_svc->insert( [],
+ { map { $_->exportnum => 1 }
+ $old_part_svc->part_export
+ },
+ );
+ die "error inserting service: $error\n" if $error;
+
+ # this part is specific to svc_broadband
+ foreach (qsearch( 'part_svc_router', { 'svcpart' => $pkg_svc->svcpart } ))
+ {
+ my $part_svc_router = new FS::part_svc_router( { $_->hash } );
+ $part_svc_router->svcrouternum( '' );
+ $part_svc_router->svcpart( $part_svc->svcpart );
+ my $error = $part_svc_router->insert;
+ die "error associating service with router: $error\n" if $error;
+ }
+
+ $pkg_svc_map{ $pkg_from }{ $pkg_svc->svcpart } = $part_svc->svcpart;
+
+ }
+
+ my $new_pkg_svc = new FS::pkg_svc( { $pkg_svc->hash } );
+ $new_pkg_svc->svcpart( $pkg_svc_map{ $pkg_from }{ $pkg_svc->svcpart } );
+ my $error = $pkg_svc->delete;
+ die "error removing old service from package: $error\n" if $error;
+ $error = $new_pkg_svc->insert;
+ die "error adding new service to package: $error\n" if $error;
+
+ }
+}
+warn "done with packages\n" if $DEBUG;
+
+foreach my $svcpart ( @old_svcpart ) {
+ foreach my $cust_svc ( qsearch( 'cust_svc', { 'svcpart' => $svcpart } ) ) {
+ my $svc_x = $cust_svc->svc_x;
+ my $cust_pkg = $cust_svc->cust_pkg;
+ die "can't handle unattached service ". $cust_svc->svcnum unless $cust_pkg;
+ my $pkg_from = $cust_pkg->part_pkg->$pkg_property;
+ $svc_x->setfield( $svc_property, $pkg_from );
+ $svc_x->setfield( 'svcpart', $pkg_svc_map{ $pkg_from }{ $svcpart } );
+ my $error = $svc_x->replace;
+ die "error replacing service ". $svc_x->svcnum. ": $error\n" if $error;
+
+ $cust_svc->svcpart( $pkg_svc_map{ $pkg_from }{ $svcpart } );
+ $error = $cust_svc->replace;
+ die "error replacing customer service ". $cust_svc->svcnum. ": $error\n"
+ if $error;
+ }
+
+ my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+ die "can't find old part_svc!" unless $part_svc;
+
+ my $new_part_svc = new FS::part_svc( { $part_svc->hash } );
+ $new_part_svc->disabled('Y');
+ my $svcdb = $part_svc->svcdb;
+ foreach ( $part_svc->all_part_svc_column ) {
+ my $formatter = FS::part_svc->svc_table_fields($svcdb)->{$_}->{format}
+ || sub { shift };
+
+ $part_svc->setfield( $svcdb.'__'.$_->columnname.'_flag', $_->columnflag);
+ $part_svc->setfield( $svcdb.'__'.$_->columnname,
+ &$formatter($_->columnvalue)
+ );
+ }
+ my $error = $new_part_svc->replace($part_svc, '1.3-COMPAT');
+ die "error disabling service: $error\n" if $error;
+}
+
+$dbh->commit or die $dbh->errstr;
+$dbh->disconnect or die $dbh->errstr;
+
+
+sub usage {
+ die "Usage:\n\n make-pkg-fruit user\n";
+}
+
+=head1 NAME
+
+make-pkg-fruit - Tool to migrate package properties to services
+
+=head1 SYNOPSIS
+
+ make-pkg-fruit
+
+=head1 DESCRIPTION
+
+Multiplies out services with package properties and migrates package
+definitions and customer services to the new services. Read the source.
+
+=head1 SEE ALSO
+
+=cut
+
+1;
diff --git a/bin/mapsecrets2access_user b/bin/mapsecrets2access_user
index 945f130..d632360 100755
--- a/bin/mapsecrets2access_user
+++ b/bin/mapsecrets2access_user
@@ -24,7 +24,7 @@ unless ( $supergroup ) {
my $error = $supergroup->insert;
die $error if $error;
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => $supergroup->groupnum,
diff --git a/bin/move-customers b/bin/move-customers
new file mode 100755
index 0000000..a7ea197
--- /dev/null
+++ b/bin/move-customers
@@ -0,0 +1,678 @@
+#!/usr/bin/perl -w
+
+#script to move customers from one installation to another
+# source is remote, destination is local
+# script is kinda-specific to a somewhat old source installation (1.7? older?)
+# target installation has to be 1.9 (after 9/2009)
+
+use strict;
+use vars qw( $sdbh );
+use DBI;
+use FS::UID qw( adminsuidsetup dbh );
+use FS::Schema qw( dbdef );
+use FS::Record qw( qsearchs );
+use FS::agent;
+use FS::cust_main;
+use FS::part_pkg;
+use FS::part_svc;
+use FS::cust_bill_ApplicationCommon;
+use FS::svc_Common;
+use FS::cust_event;
+use FS::svc_domain;
+use FS::cust_pkg;
+
+my $DANGEROUS = 0;
+my $DRY = 0;
+
+#ssh -p 2222 -L 1080:66.209.32.4:7219 -L 5454:localhost:5432 66.209.32.4
+
+#my $source_datasrc = 'DBI:Pg:host=66.209.32.4;dbname=freeside;sslmode=require';
+my $source_datasrc = 'DBI:Pg:host=localhost;port=5454;dbname=freeside';
+my $source_user = 'readonly';
+my $source_pw = '';
+
+#my @source_agents = ( 2, 7, 3, 4, 5, 1 );
+my @source_agents = ( 1, 2, 3, 4, 5, 7 );
+
+my $dest_agent_typenum = 12;
+
+my $dest_refnum = 60;
+
+my $dest_legacy_credit_reasontype = 5;
+
+my $dest_pkg_classnum = 6;
+
+my %domsvc_map = (
+ 1 => 20450,
+ 3653 => 20162,
+ 7634 => 20451,
+);
+
+#testing
+#my %eventparts = (
+# 'CARD' => [ 1, ],
+# 'CHEK' => [],
+# 'BILL' => [],
+# 'DCHK' => [],
+# 'DCRD' => [],
+# 'COMP' => [],
+#);
+#production
+my %eventparts = (
+ 'CARD' => [ 1, ],
+ 'CHEK' => [ 2, ],
+ 'BILL' => [ 5, ],
+ 'DCHK' => [ 12, ],
+ 'DCRD' => [ 15, ],
+ 'COMP' => [],
+);
+
+#--
+
+# target(local) setup
+
+my $user = shift
+ or die "Usage:\n (edit variables at top of script and then)\n".
+ " move-customers user\n";
+adminsuidsetup $user;
+
+$FS::cust_main::ignore_expired_card = 1;
+$FS::cust_main::ignore_expired_card = 1;
+$FS::part_pkg::skip_pkg_svc_hack = 1;
+$FS::part_pkg::skip_pkg_svc_hack = 1;
+$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1;
+$FS::cust_bill_ApplicationCommon::skip_apply_to_lineitems_hack = 1;
+$FS::svc_Common::noexport_hack = 1;
+$FS::svc_Common::noexport_hack = 1;
+$FS::svc_domain::whois_hack = 1;
+$FS::svc_domain::whois_hack = 1;
+$FS::cust_pkg::disable_agentcheck = 1;
+$FS::cust_pkg::disable_agentcheck = 1;
+
+my $void_paynum = 2147483646; #top of int range
+
+# --
+
+# source(remote) setup
+
+$sdbh = DBI->connect($source_datasrc, $source_user, $source_pw)
+ or die $DBI::errstr;
+
+$sdbh->{ChopBlanks} = 1;
+
+# --
+
+my %map = ();
+$map{'_DOMSVC'} = \%domsvc_map;
+
+import_table('pkg_class', 'nomap' => 1);
+import_table('svc_acct_pop', 'nomap' => 1);
+
+#XXX
+#import_table('reason_type', 'nomap' => 1);
+#foreach my $src_typenum ( keys %{ $map{'reason_type'} } ) {
+# import_table('reason', 'reason_type' => $src_typenum,
+# 'search' => 'reason_type',
+# 'map' => 'reason_type',
+# );
+#}
+
+my $agent_sth = $sdbh->prepare(
+ 'SELECT * FROM agent WHERE agentnum IN ( '. join(',', @source_agents ). ')'
+) or die $sdbh->errstr;
+
+$agent_sth->execute or die $agent_sth->errstr;
+
+
+while ( my $agentrow = $agent_sth->fetchrow_hashref ) {
+
+ my $src_agent = $agentrow->{'agent'};
+
+ warn "importing customers for $src_agent\n";
+
+ my $agent = qsearchs('agent', { 'agent' => $src_agent, 'disabled' => '' } );
+
+ if ( $agent ) {
+
+ warn " using existing agentnum ". $agent->agentnum. "\n";
+
+ if ( $DANGEROUS ) {
+ warn "DELETING ALL CUSTOMERS OF $src_agent locally \n";
+
+ foreach my $statement (
+ 'DELETE FROM cust_main WHERE agentnum = '. $agent->agentnum,
+ ( map { "DELETE FROM $_
+ WHERE 0 = ( SELECT COUNT(*) FROM cust_main
+ WHERE cust_main.custnum = $_.custnum )
+ "
+ }
+ qw(
+ cust_credit
+ cust_main_invoice
+ cust_main_note
+ cust_pay
+ cust_refund
+ )
+ )
+ #pkg_class, part_pkg_pop
+ #part_pkg, pkg_svc, part_svc, part_svc_column
+ #XXX more... does it matter?
+ ) {
+
+ #warn $statement;
+ my $sth = dbh->prepare($statement) or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+
+ dbh->commit or die dbh->errstr;
+
+ }
+
+ } else {
+
+ warn " creating new agent...\n";
+
+ $agent = new FS::agent { 'agent' => $src_agent,
+ 'typenum' => $dest_agent_typenum };
+ my $error = $agent->insert;
+ die $error if $error;
+
+ warn " agentnum ". $agent->agentnum. "\n";
+
+ }
+
+ $map{'agent'}->{ $agentrow->{'agentnum'} } = $agent->agentnum;
+
+}
+
+ #my $customer_sth = $sdbh->prepare(
+ # 'SELECT * FROM cust_main WHERE agentnum = '. $agentrow->{'agentnum'}
+ #) or die $sdbh->errstr;
+my $customer_sth = $sdbh->prepare(
+ 'SELECT * FROM cust_main WHERE agentnum IN ( '. join(',', @source_agents ). ')
+ ORDER BY custnum'
+) or die $sdbh->errstr;
+
+$customer_sth->execute or die $customer_sth->errstr;
+
+while ( my $customerrow = $customer_sth->fetchrow_hashref ) {
+
+ #use Data::Dumper;
+ # warn Dumper($customerrow);
+ my $src_custnum = $customerrow->{'custnum'};
+
+ warn " $src_custnum has referral_custnum ". $customerrow->{'referral_custnum'}
+ if $customerrow->{'referral_custnum'};
+
+ my $cust_main = new FS::cust_main {
+ %{ $customerrow },
+ 'custnum' => '',
+ 'referral_custnum' => '', #restore afterwords?
+ 'refnum' => $dest_refnum,
+ 'agentnum' => $map{'agent'}->{ $customerrow->{'agentnum'} },
+ 'agent_custid' => $src_custnum,
+ };
+
+ #$cust_main->ship_country('') if $cust_main->ship_country eq ' ';
+ #$cust_main->tax('') if $cust_main->tax =~ /^\s+$/;
+
+ my $error = $cust_main->insert;
+ if ( $error ) {
+ warn "*** WARNING: error importing customer src custnum $src_custnum: $error";
+ use Data::Dumper;
+ warn Dumper($cust_main) if $src_custnum == 6854;
+ next;
+ }
+
+ warn "inserting dest customer ". $cust_main->custnum. " for $src_custnum\n";
+
+ $map{'cust_main'}->{$src_custnum} = $cust_main->custnum;
+
+ #now import the relations, easy and hard:
+
+ import_table( 'cust_main_note', 'custnum' => $src_custnum );
+
+ import_table( 'cust_pay', 'custnum' => $src_custnum,
+ #ivan showing up as cust_pay otaker
+ # old db doesn't have cust_pay.otaker, pull it from history
+ 'preinsert_callback' => sub {
+ my($row, $cust_pay) = @_;
+
+ my $sth = $sdbh->prepare(
+ "SELECT history_user FROM h_cust_pay WHERE history_action = 'insert'
+ AND paynum = ". $row->{'paynum'}
+ ) or die $sdbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my $otaker = $sth->fetchrow_arrayref->[0];
+
+ $cust_pay->otaker($otaker);
+ },
+ );
+
+ # crap, cust_credit.reason is text in old db
+#*** WARNING: error importing cust_credit src crednum 2200: failed to set reason for [ FS::cust_credit ]: at ./move-customers line 232.
+ import_table( 'cust_credit', 'custnum' => $src_custnum,
+ 'insert_opts' => [ 'reason_type' => $dest_legacy_credit_reasontype ],
+ 'preinsert_callback' => sub {
+ my($row, $object) = @_;
+ $object->set('reason', '(none)') if $object->get('reason') =~ /^\s*$/;
+ },
+ );
+
+ import_table( 'cust_refund', 'custnum' => $src_custnum,
+ 'post_callback' => sub {
+ #my( $src_refundnum, $dst_refundnum ) = @_;
+ my $src_refundnum = shift;
+
+ # cust_credit_refund (map refundnum and crednum...)
+ import_table( 'cust_credit_refund',
+ 'refundnum' => $src_refundnum,
+ 'search' => 'refundnum',
+ 'map' => 'cust_refund',
+ 'map2' => 'cust_credit',
+ 'map2key' => 'crednum',
+ );
+
+ # cust_pay_refund (map refundnum and paynum...)
+ import_table( 'cust_pay_refund',
+ 'refundnum' => $src_refundnum,
+ 'search' => 'refundnum',
+ 'map' => 'cust_refund',
+ 'map2' => 'cust_pay',
+ 'map2key' => 'paynum',
+ );
+
+ },
+ );
+
+ # dunno what's up with this (ship_country ' ', fixed)
+#*** WARNING: error importing customer src custnum 6854: Illegal (name) (error code illegal_name) ship_last: at ./move-customers line 129.
+
+ # cust_pay_void
+ import_table( 'cust_pay_void', 'custnum' => $src_custnum,
+ 'preinsert_callback' => sub {
+ my($row, $object) = @_;
+ $object->paynum( $void_paynum-- );
+ },
+ );
+
+ # (not in old db: cust_attachment, cust_statement, cust_location,
+ # cust_main_exemption, cust_pay_pending )
+ # (not used in old db: cust_pay_batch, cust_tax_exempt)
+ # (not useful to migrate: queue)
+
+ #werid direct cust_main relations:
+
+ # cust_pkg (part_pkg, part_svc, etc.)
+ import_table( 'cust_pkg', 'custnum' => $src_custnum,
+ 'preinsert_callback' => sub {
+ my($row, $object) = @_;
+ my $src_pkgpart = $row->{'pkgpart'} or die "wtf";
+ my $dest_pkgpart = $map{'part_pkg'}->{$src_pkgpart};
+ if ( $dest_pkgpart ) {
+ $object->pkgpart($dest_pkgpart);
+ return;
+ }
+
+ my $sth = $sdbh->prepare(
+ "SELECT * FROM part_pkg WHERE pkgpart = $src_pkgpart"
+ ) or die $sdbh->errstr;
+
+ $sth->execute or die $sth->errstr;
+
+ my $part_pkg_row = $sth->fetchrow_hashref
+ or die "cust_pkg.pkgpart missing in part_pkg?!";
+
+ my $hashref = {
+ %{ $part_pkg_row },
+ 'pkgpart' => '',
+ };
+ my $src_classnum = $part_pkg_row->{'classnum'};
+ $hashref->{'classnum'} = $map{'pkg_class'}->{ $src_classnum }
+ if $src_classnum;
+
+ my $part_pkg = new FS::part_pkg $hashref;
+
+ #$part_pkg->setuptax('') if $part_pkg->setuptax =~ /^\s+$/;
+ #$part_pkg->recurtax('') if $part_pkg->recurtax =~ /^\s+$/;
+
+ my $error = $part_pkg->insert( 'options' => {} );
+ die "*** FATAL: error importing part_pkg src pkgpart $src_pkgpart ".
+ ": $error"
+ if $error;
+
+ $map{ 'part_pkg' }->{ $part_pkg_row->{'pkgpart'} } = $part_pkg->pkgpart;
+
+ # part_pkg_option
+ import_table( 'part_pkg_option',
+ 'pkgpart' => $src_pkgpart,
+ 'search' => 'pkgpart',
+ 'map' => 'part_pkg',
+ );
+
+ my $osth = $sdbh->prepare(
+ "SELECT * FROM part_pkg_option WHERE pkgpart = $src_pkgpart"
+ ) or die $sdbh->errstr;
+
+ # pkg_svc, part_svc, part_svc_column
+ import_table( 'pkg_svc',
+ 'pkgpart' => $src_pkgpart,
+ 'search' => 'pkgpart',
+ 'map' => 'part_pkg',
+ 'preinsert_callback' => sub {
+
+ my($row, $object) = @_;
+ my $src_svcpart = $row->{'svcpart'} or die "wtf2";
+ my $dest_svcpart = $map{'part_svc'}->{$src_svcpart};
+ if ( $dest_svcpart ) {
+ $object->svcpart($dest_svcpart);
+ return;
+ }
+
+ my $sth = $sdbh->prepare(
+ "SELECT * FROM part_svc WHERE svcpart = $src_svcpart"
+ ) or die $sdbh->errstr;
+
+ $sth->execute or die $sth->errstr;
+
+ my $part_svc_row = $sth->fetchrow_hashref
+ or die "svcpart missing in part_svc?!";
+
+ my $hashref = {
+ %{ $part_svc_row },
+ 'svcpart' => '',
+ };
+
+ my $part_svc = new FS::part_svc $hashref;
+ $part_svc->disabled('') if $part_svc->disabled =~ /^\s+$/;
+ my $error = $part_svc->insert;
+ die "*** FATAL: error importing part_svc src svcpart $src_svcpart ".
+ ": $error"
+ if $error;
+
+ $map{ 'part_svc' }->{ $part_svc_row->{'svcpart'} } = $part_svc->svcpart;
+
+ # part_svc_column
+ import_table( 'part_svc_column',
+ 'svcpart' => $src_svcpart,
+ 'search' => 'svcpart',
+ 'map' => 'part_svc',
+ 'preinsert_callback' => sub {
+ my($row, $object) = @_;
+ if ( $object->columnname eq 'domsvc' ) {
+ $object->columnvalue( $map{'_DOMSVC'}->{ $object->columnvalue } );
+ }
+ },
+ );
+
+ #what we came here for in the first place
+ $object->svcpart( $part_svc->svcpart );
+
+ }
+ );
+
+ #what we came here for in the first place
+ $object->pkgpart( $part_pkg->pkgpart );
+
+ },
+
+ 'post_callback' => sub {
+ #my( $src_pkgnum, $dst_pkgnum ) = @_;
+ my $src_pkgnum = shift;
+
+ #XXX grr... action makes this very hard...
+ ## cust_pkg_reason (shit, and bring in/remap reasons)
+ #import_table( 'cust_pkg_reason',
+ # 'pkgnum' => $src_pkgnum,
+ # 'search' => 'pkgnum',
+ # 'map' => 'cust_pkg',
+ # 'map2' => 'reason',
+ # 'map2key' => 'reasonnum',
+ # );
+
+ #cust_svc
+ import_table( 'cust_svc',
+ 'pkgnum' => $src_pkgnum,
+ 'search' => 'pkgnum',
+ 'map' => 'cust_pkg',
+ 'map2' => 'part_svc',
+ 'map2key' => 'svcpart',
+ 'post_callback' => sub {
+ #my( $src_svcnum, $dst_svcnum ) = @_;
+ my $src_svcnum = shift;
+
+ #svc_domain
+ import_table( 'svc_domain',
+ 'svcnum' => $src_svcnum,
+ 'search' => 'svcnum',
+ 'map' => 'cust_svc',
+ 'noblank_primary' => 1,
+ );
+
+ #svc_acct
+ import_table( 'svc_acct',
+ 'svcnum' => $src_svcnum,
+ 'search' => 'svcnum',
+ 'map' => 'cust_svc',
+ 'noblank_primary' => 1,
+ 'map2' => 'svc_acct_pop',
+ 'map2key' => 'popnum',
+ #'map3' => 'svc_domain',
+ 'map3' => '_DOMSVC',
+ 'map3key' => 'domsvc',
+ );
+
+ #radius_usergroup
+ import_table( 'radius_usergroup',
+ 'svcnum' => $src_svcnum,
+ 'search' => 'svcnum',
+ 'map' => 'cust_svc',
+ );
+
+ #other svc_ tables not in old db
+
+ },
+ );
+
+ },
+
+
+
+
+ );
+ # end of cust_pkg (part_pkg, part_svc, etc.)
+
+ # cust_bill (invnum move)
+ import_table( 'cust_bill', 'custnum' => $src_custnum,
+ 'preinsert_callback' => sub {
+ my($row, $object) = @_;
+ $object->agent_invid( $row->{'invnum'} );
+ },
+ 'post_callback' => sub {
+ my( $src_invnum, $dst_invnum ) = @_;
+ #my $src_invnum = shift;
+
+ # cust_bill_pkg ( map invnum and pkgnum... )
+ import_table( 'cust_bill_pkg',
+ 'invnum' => $src_invnum,
+ 'search' => 'invnum',
+ 'map' => 'cust_bill',
+ 'map2' => 'cust_pkg',
+ 'map2key' => 'pkgnum',
+ 'post_callback' => sub {
+ my $src_billpkgnum = shift;
+
+ import_table( 'cust_bill_pkg_detail',
+ 'billpkgnum' => $src_billpkgnum,
+ 'search' => 'billpkgnum',
+ 'map' => 'cust_bill_pkg',
+ 'addl_from' => 'left join cust_bill_pkg using ( invnum, pkgnum )',
+ );
+
+ },
+ );
+
+ # cust_credit_bill (map invnum and crednum... )
+ import_table( 'cust_credit_bill',
+ 'invnum' => $src_invnum,
+ 'search' => 'invnum',
+ 'map' => 'cust_bill',
+ 'map2' => 'cust_credit',
+ 'map2key' => 'crednum',
+ 'post_callback' => sub {
+ my $src_creditbillnum = shift;
+ #map creditbillnum and billpkgnum
+ import_table( 'cust_credit_bill_pkg',
+ 'creditbillnum' => $src_creditbillnum,
+ 'search' => 'creditbillnum',
+ 'map' => 'cust_credit_bill',
+ 'map2' => 'cust_bill_pkg',
+ 'map2key' => 'billpkgnum',
+ );
+
+ },
+ );
+
+ # cust_bill_pay (map invnum and paynum...)
+ import_table( 'cust_bill_pay',
+ 'invnum' => $src_invnum,
+ 'search' => 'invnum',
+ 'map' => 'cust_bill',
+ 'map2' => 'cust_pay',
+ 'map2key' => 'paynum',
+ 'post_callback' => sub {
+ my $src_billpaynum = shift;
+ #map billpaynum and billpkgnum
+ import_table( 'cust_bill_pay_pkg',
+ 'billpaynum' => $src_billpaynum,
+ 'search' => 'billpaynum',
+ 'map' => 'cust_bill_pay',
+ 'map2' => 'cust_bill_pkg',
+ 'map2key' => 'billpkgnum',
+ );
+ },
+ );
+
+ #need to do something about events. mark initial stuff as done
+ foreach my $eventpart ( @{ $eventparts{$cust_main->payby} } ) {
+
+ my $cust_event = new FS::cust_event {
+ 'eventpart' => $eventpart,
+ 'tablenum' => $dst_invnum,
+ '_date' => time, # XXX something? probably not
+ 'status' => 'done',
+ };
+
+ my $error = $cust_event->insert;
+ die "*** FATAL: error inserting cust_event for eventpart $eventpart,".
+ " tablenum (invnum) $dst_invnum: $error"
+ if $error;
+
+ }
+
+ },
+ );
+
+ # ---
+
+ # (not in old db: cust_pkg_detail)
+ # (not used in old db: cust_bill_pay_batch, cust_pkg_option)
+
+ # ---
+
+ # (not in old db: cust_bill_pkg_display, cust_bill_pkg_tax_location,
+ # cust_bill_pkg_tax_rate_location, cust_tax_adjustment, cust_svc_option, )
+ # (not used in old db: cust_tax_exempt_pkg)
+
+ #do this last, so no notices go out
+ import_table( 'cust_main_invoice', 'custnum' => $src_custnum );
+
+ #dbh->commit or die dbh->errstr;
+ warn "customer ". $cust_main->custnum. " inserted\n";
+ #exit;
+
+}
+
+
+warn "import successful!\n";
+if ( $DRY ) {
+ warn "rolling back (dry run)\n";
+ dbh->rollback or die dbh->errstr;
+ warn "rolled back\n"
+} else {
+ warn "commiting\n";
+ dbh->commit or die dbh->errstr;
+ warn "committed\n";
+}
+
+sub import_table {
+ my( $table, %opt ) = @_;
+
+ eval "use FS::$table;";
+ die $@ if $@;
+
+ my $map = $opt{'map'} || 'cust_main';
+ my $search = $opt{'search'} || 'custnum';
+
+ $opt{'insert_opts'} ||= [];
+
+ my $primary_key = dbdef->table($table)->primary_key;
+
+ my $addl_from = defined($opt{'addl_from'}) ? $opt{'addl_from'} : '';
+
+ my $sth = $sdbh->prepare(
+ "SELECT * FROM $table $addl_from ".
+ ( $opt{'nomap'} ? '' : " WHERE $search = ". $opt{$search} )
+ ) or die $sdbh->errstr;
+
+ $sth->execute or die "(searching $table): ". $sth->errstr;
+
+ while ( my $row = $sth->fetchrow_hashref ) {
+ #my $src_custnum = $customerrow->{'custnum'};
+
+ my $hashref = { %$row };
+ $hashref->{$primary_key} = ''
+ unless $opt{'noblank_primary'};
+ $hashref->{ $search } = $map{$map}->{ $row->{$search} }
+ unless $opt{'nomap'};
+
+ if ( $opt{'map2'} ) {
+ my $key2 = $opt{'map2key'};
+ $hashref->{$key2} = $map{ $opt{'map2'} }->{ $row->{$key2} }
+ unless $opt{map2key} eq 'pkgnum' && ( $row->{$key2} eq '0'
+ || $row->{$key2} eq '-1'
+ )
+ or ! defined($row->{$key2})
+ or $row->{$key2} eq '';
+ #warn "map $opt{map2}.$opt{map2key}: ". $row->{$key2}. " to ". $map{ $opt{'map2'} }->{ $row->{$key2} };
+ }
+
+ if ( $opt{'map3'} ) {
+ my $key3 = $opt{'map3key'};
+ $hashref->{$key3} = $map{ $opt{'map3'} }->{ $row->{$key3} };
+ }
+
+ my $object = eval "new FS::$table \$hashref;";
+ die $@ if $@;
+
+ &{ $opt{preinsert_callback} }( $row, $object )
+ if $opt{preinsert_callback};
+
+ my $error = $object->insert( @{ $opt{'insert_opts'} } );
+ if ( $error ) {
+ warn "*** WARNING: error importing $table src $primary_key ". $row->{$primary_key}. ": $error";
+ next;
+ }
+
+ $map{ $table }->{ $row->{$primary_key} } = $object->get($primary_key);
+
+ &{ $opt{post_callback} }( $row->{$primary_key}, $object->get($primary_key) )
+ if $opt{post_callback};
+
+ }
+
+}
+
+1;
+
diff --git a/bin/ping b/bin/ping
new file mode 100755
index 0000000..605a204
--- /dev/null
+++ b/bin/ping
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+
+use Net::Ping;
+use Net::SSH qw( ssh_cmd );
+use Email::Send;
+
+my @other_hosts = ( 'freeside.biz', 'saturn5.com' );
+
+my( $machine, @emails ) = @ARGV;
+die "no notification email given" unless @emails;
+
+my $ping = new Net::Ping; # 'icmp'; #requires root
+
+my $pong = '';
+# can't tcp ping... $ping->ping($machine) and
+$pong = eval { ssh_cmd('freeside@'.$machine, 'echo pong') };
+#(command ignored if authorized_keys setup w/command=)
+
+if ( $@ || $pong !~ /pong/ ) { #houston, we may have a problem
+
+ #warn "can't reach $machine, checking @other_hosts\n";
+
+ #let's do a sanity check, can we see some other hosts?
+ exit unless grep $ping->ping($_), @other_hosts;
+
+ #uh-oh, this is bad.
+
+ #warn "checking to see if we've alerted on this recently\n";
+
+ #but we don't want to be too noisy, have we alerted on this in the last 24h?
+ my $file = "/tmp/alert-$machine";
+ exit if -e $file && -M $file < 1;
+
+ open(FILE, ">>$file");
+ print FILE "emailing\n";
+ close FILE;
+
+ #warn "emailing alerts\n";
+
+ foreach my $email ( @emails ) {
+
+ my $message = <<"__MESSAGE__";
+From: support\@freeside.biz
+To: $email
+Subject: ALERT - $machine
+
+ALERT: $machine appears to be down.
+
+__MESSAGE__
+
+ my $sender = Email::Send->new({mailer => 'SMTP'});
+ $sender->mailer_args([Host => 'mail.freeside.biz']);
+ $sender->send($message);
+
+ }
+
+}
+
diff --git a/bin/print-directory_assist b/bin/print-directory_assist
new file mode 100755
index 0000000..4c5e4a8
--- /dev/null
+++ b/bin/print-directory_assist
@@ -0,0 +1,12 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my $acs = `cut -c1-3 ../etc/areacodes.txt`;
+
+my $plus = '';
+foreach my $npa ( split(/\n/, $acs ) ) {
+ warn $npa;
+ $plus .= $npa. '5551212,';
+}
+print "$plus\n";
diff --git a/bin/rebill b/bin/rebill
new file mode 100755
index 0000000..4f05238
--- /dev/null
+++ b/bin/rebill
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Std;
+use Date::Parse;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw( qsearch );
+use cust_main_special;
+
+&untaint_argv; #what it sounds like (eww)
+use vars qw(%opt);
+getopts("p:a:d:sy:n", \%opt);
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+my (@custnums) = @ARGV;
+
+my $time = $opt{d} ? str2time($opt{d}) : $^T;
+$time += $opt{y} * 86400 if $opt{y};
+my $invoice_time = $opt{n} ? $^T : $time;
+
+my %args = (
+ 'time' => $time,
+ 'invoice_time' => $invoice_time,
+ 'actual_time' => $^T, #when freeside-bill was started
+ #(not, when using -m, freeside-queued)
+ 'resetup' => ( $opt{'s'} ? $opt{'s'} : 0 ),
+ 'backbill' => $time,
+);
+
+my $extra_sql = ( $opt{a} || $opt{p} ) ? ' AND ' : ' WHERE ';
+$extra_sql .= "( ". join( ' OR ', map{ "custnum = $_" } @custnums ). " )";
+$extra_sql = '' unless scalar @custnums;
+
+my @cust = qsearch( { table => 'cust_main',
+ hashref => { $opt{a} ? ( 'agentnum' => $opt{a} ) : (),
+ $opt{p} ? ( 'payby' => $opt{p} ) : (),
+ },
+ extra_sql => $extra_sql,
+ }
+ );
+
+foreach my $cust ( @cust ) {
+ my $balance = $cust->balance;
+ cust_main_special::bill($cust, %args);
+ if ($balance != $cust->balance){
+ $cust->apply_payments_and_credits;
+ my $error = $cust->collect(%args);
+ warn "Error collecting, custnum ". $cust->custnum. ": $error" if $error;
+ }
+}
+
+
+###
+# subroutines
+###
+
+sub untaint_argv {
+ foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
+ #$ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ # Date::Parse
+ $ARGV[$_] =~ /^(.*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+ $ARGV[$_]=$1;
+ }
+}
+
+sub usage {
+ die "Usage:\n\n freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] user [ custnum custnum ... ]\n";
+}
+
+###
+# documentation
+###
+
+=head1 NAME
+
+freeside-daily - Run daily billing and invoice collection events.
+
+=head1 SYNOPSIS
+
+ freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] user [ custnum custnum ... ]
+
+=head1 DESCRIPTION
+
+Bills customers and runs invoice collection events. Should be run from
+crontab daily.
+
+Bills customers. Searches for customers who are due for billing and calls
+the bill and collect methods of a cust_main object. See L<FS::cust_main>.
+
+ -d: Pretend it's 'date'. Date is in any format Date::Parse is happy with,
+ but be careful.
+
+ -y: In addition to -d, which specifies an absolute date, the -y switch
+ specifies an offset, in days. For example, "-y 15" would increment the
+ "pretend date" 15 days from whatever was specified by the -d switch
+ (or now, if no -d switch was given).
+
+ -n: When used with "-d" and/or "-y", specifies that invoices should be dated
+ with today's date, irregardless of the pretend date used to pre-generate
+ the invoices.
+
+ -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
+
+ -a: Only process customers with the specified agentnum
+
+ -s: re-charge setup fees
+
+ -v: enable debugging
+
+ -l: debugging level
+
+ -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+
+ -r: Multi-process mode dry run option
+
+ -k: skip notify_flat_delay and vacuum
+
+user: From the mapsecrets file - see config.html from the base documentation
+
+custnum: if one or more customer numbers are specified, only bills those
+customers. Otherwise, bills all customers.
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_main>, config.html from the base documentation
+
+=cut
+
diff --git a/bin/svc_acct-recalculate_usage b/bin/svc_acct-recalculate_usage
new file mode 100644
index 0000000..1b3955b
--- /dev/null
+++ b/bin/svc_acct-recalculate_usage
@@ -0,0 +1,110 @@
+#!/usr/bin/perl -w
+
+use strict;
+use vars qw($opt_s $opt_u $opt_p $opt_k);
+use Getopt::Std;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearch qsearchs);
+use FS::svc_acct;
+use FS::cust_svc;
+
+my %field2sub = (
+ 'seconds' => sub {
+ my($svc_acct, $cust_pkg) = @_;
+ $svc_acct->seconds_since_sqlradacct( $cust_pkg->last_bill, time );
+ },
+ 'upbytes' => sub {
+ my($svc_acct, $cust_pkg) = @_;
+ $svc_acct->attribute_since_sqlradacct(
+ $cust_pkg->last_bill, time, 'AcctInputOctets' );
+ },
+ 'downbytes' => sub {
+ my($svc_acct, $cust_pkg) = @_;
+ $svc_acct->attribute_since_sqlradacct(
+ $cust_pkg->last_bill, time, 'AcctOutputOctets' );
+ },
+ 'totalbytes' => sub {
+ my($svc_acct, $cust_pkg) = @_;
+ $svc_acct->attribute_since_sqlradacct(
+ $cust_pkg->last_bill, time, 'AcctInputOctets' )
+ +
+ $svc_acct->attribute_since_sqlradacct(
+ $cust_pkg->last_bill, time, 'AcctOutputOctets' )
+ ;
+ },
+);
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+my $field = shift;
+die "can only reset seconds, upbytes, downbytes or totalbytes"
+ unless $field2sub{$field};
+
+my $value = shift;
+
+#false laziness w/freeside-reexport
+getopts('s:u:p:k:');
+
+my @svc_x = ();
+if ( $opt_s ) {
+ my $cust_svc = qsearchs('cust_svc', { svcnum=>$opt_s } )
+ or die "svcnum $opt_s not found\n";
+ push @svc_x, $cust_svc->svc_x;
+} elsif ( $opt_u ) {
+ my $svc_x = qsearchs('svc_acct', { username=>$opt_u } )
+ or die "username $opt_u not found\n";
+ push @svc_x, $svc_x;
+} elsif ( $opt_p ) {
+ push @svc_x, map { $_->svc_x } qsearch('cust_svc', { svcpart=>$opt_p } );
+ die "no services with svcpart $opt_p found\n" unless @svc_x;
+} elsif ( $opt_k ) {
+ push @svc_x,
+ map { $_->svc_x }
+ qsearch({
+ table => 'cust_svc',
+ addl_from => 'LEFT JOIN cust_pkg USING ( pkgnum )',
+ extra_sql => "WHERE pkgpart = $opt_k",
+ });
+ die "no services with pkgpart $opt_k found\n" unless @svc_x;
+}
+
+warn "setting $field to $value before usage\n";
+foreach my $svc_x ( @svc_x ) {
+ my $cust_pkg = $svc_x->cust_svc->cust_pkg;
+ my $cust_usage = $value - &{ $field2sub{$field} }( $svc_x, $cust_pkg );
+# warn "resetting ". $svc_x->svcnum.':'.$svc_x->username. " to $cust_usage\n";
+ warn "$field for ". $svc_x->svcnum.':'.$svc_x->username. " reached limit\n"
+ if $cust_usage <= 0;
+ $svc_x->$field($cust_usage);
+
+ my $error = $svc_x->replace;
+ die $error if $error;
+}
+
+sub usage {
+ die "Usage:\n\n svc_acct-recalculate_usage user [ -s svcnum | -u username | -p svcpart ]\n";
+}
+
+=head1 NAME
+
+svc-acct-recalculate_usage - Command line tool to recalculate usage for existing services
+
+=head1 SYNOPSIS
+
+ svc_acct-recalculate_usage user usagefield initialvalue [ -s svcnum | -u username | -p svcpart ]
+
+ #recalculate a 1gb totalbytes limit for pkgpart 2
+ svc_acct-recalculate_usage ivan totalbytes 1073741824 -k 2
+
+=head1 DESCRIPTION
+
+Re-calculates the specified usage field for the specified service(s) (selected
+by svcnum, username or svcpart).
+
+=head1 SEE ALSO
+
+L<FS::svc_acct>, L<freeside-reexport>, L<FS::part_export>
+
+=cut
+
diff --git a/bin/tax_rate_location.import b/bin/tax_rate_location.import
new file mode 100755
index 0000000..439d27c
--- /dev/null
+++ b/bin/tax_rate_location.import
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -Tw
+
+use strict;
+use vars qw($opt_g $opt_f);
+use vars qw($DEBUG);
+use Getopt::Std;
+use FS::UID qw(adminsuidsetup);
+use FS::Conf;
+use FS::tax_rate_location;
+
+getopts('f:g:');
+
+my $user = shift or die &usage;
+my $dbh = adminsuidsetup $user;
+
+my ($format) = $opt_f =~ /^([-\w]+)$/;
+
+my @list = (
+ 'GEOCODE', $opt_g, \&FS::tax_rate_location::batch_import,
+);
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+
+my $error = '';
+
+while(@list) {
+ my ($name, $file, $method) = splice(@list, 0, 3);
+
+ my $fh;
+
+ $file =~ /^([\s\d\w.]+)$/ or die "Illegal filename: $file\n";
+ $file = $1;
+
+ open $fh, '<', $file or die "can't open $name file: $!\n";
+ $error ||= &{$method}( { filehandle => $fh, 'format' => $format, } );
+
+ die "error while processing $file: $error" if $error;
+ close $fh;
+}
+
+if ($error) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+}else{
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+}
+
+sub usage { die "Usage:\ntax_rates_location.import -f FORMAT -g GEOCODEFILE user\n\n"; }
diff --git a/conf/invoice_html b/conf/invoice_html
index 7a43aa6..b7f7b97 100644
--- a/conf/invoice_html
+++ b/conf/invoice_html
@@ -3,6 +3,8 @@
.invoice_header { font-size: 10pt }
.invoice_headerright TH { border-top: 2px solid #000000; border-bottom: 2px solid #000000 }
.invoice_headerright TD { font-size: 10pt; empty-cells: show }
+.invoice_summary TH { border-bottom: 2px solid #000000 }
+.invoice_summary TD { font-size: 10pt; empty-cells: show }
.invoice_longtable table { cellspacing: none }
.invoice_longtable TH { border-top: 2px solid #000000; border-bottom: 1px solid #000000; padding-left: none; padding-right: none; font-size: 10pt }
.invoice_desc TD { border-top: 2px solid #000000; font-weight: bold; font-size: 10pt }
@@ -11,7 +13,7 @@
.invoice_totaldesc TD { font-size: 10pt; empty-cells: show }
</STYLE>
-<table class="invoice" bgcolor="#ffffff" WIDTH=768 CELLSPACING=8><tr><td>
+<table class="invoice" bgcolor="#ffffff" WIDTH=625 CELLSPACING=8><tr><td>
<table class="invoice_header" width="100%">
<tr>
@@ -40,7 +42,7 @@
<tr>
<th>&nbsp;</th>
<th colspan=3 align="center">
- <FONT SIZE="+3">I</FONT><FONT SIZE="+2">NVOICE</FONT>
+ <FONT SIZE="+3"><%= $notice_name ? substr($notice_name, 0, 1) : 'I' %></FONT><FONT SIZE="+2"><%= $notice_name ? uc(substr($notice_name, 1)) : 'NVOICE' %></FONT>
</th>
<th>&nbsp;</th>
</tr>
@@ -82,10 +84,10 @@
</tr>
</table>
-
+ <%= $summary %>
<%=
- foreach my $section ( @sections ) {
- if ($section->{'pretotal'}) {
+ foreach my $section ( grep { !$summary || $_->{description} ne $finance_section } @sections ) {
+ if ($section->{'pretotal'} && !$summary) {
$OUT .=
'<table width="100%"><tr><td>'.
'<p align="right"><b><font size="+1">'.
@@ -95,91 +97,92 @@
'<p>'.
'</td></tr></table>';
}
- $OUT .= '<table><tr><td>';
- if ($section->{'description'}) {
- $OUT .=
- '<p><b><font size="+1">'. uc(substr($section->{'description'},0,1)).
- '</font><font size="+0">'. uc(substr($section->{'description'},1)).
- '</font></b>'.
- '<p>';
- }else{
- $OUT .=
- '<p><b><font size="+1">C</font><font size="+0">HARGES</font></b>'.
- '<p>';
- }
- $OUT .= '</td></tr></table>';
+ unless ($section->{'summarized'}) {
+ $OUT .= '<table><tr><td>';
+ if ($section->{'description'}) {
+ $OUT .=
+ '<p><b><font size="+1">'. uc(substr($section->{'description'},0,1)).
+ '</font><font size="+0">'. uc(substr($section->{'description'},1)).
+ '</font></b>'.
+ '<p>';
+ }else{
+ $OUT .=
+ '<p><b><font size="+1">C</font><font size="+0">HARGES</font></b>'.
+ '<p>';
+ }
+ $OUT .= '</td></tr></table>';
- $OUT .=
- '<table class="invoice_longtable" CELLSPACING=0 WIDTH="100%">'.
- '<tr>'.
- '<th align="center">Ref</th>'.
- '<th align="left">Description</th>'.
- ( $unitprices
- ? '<th align="left">Unit Price</th>'.
- '<th align="left">Quantity</th>'
- : ''
- ).
- '<th align="right">Amount</th>'.
- '</tr>';
-
- my $lastref = 0;
- foreach my $line (
- grep { ( scalar(@sections) > 1
- ? $section->{'description'} eq $_->{'section'}->{'description'}
- : 1
- ) }
- @detail_items )
- {
$OUT .=
- '<tr class="invoice_desc'.
- ( ($line->{'ref'} && $line->{'ref'} ne $lastref) ? '' : '_more' ).
- '">'.
- '<td align="center">'.
- ( $line->{'ref'} ne $lastref ? $line->{'ref'} : '' ). '</td>'.
- '<td align="left">'. $line->{'description'}. '</td>'.
+ '<table class="invoice_longtable" CELLSPACING=0 WIDTH="100%">'.
+ '<tr>'.
+ '<th align="center">Ref</th>'.
+ '<th align="left">Description</th>'.
( $unitprices
- ? '<td align="left">'. $line->{'unit_amount'}. '</td>'.
- '<td align="left">'. $line->{'quantity'}. '</td>'
+ ? '<th align="left">Unit Price</th>'.
+ '<th align="left">Quantity</th>'
: ''
- ).
-
- '<td align="right">'. $line->{'amount'}. '</td>'.
- '</tr>'
- ;
- $lastref = $line->{'ref'};
- if ( @{$line->{'ext_description'} } ) {
- $OUT .= '<tr class="invoice_extdesc"><td></td><td';
- $OUT .= $unitprices ? ' colspan=3>' : '>';
- $OUT .= '<table width="100%">';
- foreach my $ext_desc ( @{$line->{'ext_description'} } ) {
- $OUT .=
- '<tr class="invoice_extdesc">'.
- '<td align="left" '.
- ( $ext_desc =~ /<\/?TD>/i ? '' : 'colspan=99' ). '>'.
- '&nbsp;&nbsp;'. $ext_desc.
- '</td>'.
- '</tr>'
+ ).
+ '<th align="right">Amount</th>'.
+ '</tr>';
+
+ my $lastref = 0;
+ foreach my $line (
+ grep { ( scalar(@sections) > 1
+ ? $section->{'description'} eq $_->{'section'}->{'description'}
+ : 1
+ ) }
+ @detail_items )
+ {
+ $OUT .=
+ '<tr class="invoice_desc'.
+ ( ($line->{'ref'} && $line->{'ref'} ne $lastref) ? '' : '_more' ).
+ '">'.
+ '<td align="center">'.
+ ( $line->{'ref'} ne $lastref ? $line->{'ref'} : '' ). '</td>'.
+ '<td align="left">'. $line->{'description'}. '</td>'.
+ ( $unitprices
+ ? '<td align="left">'. $line->{'unit_amount'}. '</td>'.
+ '<td align="left">'. $line->{'quantity'}. '</td>'
+ : ''
+ ).
+
+ '<td align="right">'. $line->{'amount'}. '</td>'.
+ '</tr>'
+ ;
+ $lastref = $line->{'ref'};
+ if ( @{$line->{'ext_description'} } ) {
+ $OUT .= '<tr class="invoice_extdesc"><td></td><td';
+ $OUT .= $unitprices ? ' colspan=3>' : '>';
+ $OUT .= '<table width="100%">';
+ foreach my $ext_desc ( @{$line->{'ext_description'} } ) {
+ $OUT .=
+ '<tr class="invoice_extdesc">'.
+ '<td align="left" '.
+ ( $ext_desc =~ /<\/?TD>/i ? '' : 'colspan=99' ). '>'.
+ '&nbsp;&nbsp;'. $ext_desc.
+ '</td>'.
+ '</tr>'
+ }
+ $OUT .= '</table></td><td></td></tr>';
}
- $OUT .= '</table></td><td></td></tr>';
}
- }
- if (scalar(@sections) > 1) {
- my $style = 'border-top: 3px solid #000000;'.
- 'border-bottom: 3px solid #000000;';
- $OUT .=
- '<tr class="invoice_totaldesc">'.
- qq(<td style="$style">&nbsp;</td>).
- qq(<td align="left" style="$style").
- ( $unitprices ? ' colspan=3>' : '>' ).
- $section->{'description'}. ' Total </td>'.
- qq(<td align="right" style="$style">).
- $section->{'subtotal'}. '</td>'.
- '</tr>'
- ;
- }
-
+ if (scalar(@sections) > 1) {
+ my $style = 'border-top: 3px solid #000000;'.
+ 'border-bottom: 3px solid #000000;';
+ $OUT .=
+ '<tr class="invoice_totaldesc">'.
+ qq(<td style="$style">&nbsp;</td>).
+ qq(<td align="left" style="$style").
+ ( $unitprices ? ' colspan=3>' : '>' ).
+ $section->{'description'}. ' Total </td>'.
+ qq(<td align="right" style="$style">).
+ $section->{'subtotal'}. '</td>'.
+ '</tr>'
+ ;
+ }
+ }
if ($section->{'posttotal'}) {
$OUT .= '<tr><td align="right" colspan=5>';
$OUT .=
@@ -218,9 +221,15 @@
</table>
<br><br>
-<%= $notes %>
+<%= length($summary)
+ ? ''
+ : ( $smallernotes
+ ? '<FONT SIZE="-1">'.$notes.'</FONT>'
+ : $notes
+ )
+%>
<hr NOSHADE SIZE=2 COLOR="#000000">
- <p align="center"><%= $footer %>
+ <p align="center" <%= $smallerfooter ? 'STYLE="font-size:75%;"' : '' %>><%= $footer %>
</td></tr></table>
diff --git a/conf/invoice_htmlsummary b/conf/invoice_htmlsummary
new file mode 100644
index 0000000..b158478
--- /dev/null
+++ b/conf/invoice_htmlsummary
@@ -0,0 +1,74 @@
+<table>
+ <tr>
+ <td>
+ <table>
+ <tr><td><%= $notes %></td></tr>
+ </table>
+ </td>
+ <td>
+ <table class="invoice_summary">
+ <tr><th colspan=2><br></th></tr>
+ <tr>
+ <td><b><u><br>Summary of Previous Balance and Payments<br></u></b></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td><b>Previous Balance</b></td>
+ <td align="right"><b><%= $dollar.$true_previous_balance %></b></td>
+ </tr>
+ <tr>
+ <td><b>Payments</b></td>
+ <th align="right"><b><%= $dollar.$balance_adjustments %></b></th>
+ </tr>
+ <tr>
+ <td><b>Balance Outstanding</b></td>
+ <td align="right"><b><%= $dollar.sprintf('%.2f', $true_previous_balance - $balance_adjustments) %></b></td>
+ </tr>
+ <tr><th colspan=2><br></th></tr>
+ <tr><td colspan=2><br></td></tr>
+ <tr>
+ <td><b><u>Summary of New Charges</u></b></td>
+ <td></td>
+ </tr>
+ <tr><td colspan=2><br></td></tr>
+ <%=
+ my ($last) = grep { $_->{tax_section} || !$_->{summarized} and !($finance_section && $_->{'description'} eq $finance_section)} reverse @sections;
+
+ foreach my $section ( grep { $_->{tax_section} || !$_->{summarized} and !($finance_section && $_->{'description'} eq $finance_section)} @sections ) {
+ $OUT .= '<tr><td><b>'. ($section->{'description'} ? $section->{'description'} : 'Charges' ). '</b></td>';
+ my $celltype = ($last == $section) ? 'th' : 'td';
+ $OUT .= qq(<$celltype align="right"><b>). $section->{'subtotal'}. "</b></$celltype></tr>";
+ }
+ %>
+ <tr>
+ <td><b>New Charges Total</b></td>
+ <td align="right"><b><%= $dollar.$current_less_finance %></b></td>
+ </tr>
+ <tr><th colspan=2><br></th></tr>
+ <tr><td colspan=2><br></td></tr>
+ <tr>
+ <td><b><u>Invoice Summary</u></b></td>
+ <td></td>
+ </tr>
+ <tr><td colspan=2><br></td></tr>
+ <tr>
+ <td><b>Previous Past Due Charges</b></td>
+ <td align="right"><b><%= $dollar.sprintf('%.2f', $true_previous_balance - $balance_adjustments) %></b></td>
+ </tr>
+ <tr>
+ <td><b>Finance charges on overdue amount</b></td>
+ <td align="right"><b><%= $dollar.$finance_amount %></b></td>
+ </tr>
+ <tr>
+ <td><b>New Charges</b></td>
+ <th align="right"><b><%= $dollar.$current_less_finance %></b></th>
+ </tr>
+ <tr>
+ <td><b>Total Amount Due</b></td>
+ <td align="right"><b><%= $dollar.sprintf('%.2f', $true_previous_balance + $current_charges - $balance_adjustments) %></b></td>
+ </tr>
+ <tr><th colspan=2><br></th></tr>
+ </table>
+ </td>
+ </tr>
+</table>
diff --git a/conf/invoice_latex b/conf/invoice_latex
index aaec6be..ef6546f 100644
--- a/conf/invoice_latex
+++ b/conf/invoice_latex
@@ -19,7 +19,7 @@
\documentclass[letterpaper]{article}
-\usepackage{fancyhdr,lastpage,ifthen,fslongtable,afterpage,caption,multirow,bigstrut}
+\usepackage{fancyhdr,lastpage,ifthen,array,fslongtable,afterpage,caption,multirow,bigstrut}
\usepackage{graphicx} % required for logo graphic
\addtolength{\voffset}{-0.0cm} % top margin to top of header
@@ -82,12 +82,12 @@
$OUT .= $coupon;
}
'';
---@] \small{
+--@] [@-- $smallerfooter ? '\scriptsize{' : '\small{' --@]
[@-- $footer --@]
}[@-- $coupon ? '\vspace{\extracouponspace}' : '' --@]
}
{ % ... pages
- \small{
+ [@-- $smallerfooter ? '\scriptsize{' : '\small{' --@]
[@-- $smallfooter --@]
}
}
@@ -127,7 +127,7 @@
Invoice date & Invoice \#& Customer\#\\
\vspace{0.2cm}
\textbf{[@-- $date --@]} & \textbf{[@-- $invnum --@]} & \textbf{[@-- $custnum --@]} \\\hline
- \rule{0pt}{5ex} &~~ \huge{\textsc{Invoice}} & \\
+ \rule{0pt}{5ex} &~~ \huge{\textsc{[@-- $notice_name || 'Invoice' --@]}} & \\
\vspace{-0.2cm}
& & \\\hline
\end{tabular}
@@ -197,19 +197,7 @@
\begin{document}
-%
-%% Headers and footers defined for the first page
-%
-%% The LH Heading comprising logo
-%% UNCOMMENT the following FOUR lines and change the path if necssary to provide a logo
-%
-%% The Heading comprising isue date, customer ref & INVOICE name
-%
-%% Header & footer changes for subsequent pages
-%
-%
-%
-[@-- $coupon ? '\enlargethispage{-\extracouponspace}' : '' --@]
+% Headers and footers defined for the first page
\addressinset \rule{0.5cm}{0cm}
\makebox{
\begin{minipage}[t]{7.0cm}
@@ -244,83 +232,86 @@ Terms: [@-- $terms --@]\\
\end{minipage}}
\vspace{1.5cm}
%
+[@-- $summary --@]
+%
\section*{}
[@--
- foreach my $section ( @sections ) {
- if ($section->{'pretotal'}) {
+ foreach my $section ( grep { !$summary || $_->{description} ne $finance_section } @sections ) {
+ if ($section->{'pretotal'} && !$summary) {
$OUT .= '\begin{flushright}';
$OUT .= '\large\textsc{'. $section->{'pretotal'}. '}\\\\';
$OUT .= '\\end{flushright}';
}
$OUT .= '\pagebreak' if $section{'post_total'};
- $OUT .= '\captionsetup{singlelinecheck=false,justification=raggedright,font={Large,sc,bf}}';
- $OUT .= '\ifthenelse{\equal{\thepage}{1}}{\setlength{\LTextracouponspace}{\extracouponspace}}{\setlength{\LTextracouponspace}{0pt}}'
- if $coupon;
- $OUT .= '\begin{longtable}{cllllllr}';
- $OUT .= '\caption*{ ';
- $OUT .= ($section->{'description'}) ? $section->{'description'}: 'Charges';
- $OUT .= '}\\\\';
- $OUT .= '\FShead';
- $OUT .= '\endfirsthead';
- $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\\\';
- $OUT .= '\FShead';
- $OUT .= '\endhead';
- $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued on next page...}\\\\';
- $OUT .= '\endfoot';
- $OUT .= '\hline';
-
- if (scalar(@sections) > 1) {
- $OUT .= '\FStotaldesc{' . $section->{'description'} . ' Total}' .
- '{' . $section->{'subtotal'} . '}' . "\n";
- }
-
- #if ($section == $sections[$#sections]) {
- foreach my $line (grep {$_->{section}->{description} eq $section->{description}} @total_items) {
- $OUT .= '\FStotaldesc{' . $line->{'total_item'} . '}' .
- '{' . $line->{'total_amount'} . '}' . "\n";
+ unless ($section->{'summarized'} ) {
+ $OUT .= '\captionsetup{singlelinecheck=false,justification=raggedright,font={Large,sc,bf}}';
+ $OUT .= '\ifthenelse{\equal{\thepage}{1}}{\setlength{\LTextracouponspace}{\extracouponspace}}{\setlength{\LTextracouponspace}{0pt}}'
+ if $coupon;
+ $OUT .= '\begin{longtable}{cllllllr}';
+ $OUT .= '\caption*{ ';
+ $OUT .= ($section->{'description'}) ? $section->{'description'}: 'Charges';
+ $OUT .= '}\\\\';
+ $OUT .= '\FShead';
+ $OUT .= '\endfirsthead';
+ $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\\\';
+ $OUT .= '\FShead';
+ $OUT .= '\endhead';
+ $OUT .= '\multicolumn{7}{r}{\rule{0pt}{2.5ex}Continued on next page...}\\\\';
+ $OUT .= '\endfoot';
+ $OUT .= '\hline';
+
+ if (scalar(@sections) > 1) {
+ $OUT .= '\FStotaldesc{' . $section->{'description'} . ' Total}' .
+ '{' . $section->{'subtotal'} . '}' . "\n";
}
- #}
-
- $OUT .= '\hline';
- $OUT .= '\endlastfoot';
-
- my $lastref = 0;
- foreach my $line (
- grep { ( scalar( @sections ) > 1
- ? $section->{'description'} eq $_->{'section'}->{'description'}
- : 1
- ) }
- @detail_items )
- {
- my $ext_description = $line->{'ext_description'};
+
+ #if ($section == $sections[$#sections]) {
+ foreach my $line (grep {$_->{section}->{description} eq $section->{description}} @total_items) {
+ $OUT .= '\FStotaldesc{' . $line->{'total_item'} . '}' .
+ '{' . $line->{'total_amount'} . '}' . "\n";
+ }
+ #}
+
+ $OUT .= '\hline';
+ $OUT .= '\endlastfoot';
+
+ my $lastref = 0;
+ foreach my $line (
+ grep { ( scalar( @sections ) > 1
+ ? $section->{'description'} eq $_->{'section'}->{'description'}
+ : 1
+ ) }
+ @detail_items )
+ {
+ my $ext_description = $line->{'ext_description'};
- # Don't break-up small packages.
- my $rowbreak = @$ext_description < 5 ? '*' : '';
+ # Don't break-up small packages.
+ my $rowbreak = @$ext_description < 5 ? '*' : '';
- $OUT .= "\\hline\n" if ($line->{'ref'} && $line->{'ref'} ne $lastref);
- $OUT .= '\FSdesc'.
- '{' . ( $line->{'ref'} ne $lastref ? $line->{'ref'} : '' ) . '}'.
- '{' . $line->{'description'} . '}' .
- '{' . ( $unitprices ? $line->{'unit_amount'} : '' ) . '}'.
- '{' . ( $unitprices ? $line->{'quantity'} : '' ) . '}' .
- '{' . $line->{'amount'} . "}${rowbreak}\n";
- $lastref = $line->{'ref'};
-
- foreach my $ext_desc (@$ext_description) {
- if ( $ext_desc !~ /[^\\]&/ ) {
- $ext_desc = substr($ext_desc, 0, 80) . '...'
- if (length($ext_desc) > 80);
- $ext_desc = '\multicolumn{6}{l}{\small{~~~'. $ext_desc. '}}';
- }else{
- $ext_desc = "~~~$ext_desc";
+ $OUT .= "\\hline\n" if ($line->{'ref'} && $line->{'ref'} ne $lastref);
+ $OUT .= '\FSdesc'.
+ '{' . ( $line->{'ref'} ne $lastref ? $line->{'ref'} : '' ) . '}'.
+ '{' . $line->{'description'} . '}' .
+ '{' . ( $unitprices ? $line->{'unit_amount'} : '' ) . '}'.
+ '{' . ( $unitprices ? $line->{'quantity'} : '' ) . '}' .
+ '{' . $line->{'amount'} . "}${rowbreak}\n";
+ $lastref = $line->{'ref'};
+
+ foreach my $ext_desc (@$ext_description) {
+ if ( $ext_desc !~ /[^\\]&/ ) {
+ $ext_desc = substr($ext_desc, 0, 80) . '...'
+ if (length($ext_desc) > 80);
+ $ext_desc = '\multicolumn{6}{l}{\small{~~~'. $ext_desc. '}}';
+ }else{
+ $ext_desc = "~~~$ext_desc";
+ }
+ $OUT .= '\FSextdesc{' . $ext_desc . '}' . "${rowbreak}\n";
}
- $OUT .= '\FSextdesc{' . $ext_desc . '}' . "${rowbreak}\n";
+
}
+ $OUT .= '\end{longtable}';
}
-
- $OUT .= '\end{longtable}';
-
if ($section->{'posttotal'}) {
$OUT .= '\begin{flushright}';
$OUT .= '\normalfont\large\bfseries\textsc{'. $section->{'posttotal'}. '}\\\\';
@@ -330,5 +321,14 @@ Terms: [@-- $terms --@]\\
--@]
\vfill
-[@-- $notes --@]
+\begin{minipage}[t]{\textwidth}
+ [@-- length($summary)
+ ? ''
+ : ( $smallernotes
+ ? '\scriptsize{ '.$notes.' }'
+ : $notes
+ )
+ --@]
+ [@-- $coupon ? '\ifthenelse{\equal{\thepage}{1}}{\rule{0pt}{\extracouponspace}}{}' : '' --@]
+\end{minipage}
\end{document}
diff --git a/conf/invoice_latexsummary b/conf/invoice_latexsummary
new file mode 100644
index 0000000..a181ee4
--- /dev/null
+++ b/conf/invoice_latexsummary
@@ -0,0 +1,45 @@
+\begin{tabular}{ll}
+\begin{minipage}{6.4cm}
+\begin{tabular}{m{0cm}m{6.4cm}}
+\rule{0cm}{10cm}&\begin{minipage}{6cm}[@-- $notes --@]\end{minipage}\\
+\end{tabular}
+\end{minipage} &
+\rule{2cm}{0cm}
+\begin{minipage}{12.8cm}
+\begin{tabular}{lr}
+\hline
+&\\
+\textbf{\underline{Summary of Previous Balance and Payments}} & \\
+&\\
+\textbf{Previous Balance}&\textbf{\dollar[@-- $true_previous_balance --@]}\\
+\textbf{Payments}&\textbf{\dollar[@-- $balance_adjustments --@]}\\
+\cline{2-2}
+\textbf{Balance Outstanding}&\textbf{\dollar[@-- sprintf('%.2f', $true_previous_balance -$balance_adjustments) --@]}\\
+&\\
+\hline
+&\\
+\textbf{\underline{Summary of New Charges}} & \\
+&\\
+[@--
+ foreach my $section ( grep { $_->{tax_section} || !$_->{summarized} and !($finance_section && $_->{'description'} eq $finance_section)} @sections ) {
+ $OUT .= '\textbf{'. ($section->{'description'} ? $section->{'description'} : 'Charges' ). '}';
+ $OUT .= '&\textbf{'. $section->{'subtotal'}. '}\\\\';
+ }
+ $OUT .= '\cline{2-2}';
+--@]
+\textbf{New Charges Total}&\textbf{\dollar[@-- $current_less_finance --@]}\\
+&\\
+\hline
+&\\
+\textbf{\underline{Invoice Summary}} & \\
+& \\
+\textbf{Previous Past Due Charges}&\textbf{\dollar[@-- sprintf('%.2f', $true_previous_balance - $balance_adjustments) --@]}\\
+\textbf{Finance charges on overdue amount}&\textbf{\dollar[@-- $finance_amount --@]}\\
+\textbf{New Charges}&\textbf{\dollar[@-- $current_less_finance --@]}\\
+\cline{2-2}
+\textbf{Total Amount Due}&\textbf{\dollar[@-- sprintf('%.2f', $true_previous_balance + $current_charges - $balance_adjustments) --@]}\\
+&\\
+\hline
+\end{tabular}
+\end{minipage} \\
+\end{tabular}
diff --git a/conf/invoice_template b/conf/invoice_template
index b33c4dd..ebf8ef7 100644
--- a/conf/invoice_template
+++ b/conf/invoice_template
@@ -1,5 +1,5 @@
- Invoice
+ { $notice_name || 'Invoice'; }
{ substr("Page $page of $total_pages ", 0, 19); } { use Date::Format; time2str("%x", $date); } Invoice #{ $invnum; }
diff --git a/debian/changelog b/debian/changelog
index d53e90e..20a0b4f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+freeside (1.9.1-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Ivan Kohler <ivan-debian@420.am> Sat, 10 Oct 2009 19:41:01 -0700
+
+freeside (1.9.1-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Ivan Kohler <ivan-debian@420.am> Sat, 10 Oct 2009 18:57:01 -0700
+
freeside (1.9.0~cvs0-1) unstable; urgency=low
* Initial release
diff --git a/eg/cdr_template.pm b/eg/cdr_template.pm
index 5499d22..4e55c65 100644
--- a/eg/cdr_template.pm
+++ b/eg/cdr_template.pm
@@ -29,6 +29,7 @@ use FS::cdr qw( _cdr_date_parser_maker _cdr_min_parser_maker );
#premade subref factory for date+time parsing, understands dates like:
# 10/31/2007 08:57:24
# 2007-10-31 08:57:24.113000000
+ # Mon Dec 15 11:38:34 2003
_cdr_date_parser_maker('startddate'), #for example
#premade subref factory for decimal minute parsing
@@ -71,7 +72,7 @@ list of freeside CDR fields, useful ones marked with *
amaflags - What flags to use: BILL, IGNORE etc, specified on a per
channel basis like accountcode.
*[3] accountcode - CDR account number to use: account
- uniqueid - Unique channel identifier (Unitel/RSLCOM Event ID)
+ uniqueid - Unique channel identifier
userfield - CDR user-defined field
cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
*[4] charged_party - Service number to be billed
@@ -85,7 +86,7 @@ list of freeside CDR fields, useful ones marked with *
description - Description (cdr_type 7&8 only) (used for
cust_bill_pkg.itemdesc)
quantity - Number of items (cdr_type 7&8 only)
- carrierid - Upstream Carrier ID (see FS::cdr_carrier)
+*[7] carrierid - Upstream Carrier ID (see FS::cdr_carrier)
upstream_rateid - Upstream Rate ID
svcnum - Link to customer service (see FS::cust_svc)
freesidestatus - NULL, done (or something)
@@ -97,3 +98,4 @@ list of freeside CDR fields, useful ones marked with *
[5] When using 'upstream_simple' rating method.
[6] Set to usage class classnum when using pre-rated CDRs and usage class-based
taxation (local/intrastate/interstate/international)
+[7] If doing settlement charging
diff --git a/etc/areacodes.txt b/etc/areacodes.txt
new file mode 100644
index 0000000..e214db1
--- /dev/null
+++ b/etc/areacodes.txt
@@ -0,0 +1,353 @@
+201 NJ New Jersey (Hackensack, Jersey City, Hoboken and northeast New Jersey, overlays with 551)<Eastern Time Zone>
+202 DC District of Columbia (all of Washington, DC)<Eastern Time Zone>
+203 CT Connecticut (Bridgeport, New Haven, Waterbury and southwestern Connecticut, overlays with 475)<Eastern Time Zone>
+204 MB Manitoba (all of Manitoba)<Central Time Zone>
+205 AL Alabama (Birmingham, Tuscaloosa and central and western Alabama)<Central Time Zone>
+206 WA Washington (Seattle, Sea-Tac, Ballard, Madison, Capitol Hill and central Seattle neighborhoods)<Pacific Time Zone>
+207 ME Maine (all of Maine)<Eastern Time Zone>
+208 ID Idaho (all of Idaho)<Mountain & Pacific Time Zones>
+209 CA California (Stockton, Merced, Modesto, San Andreas and central California)<Pacific Time Zone>
+210 TX Texas (San Antonio area)<Central Time Zone>
+212 NY New York (New York City Manhattan area, overlays with 646 and 917)<Eastern Time Zone>
+213 CA California (Downtown Los Angeles area only)<Pacific Time Zone>
+214 TX Texas (Dallas area, overlays with 469 and 972)<Central Time Zone>
+215 PA Pennsylvania (Philadelphia area, overlays with 267 and 445)<Eastern Time Zone>
+216 OH Ohio (Cleveland area)<Eastern Time Zone>
+217 IL Illinois (Champaign, Decatur, Urbana, Springfield and central Illinois)<Central Time Zone>
+218 MN Minnesota (Duluth, Thief River Falls, Brainerd, International Falls and northern Minnesota)<Central Time Zone>
+219 IN Indiana (Gary, Valparaiso, Michigan City, Goodland, Fowler and northwestern Indiana)<Central Time Zone>
+224 IL Illinois (Waukegan, Des Plaines, northwest Chicago suburbs and northeastern Illinois, overlays with 847)<Central Time Zone>
+225 LA Louisiana (Baton Rouge, New Roads, White Castle and central eastern Louisiana)<Central Time Zone>
+226 ON Ontario (London, Windsor and southwestern Ontario, overlays with 519)<Eastern Time Zone>
+228 MS Mississippi (Gulfport, Pascagoula, Biloxi, Bay St Louis and southern Mississippi gulf coast)<Central Time Zone>
+229 GA Georgia (Albany, Valdosta, Bainbridge, Americus, Fitzgerald and southwestern Georgia)<Eastern Time Zone>
+231 MI Michigan (Traverse City, Ludington, Muskegon, Petoskey and northwestern Michigan)<Eastern Time Zone>
+234 OH Ohio (Youngstown, Warren, Akron, Canton and northeastern Ohio, overlays with 330)<Eastern Time Zone>
+239 FL Florida (Fort Meyers, Naples, Everglades and southwestern Florida)<Eastern Time Zone>
+240 MD Maryland (Hagerstown, Rockville, Cumberland and western Maryland, overlays with 301)<Eastern Time Zone>
+242 BAHAMAS (all of Bahamas)<Atlantic Time Zone (one hour later than Eastern)>
+246 BARBADOS (all of Barbados)<Atlantic Time Zone (one hour later than Eastern)>
+248 MI Michigan (Troy, Oakland County, Pontiac, Southfield, Rochester Hills and northwestern Detroit suburbs, overlays with 947)<Eastern Time Zone>
+250 BC British Columbia (all except Vancouver area)<Mountain & Pacific Time Zones>
+251 AL Alabama (Mobile, Jackson and southwestern Alabama)<Central Time Zone>
+252 NC North Carolina (Greenville, Kitty Hawk, Rocky Mount and northeastern North Carolina)<Eastern Time Zone>
+253 WA Washington (Tacoma, Auburn, Puyallup, Enumclaw, Spanaway and south Seattle suburbs)<Pacific Time Zone>
+254 TX Texas (Waco, Killeen, Belton, Stephenville and north central Texas)<Central Time Zone>
+256 AL Alabama (Florence, Huntsville, Gadsden, Anniston and northern and eastern Alabama)<Central Time Zone>
+260 IN Indiana (Fort Wayne, Decatur, Angola, Wabash and northeastern Indiana)<Eastern Time Zone>
+262 WI Wisconsin (Menomonee Falls, Waukesha, Racine and southeastern Wisconsin excluding Milwaukee area)<Central Time Zone>
+264 ANGUILLA (all of Anguilla)<Atlantic Time Zone (one hour later than Eastern)>
+267 PA Pennsylvania (Philadelphia area, overlays with 215 and 445)<Eastern Time Zone>
+268 ANTIGUA and BARBUDA (all of Antigua and Barbuda)<Atlantic Time Zone (one hour later than Eastern)>
+269 MI Michigan (Battle Creek, Benton Harbor, Allegan, Hastings, Kalamazoo, St Joseph, and southwestern Michigan)<Eastern Time Zone>
+270 KY Kentucky (Paducah, Bowling Green, Hopkinsville, Owensboro and western Kentucky)<Central Time Zone>
+276 VA Virginia (Abingdon, Wytheville, Martinsville, Bluefield and western Virginia)<Eastern Time Zone>
+281 TX Texas (Spring, Katy, Houston area, overlays with 713 and 832)<Central Time Zone>
+284 BRITISH VIRGIN ISLANDS (all of the British Virgin Islands)<Atlantic Time Zone (one hour later than Eastern)>
+289 ON Ontario (Hamilton, Toronto suburbs and central southeastern Ontario, overlays with 905)<Eastern Time Zone>
+301 MD Maryland (Hagerstown, Rockville, Cumberland and western Maryland, overlays with 240)<Eastern Time Zone>
+302 DE Delaware (all of Delaware)<Eastern Time Zone>
+303 CO Colorado (Boulder, Longmont, Aurora, Denver and central Colorado, overlays with 720)<Mountain Time Zone>
+304 WV West Virginia (all of West Virginia)<Eastern Time Zone>
+305 FL Florida (Miami, Homestead, Coral Gables, Key West and southeastern Florida, overlays with 786)<Eastern Time Zone>
+306 SK Saskatchewan (all of Saskatchewan)<Central & Mountain Time Zones>
+307 WY Wyoming (all of Wyoming)<Mountain Time Zone>
+308 NE Nebraska (North Platte, Scottsbluff, McCook, Grand Island and western Nebraska)<Central & Mountain Time Zones>
+309 IL Illinois (Peoria, Moline, Rock Island, Galesburg and central western Illinois)<Central Time Zone>
+310 CA California (Malibu, Torrance, Beverley Hills, Santa Monica, Catalina and western Los Angeles suburbs, overlays with 424)<Pacific Time Zone>
+311 NON-EMERGENCY ACCESS
+312 IL Illinois (downtown central Chicago area)<Central Time Zone>
+313 MI Michigan (Dearborn, Detroit and inner Detroit suburbs)<Eastern Time Zone>
+314 MO Missouri (St Louis, Florissant, Crestwood, Affton and surrounding suburbs)<Central Time Zone>
+315 NY New York (Watertown, Utica, Syracuse and north central New York)<Eastern Time Zone>
+316 KS Kansas ( Wichita, Augusta, El Dorado, Mulvane and the Wichita surrounding area)<Central Time Zone>
+317 IN Indiana (Indianapolis, Greenwood, Mooresville, Beech Grove and central Indiana)<Eastern Time Zone>
+318 LA Louisiana (Shreveport, Monroe, Alexandria, Fisher, Tallulah and northern Louisiana)<Central Time Zone>
+319 IA Iowa (Burlington, Iowa City, Cedar Rapids, Waterloo and east central and southeastern Iowa)<Central Time Zone>
+320 MN Minnesota (St Cloud, Morris, Hutchinson, Sandstone, Appleton and central Minnesota)<Central Time Zone>
+321 FL Florida (Orlando, Cocoa Beach, St Cloud and central eastern Florida, overlays with 407)<Eastern Time Zone>
+323 CA California (Florence and Los Angeles excluding downtown Los Angeles)<Pacific Time Zone>
+325 TX Texas (Abilene, San Angelo, Albany, Comanche, Snyder, Ozona and west central Texas)<Central Time Zone>
+330 OH Ohio (Youngstown, Warren, Akron, Canton and northeastern Ohio, overlays with 234)<Eastern Time Zone>
+331 IL Illinois (Aurora, Batavia, Geneva and western Chicago suburbs, overlays with 630)<Central Time Zone>
+334 AL Alabama ( Montgomery, Auburn, Dothan, Selma and southeastern Alabama)<Central Time Zone>
+336 NC North Carolina (Winston-Salem, Greensboro, North Wilkesboro and northwest North Carolina)<Eastern Time Zone>
+337 LA Louisiana (Leesville, Lake Charles, Lafayette, De Ridder and southwestern Louisiana)<Central Time Zone>
+339 MA Massachusetts (Saugus, Norwood and east central Massachusetts, overlays with 781)<Eastern Time Zone>
+340 US VIRGIN ISLANDS (all of the US Virgin Islands)<Atlantic Time Zone>
+345 CAYMAN ISLANDS (all of the Cayman Islands)<Eastern Time Zone>
+347 NY New York (Flushing, Jamaica, Brooklyn, Staten Island, Bronx and Queens, overlays with 718 and 917)<Eastern Time Zone>
+351 MA Massachusetts (Fitchburg, Peabody and northeastern Massachusetts, overlays with 978)<Eastern Time Zone>
+352 FL Florida (Gainesville, Ocala, Inverness, Dunnellon and central Florida)<Eastern Time Zone>
+360 WA Washington (Bellingham, Vancouver, Aberdeen, Olympia and western Washington except Seattle area)<Pacific Time Zone>
+361 TX Texas (Corpus Christi, Victoria, George West and southeastern Texas)<Central Time Zone>
+385 UT Utah (North and south of Salt Lake City including Ogden, Provo, Bountiful and Spanish Fork)<Mountain Time Zone>
+386 FL Florida (Daytona Beach, Lake City, Live Oak, Crescent City and northern and eastern Florida)<Eastern Time Zone>
+401 RI Rhode Island (all of Rhode Island)<Eastern Time Zone>
+402 NE Nebraska (Valentine, Lincoln, Norfolk, Omaha, Superior, Crofton and eastern Nebraska)<Central Time Zone>
+403 AB Alberta (Calgary, Banff, Red Deer, Medicine Hat, Lethbridge and southern Alberta)<Mountain Time Zone>
+404 GA Georgia (central Atlanta area, overlays with 470 and 678)<Eastern Time Zone>
+405 OK Oklahoma (Oklahoma City, Edmond, Norman, Shawnee, Chickasha and central Oklahoma)<Central Time Zone>
+406 MT Montana (all of Montana)<Mountain Time Zone>
+407 FL Florida (Orlando, Cocoa Beach, St Cloud and central eastern Florida, overlays with 321)<Eastern Time Zone>
+408 CA California (Los Gatos, Milpitas, Sunnyvale, Cupertino and San Jose area)<Pacific Time Zone>
+409 TX Texas (Beaumont, Galveston, Port Arthur, Jasper and southeastern Texas)<Central Time Zone>
+410 MD Maryland (Annapolis, Baltimore, Salisbury and eastern Maryland, overlays with 443)<Eastern Time Zone>
+411 LOCAL DIRECTORY ASSISTANCE
+412 PA Pennsylvania (Pittsburgh area, McKeesport, Braddock, Duquesne, overlays with 878)<Eastern Time Zone>
+413 MA Massachusetts (Pittsfield, Springfield, Holyoke, Greenfield and western Massachusetts)<Eastern Time Zone>
+414 WI Wisconsin (Milwaukee, Greenfield, Oak Creek and Milwaukee suburbs)<Central Time Zone>
+415 CA California (Sausalito, San Rafael, Novato, San Quentin, San Francisco and bay area)<Pacific Time Zone>
+416 ON Ontario (Toronto area, overlays with 647)<Eastern Time Zone>
+417 MO Missouri (Joplin, Springfield, West Plains, Lamar, Lebanon and southwestern Missouri)<Central Time Zone>
+418 QC Quebec (Quebec and eastern Quebec)<Eastern Time Zone>
+419 OH Ohio (Toledo, Mansfield, Lima, Bryan, Sandusky, Bowling Green and northwestern Ohio, overlays with 567)<Eastern Time Zone>
+423 TN Tennessee (Bristol, Sweetwater, Chattanooga, and southeastern and north eastern Tennessee)<Central & Eastern Time Zones>
+424 CA California (Malibu, Torrance, Beverley Hills, Santa Monica, Catalina and western Los Angeles suburbs, overlays with 310)<Pacific Time Zone>
+425 WA Washington (north and east Seattle suburbs including Everett, Bellevue, Redmond, Renton and Issaquah)<Pacific Time Zone>
+430 TX Texas (Tyler, Sherman, Longview, Palestine and northeastern Texas, overlays with 903)<Central Time Zone>
+432 TX Texas (Alpine, Midland, Odessa, Big Bend, Seminole, Comstock and west central Texas)< Central Time Zone>
+434 VA Virginia (Lynchburg, Danville, South Hill, Charlottesville and south central Virginia)<Eastern Time Zone>
+435 UT Utah (Logan, St George, Moab and all of Utah excluding Salt Lake City, Ogden, Provo and central Utah)<Mountain Time Zone>
+438 QC Quebec (Montreal area, overlays with 514)<Eastern Time Zone>
+440 OH Ohio (Elyria, Lorain, Oberlin, Wellington and north central Ohio)<Eastern Time Zone>
+441 BERMUDA (all of Bermuda)<Atlantic Time Zone>
+443 MD Maryland (Annapolis, Baltimore, Salisbury and eastern Maryland, overlays with 410)<Eastern Time Zone>
+450 QC Quebec (central southern Quebec excluding Montreal)<Eastern Time Zone>
+456 INTERNATIONAL INBOUND
+469 TX Texas (Dallas area, overlays with 214 and 972)<Central Time Zone>
+470 GA Georgia (Atlanta, Gainesville and north central Georgia, overlays with 404 and 678 and 770)<Eastern Time Zone>
+473 GRENADA (all of Grenada)<Atlantic Time Zone (one hour later than Eastern)>
+475 CT Connecticut ( Bridgeport, New Haven, Waterbury and southwestern Connecticut, overlays with 203)<Eastern Time Zone>
+478 GA Georgia (Macon, Warner Robins, Swainsboro, Wadley, Milledgeville, Perry and central Georgia)<Eastern Time Zone>
+479 AR Arkansas (Fort Smith, Fayetteville and northwestern Arkansas)<Central Time Zone>
+480 AZ Arizona (Chandler, eastern Phoenix area and eastern Phoenix suburbs only)<Mountain & Pacific Time Zones>
+484 PA Pennsylvania (Reading, Allentown, Chester and southeastern Pennsylvania, overlays with 610 and 835)<Eastern Time Zone>
+500 PERSONAL COMMUNICATIONS SERVICES
+501 AR Arkansas (Little Rock, Hot Springs and central Arkansas)<Central Time Zone>
+502 KY Kentucky (Louisville, Frankfort, Shelbyville and north central Kentucky)<Eastern Time Zone>
+503 OR Oregon (Portland, Salem, Tillamook, Astoria and northwestern Oregon, overlays with 971)<Pacific Time Zone>
+504 LA Louisiana (New Orleans, Kenner, Metairie and surrounding areas)<Central Time Zone>
+505 NM New Mexico (Albuquerque, Farmington, Gallup, Santa Fe and northwestern New Mexico)<Mountain Time Zone>
+506 NB New Brunswick (all of New Brunswick)<Atlantic Time Zone>
+507 MN Minnesota (Rochester, Mankato, Worthington, Marshall and southern Minnesota)<Central Time Zone>
+508 MA Massachusetts (Worcester, New Bedford and southeastern Massachusetts, overlays with 774)<Eastern Time Zone>
+509 WA Washington (Spokane, Yakima, Walla Walla, Moses Lake, Ellensburg and eastern Washington)<Pacific Time Zone>
+510 CA California (Hayward, Berkeley, Oakland, Richmond and Fremont areas)<Pacific Time Zone>
+512 TX Texas (Austin, Lampasas, Bastrop, Milam and central Texas)<Central Time Zone>
+513 OH Ohio (Cincinnati, Middletown, Hamilton, Norwood, Lebanon and southwestern Ohio)<Eastern Time Zone>
+514 QC Quebec (Montreal area, overlays with 438)<Eastern Time Zone>
+515 IA Iowa (Des Moines, Ames, Fort Dodge, Jefferson, Algona, Indianola and north central Iowa)<Central Time Zone>
+516 NY New York (Nassau County, Levittown, Hicksville, Massapequa and western Long Island)<Eastern Time Zone>
+517 MI Michigan (Jackson, Lansing, Howell, Deerfield, Addison and south central Michigan)<Eastern Time Zone>
+518 NY New York (Plattsburgh, Saranac Lake, Albany and northeastern New York)<Eastern Time Zone>
+519 ON Ontario (London, Windsor and southwestern Ontario, overlays with 226)<Eastern Time Zone>
+520 AZ Arizona (Tucson and southeastern Arizona)<Mountain & Pacific Time Zones>
+530 CA California (Alturas, Chico, Redding, Placerville, Truckee and northeastern California)<Pacific Time Zone>
+540 VA Virginia (Roanoke, Harrisonburg, Winchester, Fredericksburg and northern Virginia)<Eastern Time Zone>
+541 OR Oregon (Medford, Eugene, Ontario, Burns and all of Oregon except northwestern Oregon)<Mountain & Pacific Time Zones>
+551 NJ New Jersey (Hackensack, Jersey City, and northeast New Jersey, overlays with 201)<Eastern Time Zone>
+559 CA California (Fresno, Madera, Hanford, Visalia and central California)<Pacific Time Zone>
+561 FL Florida (West Palm Beach, Boca Raton, Boynton Beach, Delray Beach, Belleglade and central eastern Florida)<Eastern Time Zone>
+562 CA California (Long Beach, Lakewood, Bellflower and southwestern Los Angeles suburbs)<Pacific Time Zone>
+563 IA Iowa (Decorah, Dubuque, Clinton, Davenport and eastern and northeastern Iowa)<Central Time Zone>
+567 OH Ohio (Toledo, Mansfield, Lima, Bryan, Sandusky and northwestern Ohio, overlays with 419)<Eastern Time Zone>
+570 PA Pennsylvania (Scranton, Williamsport, Wilkes-Barre, Susquehanna and northeastern Pennsylvania)<Eastern Time Zone>
+571 VA Virginia (Alexandria, Washington DC suburbs, Arlington and northeastern Virginia, overlays with 703)<Eastern Time Zone>
+573 MO Missouri (Jefferson City, Hannibal, Poplar Bluff and eastern Missouri excluding St Louis)<Central Time Zone>
+574 IN Indiana (South Bend, Logansport, Elkhart, Nappanee and north central Indiana)<Central & Eastern Time Zones>
+575 NM New Mexico (Carlsbad, Las Cruces, Roswell, Silver City, Taos and southern and eastern New Mexico)<Mountain Time Zone>
+580 OK Oklahoma (Guymon, Hugo, Enid, Lawton, Ardmore, Elk City and southern and western Oklahoma)<Central Time Zone>
+585 NY New York (Rochester, Wellsville, Batavia, Olean and western New York)<Eastern Time Zone>
+586 MI Michigan (Port Huron, Flint, Flushing, Warren and eastern Michigan, overlays with 810)<Eastern Time Zone>
+600 CANADA/SERVICES
+601 MS Mississippi (Jackson, Meridian, Natchez, McComb, Hattiesburg and central Mississippi, overlays with 769)<Central Time Zone>
+602 AZ Arizona (Central Phoenix only)<Mountain & Pacific Time Zones>
+603 NH New Hampshire (all of New Hampshire)<Eastern Time Zone>
+604 BC British Columbia (Vancouver, Richmond, Abbotsford, Whistler and southwestern BC, overlays with 778)<Pacific Time Zone>
+605 SD South Dakota (all of South Dakota)<Central & Mountain Time Zones>
+606 KY Kentucky (Ashland, Hazard, Somerset, London, Corbin, Pikeville, Maysville and eastern Kentucky)<Central & Eastern Time Zones>
+607 NY New York (Binghamton, Elmira, Bath, Norwich and south central New York)<Eastern Time Zone>
+608 WI Wisconsin (Madison, La Crosse, Platteville, Janesville and southwestern Wisconsin)<Central Time Zone>
+609 NJ New Jersey (Atlantic City, Brown Mills, Trenton, and central & southeastern New Jersey)<Eastern Time Zone>
+610 PA Pennsylvania (Reading, Allentown, Chester and southeastern Pennsylvania, overlays with 484 and 835)<Eastern Time Zone>
+611 REPAIR SERVICE
+612 MN Minnesota (Central Minneapolis, Fort Snelling, St Anthony and Richfield)<Central Time Zone>
+613 ON Ontario (Ottawa and southeastern Ontario)<Eastern Time Zone>
+614 OH Ohio (Columbus area)<Eastern Time Zone>
+615 TN Tennessee (Nashville, Murfreesboro, Springfield, Lebanon, Dickson and north central Tennessee)<Central Time Zone>
+616 MI Michigan ( Grand Rapids, Holland, Greenville, Grandhaven, Zeeland, and southwestern Michigan)<Eastern Time Zone>
+617 MA Massachusetts (Boston, Cambridge and east central Massachusetts, overlays with 857)<Eastern Time Zone>
+618 IL Illinois (Carbondale, Alton, Centralia, Mount Vernon and southern Illinois)<Central Time Zone>
+619 CA California (National City, Chula Vista, Imperial Beach, Otay and the San Diego area)<Pacific Time Zone>
+620 KS Kansas (Dodge City, Great Bend, Parsons, Liberal and southern Kansas)<Central & Mountain Time Zone>
+623 AZ Arizona (Buckeye, Peoria, western Phoenix area and western Phoenix suburbs only)<Mountain & Pacific Time Zones>
+626 CA California (Arcadia, Temple City, Covina, Pasadena and eastern Los Angeles suburbs)<Pacific Time Zone>
+630 IL Illinois (Aurora, Batavia, Geneva and western Chicago suburbs, overlays with 331)<Central Time Zone>
+631 NY New York (Manorville, Huntington, Lindenhurst, Islip, Deer Park and Eastern Long Island)<Eastern Time Zone>
+636 MO Missouri (Chesterfield, Union, De Soto, Troy and east central Missouri)<Central Time Zone>
+641 IA Iowa (Mason City, Oskaloosa, Creston, Pella, Ottumwa, Britt, Clear Lake, Fairfield and central Iowa)<Central Time Zone>
+646 NY New York (New York City Manhattan area, overlays with 212 and 917)<Eastern Time Zone>
+647 ON Ontario (Toronto area, overlays with 416)<Eastern Time Zone>
+649 TURKS & CAICOS (all of Turks and Caicos)<Eastern Time Zone>
+650 CA California (San Mateo, Palo Alto, Redwood City, Menlo Park and southern San Francisco suburbs)<Pacific Time Zone>
+651 MN Minnesota (St Paul, Lindstrom, Red Wing, Hastings and east central Minnesota)<Central Time Zone>
+660 MO Missouri (Marshall, Sedalia, Macon, Trenton, Maryville and north central Missouri)<Central Time Zone>
+661 CA California (Bakersfield, Mojave, Santa Clarita, Palmdale and south central California)<Pacific Time Zone>
+662 MS Mississippi (Greenville, Tupelo, Winona, Columbus, Holly Springs and northern Mississippi)<Central Time Zone>
+664 MONTSERRAT (all of Montserrat)<Atlantic Time Zone (one hour later than Eastern)>
+670 COMMONWEALTH OF THE NORTHERN MARIANA ISLANDS (all of CNMI including Saipan)<Pacific Guam Time Zone (6 or 7 hours earlier than Pacific Time, does not observe daylight savings)>
+671 GUAM (all of Guam)<Pacific Guam Time Zone (6 or 7 hours earlier than Pacific Time, does not observe daylight savings)>
+678 GA Georgia (Atlanta, Gainesville, Griffin and north central Georgia, overlays 404 and and 470 and 770)<Eastern Time Zone>
+682 TX Texas (Fort Worth, Arlington, Grandview, Weatherford, Rhome, overlays with 817)<Central Time Zone>
+684 AMERICAN SAMOA (all of American Samoa including Pago Pago)<Samoan Standard Time Zone (3 or 4 hours earlier than Pacific Time, does not observe daylight savings)>
+700 INTEREXCHANGE CARRIER SERVICES
+701 ND North Dakota (all of North Dakota)<Mountain & Central Time Zones>
+702 NV Nevada (Las Vegas, Henderson and extreme southern Nevada)<Pacific Time Zone>
+703 VA Virginia (Alexandria, Washington DC suburbs, Arlington and northeastern Virginia, overlays with 571)<Eastern Time Zone>
+704 NC North Carolina (Charlotte, Kingstown and south central North Carolina, overlays with 980)<Eastern Time Zone>
+705 ON Ontario (North Bay and northeastern Ontario)<Eastern Time Zone>
+706 GA Georgia (Augusta, Columbus, Lagrange, Rome, Dalton and northern and west central Georgia, overlays with 762)<Eastern Time Zone>
+707 CA California (Santa Rosa, Fort Bragg, Crescent City, Eureka, Ukiah and northwestern California)<Pacific Time Zone>
+708 IL Illinois (Chicago Heights, Tinley Park and southern Chicago suburbs)<Central Time Zone>
+709 NF Newfoundland (all of Newfoundland)<Newfoundland Time Zone (one and a half hours later than Eastern)>
+710 US GOVERNMENT
+711 TRS ACCESS
+712 IA Iowa (Estherville, Council Bluffs, Sioux City, Sheldon, Denison and western Iowa)<Central Time Zone>
+713 TX Texas (Spring, Katy, Houston area, overlays with 281 and 832)<Central Time Zone>
+714 CA California (Huntington Beach, Orange, Garden Grove, Tustin, Anaheim and northern Orange County)<Pacific Time Zone>
+715 WI Wisconsin (Rhinelander, Wausau, Eau Claire, Rice Lake, Ashland and northern Wisconsin)<Central Time Zone>
+716 NY New York (Buffalo, Jamestown, Niagara Falls, Tonawanda and western New York)<Eastern Time Zone>
+717 PA Pennsylvania (Harrisburg, Gettysburg, Lancaster, York and south central Pennsylvania)<Eastern Time Zone>
+718 NY New York (Flushing, Jamaica, Brooklyn, Staten Island, Bronx and Queens, overlays with 347 and 917)<Eastern Time Zone>
+719 CO Colorado (Leadville, Pueblo, Colorado Springs, Trinidad and southeastern Colorado)<Mountain Time Zone>
+720 CO Colorado (Boulder, Longmont, Aurora, Denver and central Colorado, overlays with 303)<Mountain Time Zone>
+724 PA Pennsylvania (New Castle, Washington, Uniontown and south western Pennsylvania, overlays with 878)<Eastern Time Zone>
+727 FL Florida (Clearwater, St Petersburg, Dunedin and the west central Florida gulf coast)<Eastern Time Zone>
+731 TN Tennessee (Union City, Jackson, Dyersburg, Paris, Bolivar and western Tennessee)<Central Time Zone>
+732 NJ New Jersey (New Brunswick, Neptune, Lakewood, and east central New Jersey, overlays with 848)<Eastern Time Zone>
+734 MI Michigan (Ann Arbor, Monroe, Wayne, Ypsilanti and southwestern Detroit suburbs)<Eastern Time Zone>
+740 OH Ohio (Jackson, Lancaster, Marietta, Cambridge, Zanesville, New Castle and southeastern Ohio)<Eastern Time Zone>
+754 FL Florida (Fort Lauderdale, Pompano Beach, overlays with 954)<Eastern Time Zone>
+757 VA Virginia (Hampton, Norfolk, Williamsburg, Newport News, Virginia Beach and southeastern Virginia)<Eastern Time Zone>
+758 ST LUCIA (all of St Lucia)<Atlantic Time Zone (one hour later than Eastern)>
+760 CA California (Bishop, Ridgecrest, Indio, Barstow, El Centro, Palm Springs and southeastern California)<Pacific Time Zone>
+762 GA Georgia (Augusta, Columbus, Lagrange, Rome, Dalton and northern and west central Georgia, overlays with 706)<Eastern Time Zone>
+763 MN Minnesota (Maple Grove, Monticello, Elk River, Fridley, Blaine, and northwest Minneapolis area)<Central Time Zone>
+765 IN Indiana (Lafayette, Marion, Muncie, Richmond and central Indiana excluding Indianapolis)<Eastern Time Zone>
+767 DOMINICA (all of Dominica)<Atlantic Time Zone (one hour later than Eastern)>
+769 MS Mississippi (Jackson, Meridian, Natchez, McComb, Hattiesburg and central Mississippi, overlays with 601)<Central Time Zone>
+770 GA Georgia (Marietta, Cedartown, and north central Georgia, overlays with 470 and 678)<Eastern Time Zone>
+772 FL Florida (Vero Beach, Port Saint Lucie, Fort Pierce, Sebastian, Stuart and central eastern Florida)<Eastern Time Zone>
+773 IL Illinois (Chicago excluding downtown Chicago)<Central Time Zone>
+774 MA Massachusetts (Worcester and southeastern Massachusetts, overlays with 508)<Eastern Time Zone>
+775 NV Nevada (Reno, Elko, Ely and all of Nevada excluding Las Vegas and extreme southern Nevada)<Pacific Time Zone>
+778 BC British Columbia (Vancouver, Richmond, Abbotsford and southwestern BC overlays with 604)<Pacific Time Zone>
+779 IL Illinois (La Salle, De Kalb, Rockford, Freeport and northern Illinois excluding Chicago area, overlays with 815)<Central Time Zone>
+780 AB Alberta (Edmonton, Jasper, Grande Prairie, Peace River and northern Alberta)<Mountain Time Zone>
+781 MA Massachusetts (Saugus, Norwood and east central Massachusetts, overlays with 339)<Eastern Time Zone>
+784 ST VINCENT AND THE GRENADINES (all of St Vincent and the Grenadines)<Atlantic Time Zone (one hour later than Eastern)>
+785 KS Kansas (Colby, Topeka, Salina, Manhattan, Lawrence and northern Kansas)<Mountain & Central Time Zones>
+786 FL Florida (Miami, Homestead, Coral Gables, Key West and southeastern Florida, overlays with 305)<Eastern Time Zone>
+787 PUERTO RICO (all of Puerto Rico, overlays with 939)<Eastern & Atlantic Time Zone (does not observe daylight savings time)>
+800 TOLL FREE SERVICES
+801 UT Utah (Salt Lake City, Salt Lake County, Midvale, Alta, Magna, Kearns Holladay, and central Utah)<Mountain Time Zone>
+802 VT Vermont (all of Vermont)<Eastern Time Zone>
+803 SC South Carolina (Columbia, Rock Hill, Sumter, Aiken and central South Carolina)<Eastern Time Zone>
+804 VA Virginia (Richmond, Petersburg, West Point, Chester and east central Virginia)<Eastern Time Zone>
+805 CA California (Santa Barbara, San Luis Obispo, Lompoc and central western coastal California)<Pacific Time Zone>
+806 TX Texas (Amarillo, Lubbock, Canadian, Perryton, Shamrock, Dalhart and Texas panhandle)<Central Time Zone>
+807 ON Ontario (Thunder Bay and western Ontario)<Central & Eastern Time Zones>
+808 HI Hawaii (all of Hawaii)<Hawaiian Time Zone (2 or 3 hours earlier than Pacific Time, does not observe daylight savings)>
+809 DOMINICAN REPUBLIC (all of the Dominican Republic, overlays with 829)<Atlantic Time Zone>
+810 MI Michigan (Port Huron, Flint, Flushing, Warren and eastern Michigan, overlays with 586)<Eastern Time Zone>
+811 BUSINESS OFFICE
+812 IN Indiana (Evansville, New Albany, Terre Haute, Bloomington and southern Indiana)<Central & Eastern Time Zones>
+813 FL Florida (Tampa, Hillsborough, Plant City, Port Tampa and central western Florida)<Eastern Time Zone>
+814 PA Pennsylvania (Erie, Warren, Altoona, Johnstown, Meyersdale and central and northwestern Pennsylvania)<Eastern Time Zone>
+815 IL Illinois (La Salle, De Kalb, Rockford, Freeport and northern Illinois excluding Chicago area, overlays with 779)<Central Time Zone>
+816 MO Missouri (Kansas City, St Joseph, Independence, Harrisonville and west central Missouri)<Central Time Zone>
+817 TX Texas (Fort Worth, Arlington, Grandview, Weatherford, Rhome, overlays with 682)<Central Time Zone>
+818 CA California ( Glendale, San Fernando, Burbank and northern Los Angeles suburbs)<Pacific Time Zone>
+819 QC Quebec (Western Quebec)<Eastern Time Zone>
+822 TOLL FREE SERVICES
+828 NC North Carolina (Asheville, Brevard, Morganton, Murphy and western North Carolina)<Eastern Time Zone>
+829 DOMINICAN REPUBLIC (all of the Dominican Republic, overlays with 809)<Atlantic Time Zone>
+830 TX Texas (Uvalde, New Braunfels, Kerrville, Eagle Pass and southwest Texas)<Central Time Zone>
+831 CA California (Salinas, Hollister, Monterey, Santa Cruz and central western coastal California)<Pacific Time Zone>
+832 TX Texas (Spring, Katy, Houston area, overlays with 281 and 713)<Central Time Zone>
+833 TOLL FREE SERVICES
+835 PA Pennsylvania (Reading, Allentown, and southeastern Pennsylvania, overlays with 484 and 610)<Eastern Time Zone>
+843 SC South Carolina (Florence, Myrtle Beach, Charleston, Hilton Head Island and eastern South Carolina)<Eastern Time Zone>
+844 TOLL FREE SERVICES
+845 NY New York ( Poughkeepsie, Middletown, West Point, Newburgh and southeastern New York)<Eastern Time Zone>
+847 IL Illinois (Waukegan, Des Plaines, northwest Chicago suburbs and northeastern Illinois, overlays with 224)<Central Time Zone>
+848 NJ New Jersey (New Brunswick, Neptune, and east central New Jersey, overlays with 732)<Eastern Time Zone>
+850 FL Florida ( Pensacola, Tallahassee, Panama City and the Florida panhandle)<Central & Eastern Time Zones>
+855 TOLL FREE SERVICES
+856 NJ New Jersey (Vineland, Cherry Hill, Camden, Millville, and southwestern New Jersey)<Eastern Time Zone>
+857 MA Massachusetts (Boston, Cambridge and east central Massachusetts, overlays with 617)<Eastern Time Zone>
+858 CA California (Del Mar, La Jolla and northern San Diego suburbs)<Pacific Time Zone>
+859 KY Kentucky (Lexington, Richmond, Danville, Covington, Mount Sterling and north central Kentucky)<Eastern Time Zone>
+860 CT Connecticut (Bristol, Hartford, Norwich and northern and eastern Connecticut, overlays with 959)<Eastern Time Zone>
+862 NJ New Jersey (Newark, Paterson and northwestern New Jersey, overlays with 973)<Eastern Time Zone>
+863 FL Florida (Avon Park, Clewiston, Lakeland, Bartow, Sebring, Winter Haven and south central Florida)<Eastern Time Zone>
+864 SC South Carolina (Greenville, Spartanburg, Anderson and western South Carolina)<Eastern Time Zone>
+865 TN Tennessee (Knoxville, Newport, Jefferson City, Oak Ridge and east central Tennessee)<Eastern Time Zone>
+866 TOLL FREE SERVICES
+867 YK Yukon, Northwest Territories, and Nunavut (Yukon, Northwest Territories and Nunavut)<Pacific, Mountain, Central, Eastern, and Atlantic Time Zones>
+868 TRINIDAD AND TOBAGO (all of Trinidad and Tobago)<Atlantic Time Zone (one hour later than Eastern)>
+869 ST KITTS AND NEVIS (all of St Kitts and Nevis)<Atlantic Time Zone (one hour later than Eastern)>
+870 AR Arkansas (Texarkana, Mountain Home, Pine Bluff and southern, eastern and northeastern Arkansas)<Central Time Zone>
+876 JAMAICA (all of Jamaica)<Eastern Time Zone>
+877 TOLL FREE SERVICES
+878 PA Pennsylvania (Pittsburgh, New Castle, and southwestern Pennsylvania, overlays with 412 and 724)<Eastern Time Zone>
+880 PAID 800 SERVICE FROM CARIBBEAN TO THE US AND CANADA OR FROM CANADA TO THE US
+881 PAID 888 SERVICE FROM CARIBBEAN TO THE US AND CANADA OR FROM CANADA TO THE US
+882 PAID 877 SERVICE FROM CARIBBEAN TO THE US AND CANADA OR FROM CANADA TO THE US
+888 TOLL FREE SERVICES
+900 900 NUMBER PAY PER CALL SERVICES
+901 TN Tennessee (Memphis, Covington, Somerville and south western Tennessee)<Central Time Zone>
+902 NS Nova Scotia (all of Nova Scotia and Prince Edward Island)<Atlantic Time Zone>
+903 TX Texas (Tyler, Sherman, Longview, Palestine and northeastern Texas, overlays with 430)<Central Time Zone>
+904 FL Florida (Jacksonville, St Augustine, Starke, Green Cove Springs and northeastern Florida)<Eastern Time Zone>
+905 ON Ontario (Hamilton, Toronto suburbs and central southeastern Ontario, overlays with 289)<Eastern Time Zone>
+906 MI Michigan (Ironwood, Marquette, Sault Ste Marie, Escanaba and upper Michigan)<Central & Eastern Time Zones>
+907 AK Alaska (all of Alaska)<Alaskan (1 hour earlier than Pacific) & Aleutian (2 hours earlier than Pacific) Time Zones>
+908 NJ New Jersey (Washington, Elizabeth, Warren, Plainfield and west central New Jersey)<Eastern Time Zone>
+909 CA California (San Bernardino, Ontario, Pomona, Chino, Arrowhead and Big Bear Lake areas)<Pacific Time Zone>
+910 NC North Carolina (Fayetteville, Wilmington, Lumberton and southeastern North Carolina)<Eastern Time Zone>
+911 EMERGENCY
+912 GA Georgia ( Savannah, Vidalia, Waycross, Brunswick, Douglas and southeastern Georgia)<Eastern Time Zone>
+913 KS Kansas (Kansas City, Overland Park, Paola Leavenworth and extreme eastern Kansas)<Central Time Zone>
+914 NY New York (White Plains, Yonkers, Pelham, Westchester, Peekskill and southeastern New York)<Eastern Time Zone>
+915 TX Texas (El Paso, Dell City, Guadalupe Peak, Sierra Blanca, and far western Texas)<Mountain & Central Time Zones>
+916 CA California (Sacramento area)<Pacific Time Zone>
+917 NY New York (New York City Manhattan area, overlays with 212 and 646)<Eastern Time Zone>
+918 OK Oklahoma (Tulsa, Bartlesville, McAlester, Muskogee, Henrietta and northeastern Oklahoma)<Central Time Zone>
+919 NC North Carolina (Raleigh, Durham, Chapel Hill, Oxford and north central North Carolina)<Eastern Time Zone>
+920 WI Wisconsin (Sheboygan, Oshkosh, Green Bay, Manitowoc, Fond Du Lac and eastern Wisconsin)<Central Time Zone>
+925 CA California (Pleasanton, Martinez, Concord, Livermore, Walnut Creek and Dublin areas)<Pacific Time Zone>
+928 AZ Arizona (Flagstaff, Kingman, Prescott, Yuma and northern and western Arizona)<Mountain & Pacific Time Zones>
+931 TN Tennessee (Clarksville, Columbia, Manchester, Cookeville and central Tennessee)<Central & Eastern Time Zones>
+936 TX Texas (Nacogdoches, Lufkin, Conroe, Huntsville, Center and southeastern Texas)<Central Time Zone>
+937 OH Ohio (Marysville, Springfield, Dayton, Hillsboro and southwestern Ohio excluding Cincinnati area)<Eastern Time Zone>
+939 PUERTO RICO (all of Puerto Rico, overlays with 787)<Eastern & Atlantic Time Zone (does not observe daylight savings time)>
+940 TX Texas (Vernon, Wichita Falls, Denton, Gainesville, Decatur and north central Texas)<Central Time Zone>
+941 FL Florida ( Bradenton, Port Charlotte, Sarasota, Punta Gorda and the west central Florida coast)<Eastern Time Zone>
+947 MI Michigan (Troy, Oakland County, Pontiac, Southfield, Rochester Hills and northwestern Detroit suburbs, overlays with 248)<Eastern Time Zone>
+949 CA California (Laguna Niguel, Irvine, El Toro, Newport Beach, Corona Del Mar and southern Orange County)<Pacific Time Zone>
+951 CA California (Riverside, Corona, Murrieta, Perris, San Jacinto and Temecula areas)<Pacific Time Zone>
+952 MN Minnesota (Bloomington, Minnetonka, Chaska and southwest Minneapolis area)<Central Time Zone>
+954 FL Florida (Fort Lauderdale, Pompano Beach, overlays with 754)<Eastern Time Zone>
+956 TX Texas (Laredo, Brownsville, McAllen, Harlingen and southern Texas)<Central Time Zone>
+959 CT Connecticut (Bristol, Hartford, Norwich and northern and eastern Connecticut, overlays with 860)<Eastern Time Zone>
+970 CO Colorado (Aspen, Durango, Grand Junction, Fort Collins and northern and western Colorado)<Mountain Time Zone>
+971 OR Oregon (Portland, Salem, Hillsboro, Beaverton and northwestern Oregon, overlays with 503)<Pacific Time Zone>
+972 TX Texas (Dallas area, overlays with 214 and 469)<Central Time Zone>
+973 NJ New Jersey (Newark, Paterson and northwestern New Jersey, overlays with 862)<Eastern Time Zone>
+978 MA Massachusetts (Fitchburg, Peabody and northeastern Massachusetts, overlays with 351)<Eastern Time Zone>
+979 TX Texas (Wharton, Bryan, Bay City, College Station, Lake Jackson and southeastern Texas)<Central Time Zone>
+980 NC North Carolina (Charlotte, Kingstown and south central North Carolina, overlays with 704)<Eastern Time Zone>
+985 LA Louisiana (Houma, Slidell and southeastern Louisiana excluding New Orleans)<Central Time Zone>
+989 MI Michigan (Alpena, Mt Pleasant, Bay City, Saginaw, Midland, Owosso and central Michigan)<Eastern Time Zone>
diff --git a/etc/fslongtable.sty b/etc/fslongtable.sty
index fc936a1..e322b55 100644
--- a/etc/fslongtable.sty
+++ b/etc/fslongtable.sty
@@ -138,7 +138,6 @@
\advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
\advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
\advance\dimen@ \ht\LT@foot
- \advance\dimen@ \LTextracouponspace
\dimen@ii\vfuzz
\vfuzz\maxdimen
\setbox\tw@\copy\z@
diff --git a/fs_selfservice/FS-SelfService/MANIFEST b/fs_selfservice/FS-SelfService/MANIFEST
index a619b2b..2e4d3fe 100644
--- a/fs_selfservice/FS-SelfService/MANIFEST
+++ b/fs_selfservice/FS-SelfService/MANIFEST
@@ -5,4 +5,5 @@ SelfService.pm
SelfService/XMLRPC.pm
test.pl
freeside-selfservice-clientd
+freeside-selfservice-soap-server
freeside-selfservice-xmlrpc-server
diff --git a/fs_selfservice/FS-SelfService/Makefile.PL b/fs_selfservice/FS-SelfService/Makefile.PL
index c078f08..600c9d5 100644
--- a/fs_selfservice/FS-SelfService/Makefile.PL
+++ b/fs_selfservice/FS-SelfService/Makefile.PL
@@ -5,6 +5,7 @@ WriteMakefile(
'NAME' => 'FS::SelfService',
'VERSION_FROM' => 'SelfService.pm', # finds $VERSION
'EXE_FILES' => [ 'freeside-selfservice-clientd',
+ 'freeside-selfservice-soap-server',
'freeside-selfservice-xmlrpc-server',
],
'INSTALLSCRIPT' => '/usr/local/sbin',
diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm
index 580ca73..49629d4 100644
--- a/fs_selfservice/FS-SelfService/SelfService.pm
+++ b/fs_selfservice/FS-SelfService/SelfService.pm
@@ -35,13 +35,17 @@ $socket .= '.'.$tag if defined $tag && length($tag);
'list_invoices' => 'MyAccount/list_invoices', #?
'cancel' => 'MyAccount/cancel', #add to ss cgi!
'payment_info' => 'MyAccount/payment_info',
+ 'payment_info_renew_info' => 'MyAccount/payment_info_renew_info',
'process_payment' => 'MyAccount/process_payment',
'process_payment_order_pkg' => 'MyAccount/process_payment_order_pkg',
+ 'process_payment_change_pkg' => 'MyAccount/process_payment_change_pkg',
'process_payment_order_renew' => 'MyAccount/process_payment_order_renew',
'process_prepay' => 'MyAccount/process_prepay',
+ 'realtime_collect' => 'MyAccount/realtime_collect',
'list_pkgs' => 'MyAccount/list_pkgs', #add to ss (added?)
'list_svcs' => 'MyAccount/list_svcs', #add to ss (added?)
'list_svc_usage' => 'MyAccount/list_svc_usage',
+ 'list_cdr_usage' => 'MyAccount/list_cdr_usage',
'list_support_usage' => 'MyAccount/list_support_usage',
'order_pkg' => 'MyAccount/order_pkg', #add to ss cgi!
'change_pkg' => 'MyAccount/change_pkg',
@@ -56,8 +60,11 @@ $socket .= '.'.$tag if defined $tag && length($tag);
'unprovision_svc' => 'MyAccount/unprovision_svc',
'myaccount_passwd' => 'MyAccount/myaccount_passwd',
'signup_info' => 'Signup/signup_info',
+ 'skin_info' => 'MyAccount/skin_info',
+ 'access_info' => 'MyAccount/access_info',
'domain_select_hash' => 'Signup/domain_select_hash', # expose?
'new_customer' => 'Signup/new_customer',
+ 'capture_payment' => 'Signup/capture_payment',
'agent_login' => 'Agent/agent_login',
'agent_logout' => 'Agent/agent_logout',
'agent_info' => 'Agent/agent_info',
@@ -66,11 +73,27 @@ $socket .= '.'.$tag if defined $tag && length($tag);
'call_time' => 'PrepaidPhone/call_time',
'call_time_nanpa' => 'PrepaidPhone/call_time_nanpa',
'phonenum_balance' => 'PrepaidPhone/phonenum_balance',
+ 'bulk_processrow' => 'Bulk/processrow',
+ 'check_username' => 'Bulk/check_username',
+ #sg
+ 'ping' => 'SGNG/ping',
+ 'decompify_pkgs' => 'SGNG/decompify_pkgs',
+ 'previous_payment_info' => 'SGNG/previous_payment_info',
+ 'previous_payment_info_renew_info'
+ => 'SGNG/previous_payment_info_renew_info',
+ 'previous_process_payment' => 'SGNG/previous_process_payment',
+ 'previous_process_payment_order_pkg'
+ => 'SGNG/previous_process_payment_order_pkg',
+ 'previous_process_payment_change_pkg'
+ => 'SGNG/previous_process_payment_change_pkg',
+ 'previous_process_payment_order_renew'
+ => 'SGNG/previous_process_payment_order_renew',
);
@EXPORT_OK = (
keys(%autoload),
- qw( regionselector regionselector_hashref
- expselect popselector domainselector didselector )
+ qw( regionselector regionselector_hashref location_form
+ expselect popselector domainselector didselector
+ )
);
$ENV{'PATH'} ='/usr/bin:/usr/ucb:/bin';
@@ -533,6 +556,10 @@ State
Zip or postal code
+=item country
+
+Two-letter country code
+
=item payinfo
Card number
@@ -568,6 +595,16 @@ as parameter with the keys of both methods.
Returns a hash reference with a single key, B<error>, empty on success, or an
error message on errors.
+=item process_payment_change_pkg
+
+Combines the B<process_payment> and B<change_pkg> functions in one step. If the
+payment processes sucessfully, the package is ordered. Takes a hash reference
+as parameter with the keys of both methods.
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors.
+
+
=item process_payment_order_renew
Combines the B<process_payment> and B<order_renew> functions in one step. If
@@ -849,6 +886,31 @@ Returns a hash reference with a single key, B<error>, empty on success, or an
error message on errors. The special error '_decline' is returned for
declined transactions.
+=item change_pkg
+
+Changes a package for this customer.
+
+Takes a hash reference as parameter with the following keys:
+
+=over 4
+
+=item session_id
+
+Session identifier
+
+=item pkgnum
+
+Existing customer package.
+
+=item pkgpart
+
+New package to order (see L<FS::part_pkg>).
+
+=back
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors.
+
=item renew_info
Provides useful info for early renewals.
@@ -896,6 +958,20 @@ Specified as a integer UNIX timestamp.
Renewal date as a human-readable string. (Convenience for display;
subject to change, so best not to parse for the date.)
+=item pkgnum
+
+Package that will be renewed.
+
+=item expire_date
+
+Expiration date of the package that will be renewed.
+
+=item expire_date_pretty
+
+Expiration date of the package that will be renewed, as a human-readable
+string. (Convenience for display; subject to change, so best not to parse for
+the date.)
+
=back
=item order_renew
@@ -1370,6 +1446,52 @@ sub regionselector_hashref {
};
}
+=item location_form HASHREF | LIST
+
+Takes as input a hashref or list of key/value pairs with the following keys:
+
+=over 4
+
+=item session_id
+
+Current customer session_id
+
+=item no_asterisks
+
+Omit red asterisks from required fields.
+
+=item address1_label
+
+Label for first address line.
+
+=back
+
+Returns an HTML fragment for a location form (address, city, state, zip,
+country)
+
+=cut
+
+sub location_form {
+ my $param;
+ if ( ref($_[0]) ) {
+ $param = shift;
+ } else {
+ $param = { @_ };
+ }
+
+ my $session_id = delete $param->{'session_id'};
+
+ my $rv = mason_comp( 'session_id' => $session_id,
+ 'comp' => '/elements/location.html',
+ 'args' => [ %$param ],
+ );
+
+ #hmm.
+ $rv->{'error'} || $rv->{'output'};
+
+}
+
+
#=item expselect HASHREF | LIST
#
#Takes as input a hashref or list of key/value pairs with the following keys:
@@ -1537,6 +1659,8 @@ END
$text .= "}\n</SCRIPT>\n";
+ $param->{'acstate'} = '' unless defined($param->{'acstate'});
+
$text .=
qq!<TABLE CELLPADDING="0"><TR><TD><SELECT NAME="acstate"! .
qq!SIZE=1 onChange="acstate_changed(this)"><OPTION VALUE=-1>State!;
diff --git a/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html b/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html
index 62419d1..987b97e 100644
--- a/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html
+++ b/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html
@@ -1,13 +1,11 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Payment results</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error processing your payment: $error</FONT>!;
} else {
$OUT .= 'Your payment was processed successfully. Thank you.';
} %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/bill.html b/fs_selfservice/FS-SelfService/cgi/bill.html
index 1b59027..a3884e0 100644
--- a/fs_selfservice/FS-SelfService/cgi/bill.html
+++ b/fs_selfservice/FS-SelfService/cgi/bill.html
@@ -5,10 +5,10 @@
<TD ALIGN="right">Attention</TD>
<TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%=$payname%>"></TD>
</TR><TR>
+ <TD ALIGN="right">Postal mail invoice</TD>
<TD><INPUT TYPE="checkbox" NAME="postal_invoicing" VALUE="POST" <%=
$postal_invoicing ? 'CHECKED' : ''
%>></TD>
- <TD>Postal mail invoice</TD>
</TR><TR>
<TD>Email address(es)</TD>
<TD><INPUT TYPE="text" NAME="invoicing_list" VALUE="<%= join(',', $invoicing_list ) %>"></TD>
diff --git a/fs_selfservice/FS-SelfService/cgi/card.html b/fs_selfservice/FS-SelfService/cgi/card.html
index cf6d20d..c7db2b3 100644
--- a/fs_selfservice/FS-SelfService/cgi/card.html
+++ b/fs_selfservice/FS-SelfService/cgi/card.html
@@ -1,11 +1,11 @@
<TR>
- <TD ALIGN="right">Card&nbsp;number</TD>
- <TD>
+ <TH ALIGN="right">Card&nbsp;number</TH>
+ <TD COLSPAN=6>
<TABLE>
<TR>
<TD>
<INPUT TYPE="text" NAME="payinfo" SIZE=20 MAXLENGTH=19 VALUE="<%=$payinfo%>"> </TD>
- <TD>Exp.</TD>
+ <TH>Exp.</TH>
<TD>
<SELECT NAME="month">
<%= for ( ( map "0$_", 1 .. 9 ), 10 .. 12 ) {
@@ -35,39 +35,13 @@
'';
%>
<TR>
- <TD ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TD>
- <TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%=$payname%>"></TD>
-</TR><TR>
- <TD ALIGN="right">Card&nbsp;billing&nbsp;address</TD>
- <TD>
- <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address1" VALUE="<%=$address1%>">
- </TD>
-</TR><TR>
- <TD ALIGN="right">Address&nbsp;line&nbsp;2</TD>
- <TD>
- <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address2" VALUE="<%=$address2%>">
- </TD>
-</TR><TR>
- <TD ALIGN="right">City</TD>
- <TD>
- <TABLE>
- <TR>
- <TD>
- <INPUT TYPE="text" NAME="city" SIZE="12" MAXLENGTH=80 VALUE="<%=$city%>">
- </TD>
- <TD>State</TD>
- <TD>
- <SELECT NAME="state">
- <%= for ( @states ) {
- $OUT .= '<OPTION'. ($_ eq $state ? ' SELECTED' : '' ). ">$_\n";
- } %>
- </SELECT>
- </TD>
- <TD>Zip</TD>
- <TD>
- <INPUT TYPE="text" NAME="zip" SIZE=11 MAXLENGTH=10 VALUE="<%=$zip%>">
- </TD>
- </TR>
- </TABLE>
- </TD>
+ <TH ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TH>
+ <TD COLSPAN=6><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%=$payname%>"></TD>
</TR>
+
+<%= location_form( 'session_id' => $session_id,
+ 'no_asterisks' => 1,
+ #'address1_label' => 'Card billing address',
+ 'address1_label' => 'Card&nbsp;billing&nbsp;address',
+ )
+%>
diff --git a/fs_selfservice/FS-SelfService/cgi/change_bill.html b/fs_selfservice/FS-SelfService/cgi/change_bill.html
index f186c9b..c0977d9 100755
--- a/fs_selfservice/FS-SelfService/cgi/change_bill.html
+++ b/fs_selfservice/FS-SelfService/cgi/change_bill.html
@@ -1,9 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee">
-<FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Edit billing address</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT><BR><BR>!;
@@ -19,5 +16,5 @@
<INPUT TYPE="submit" NAME="submit" VALUE="<%= $custnum ? "Apply Changes" : "Add Customer" %>">
<BR>
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/change_password.html b/fs_selfservice/FS-SelfService/cgi/change_password.html
index dcfce31..9b91d2c 100644
--- a/fs_selfservice/FS-SelfService/cgi/change_password.html
+++ b/fs_selfservice/FS-SelfService/cgi/change_password.html
@@ -1,8 +1,5 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Change password</FONT><BR><BR>
@@ -47,5 +44,5 @@
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/change_pay.html b/fs_selfservice/FS-SelfService/cgi/change_pay.html
index 2bea955..e7a9969 100644
--- a/fs_selfservice/FS-SelfService/cgi/change_pay.html
+++ b/fs_selfservice/FS-SelfService/cgi/change_pay.html
@@ -1,21 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee">
-<script language="JavaScript"><!--
- var mywindow = -1;
- function myopen(filename,windowname,properties) {
- myclose();
- mywindow = window.open(filename,windowname,properties);
- }
- function myclose() {
- if ( mywindow != -1 )
- mywindow.close();
- mywindow = -1
- }
-//--></script>
-<FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Change payment information</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT><BR><BR>!;
@@ -51,10 +36,11 @@
'LECB' => qq/Phone Bill Billing/,
'BILL' => qq/Billing/,
'COMP' => qq/Complimentary/,
+ 'PREP' => qq/Prepaid Card/,
'PREPAY' => qq/Prepaid Card/,
);
tie my %options, 'Tie::IxHash', ();
- foreach my $payby_option ( @paybys ) {
+ foreach my $payby_option ( grep { exists( $payby_index{$_} ) } @paybys ) {
$options{$payby_option} = $payby_index{$payby_option};
}
$options{$payby} = $payby_index{$payby}
@@ -69,5 +55,5 @@
)->html;
%>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/change_ship.html b/fs_selfservice/FS-SelfService/cgi/change_ship.html
index 28ee94e..f03aeb5 100755
--- a/fs_selfservice/FS-SelfService/cgi/change_ship.html
+++ b/fs_selfservice/FS-SelfService/cgi/change_ship.html
@@ -1,9 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee">
-<FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Edit service address</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT><BR><BR>!;
@@ -98,5 +95,5 @@ function samechanged(what) {
<INPUT TYPE="submit" NAME="submit" VALUE="<%= $custnum ? "Apply Changes" : "Add Customer" %>">
<BR>
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi b/fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi
index 5f344a3..253f853 100644
--- a/fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi
@@ -7,10 +7,16 @@ use FS::SelfService qw( invoice_logo );
my $cgi = new CGI;
-my($query) = $cgi->keywords;
-$query =~ /^([^\.\/]*)$/ or '' =~ /^()$/;
-my $templatename = $1;
-my $hashref = invoice_logo('templatename' => $templatename);
+my %hash = ();
+if ( $cgi->param('invnum') ) {
+ $hash{$_} = scalar($cgi->param($_)) foreach qw( invnum template );
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^([^\.\/]*)$/ or '' =~ /^()$/;
+ $hash{'template'} = $1;
+}
+
+my $hashref = invoice_logo(%hash);
print $cgi->header( '-type' => $hashref->{'content_type'},
'-expires' => 'now',
diff --git a/fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html b/fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html
index 46d3faf..95bdab7 100644
--- a/fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html
+++ b/fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<%= include('change_pkg') %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html b/fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html
index 78cc16c..a20e8ac 100755
--- a/fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html
+++ b/fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<%= include('order_pkg') %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/delete_svc.html b/fs_selfservice/FS-SelfService/cgi/delete_svc.html
index 4155d09..e16b01e 100644
--- a/fs_selfservice/FS-SelfService/cgi/delete_svc.html
+++ b/fs_selfservice/FS-SelfService/cgi/delete_svc.html
@@ -1,8 +1,5 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT>!;
@@ -10,5 +7,5 @@
$OUT .= "<FONT SIZE=4>$svc removed.</FONT>";
} %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/footer.html b/fs_selfservice/FS-SelfService/cgi/footer.html
index 98cc79b..4889b74 100644
--- a/fs_selfservice/FS-SelfService/cgi/footer.html
+++ b/fs_selfservice/FS-SelfService/cgi/footer.html
@@ -1,3 +1,3 @@
-<HR>
-<FONT SIZE="-2">powered by <a href="http://www.freeside.biz/freeside">freeside</a></FONT>
+</TD></TR></TABLE>
+<%= $body_footer %>
</BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/header.html b/fs_selfservice/FS-SelfService/cgi/header.html
new file mode 100644
index 0000000..630959e
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/header.html
@@ -0,0 +1,23 @@
+<HTML>
+ <HEAD>
+ <TITLE><%= $title || 'MyAccount' %></TITLE>
+ <%= $head %>
+ </HEAD>
+ <BODY BGCOLOR="<%= $body_bgcolor || '#eeeeee' %>">
+ <script language="JavaScript"><!--
+ var mywindow = -1;
+ function myopen(filename,windowname,properties) {
+ myclose();
+ mywindow = window.open(filename,windowname,properties);
+ }
+ function myclose() {
+ if ( mywindow != -1 )
+ mywindow.close();
+ mywindow = -1
+ }
+ //--></script>
+ <%= $body_header %>
+ <FONT SIZE=5><%= $title || 'MyAccount' %></FONT>
+ <BR><BR>
+ <%= include('myaccount_menu') %>
+ <TD VALIGN="top">
diff --git a/fs_selfservice/FS-SelfService/cgi/iframecontentmws.js b/fs_selfservice/FS-SelfService/cgi/iframecontentmws.js
new file mode 100644
index 0000000..f2a91d2
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/iframecontentmws.js
@@ -0,0 +1,59 @@
+/*
+ iframecontentmws.js - Foteos Macrides (author and copyright holder)
+ Initial: October 10, 2004 - Last Revised: January 26, 2008
+ Scripts for using HTML documents as iframe content in overlibmws popups.
+
+ See http://www.macridesweb.com/oltest/IFRAME.html
+ and http://www.macridesweb.com/oltest/AJAX.html#ajaxex3
+ for more information.
+*/
+
+/*
+ Use as lead argument in overlib or overlb2 calls. Include WRAP and
+ TEXTPADDING,0 in the call to ensure that the width arg is respected (unless
+ the CAPTION plus CLOSETEXT widths add up to more than the width arg, in which
+ case you should increase the width arg). The name arg should be a unique
+ string for each popup with iframe content in the document. The frameborder
+ arg should be 1 (browser default if omitted) or 0. The scrolling arg should
+ be 'auto' (default if omitted), 'yes' or 'no'.
+*/
+function OLiframeContent(src, width, height, name, frameborder, scrolling) {
+
+ /* stupid safari iframe location caching... */
+ var d = new Date();
+ var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
+ name = name + '' + unique;
+
+ return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"'
+ +(name!=null?' name="'+name+'" id="'+name+'"':'')
+ +(frameborder!=null?' frameborder="'+frameborder+'"':'')
+ +' scrolling="'+(scrolling!=null?scrolling:'auto')
+ +'"><div>[iframe not supported]</div></iframe>');
+}
+
+/*
+ Swap the src if we are iframe content. The name arg should be the same
+ string as in the OLiframeContent function for the popup. The src arg is
+ a partial, relative, or complete URL for the document to be swapped in.
+*/
+function OLswapIframeSrc(name, src){
+ if(parent==self){
+ alert(src+'\n\n is only for iframe content');
+ return;
+ }
+ var o=parent.OLgetRef(name);
+ if(o)o.src=src;
+ else alert(src+'\n\n is not available');
+}
+
+/*
+ Emulate the Back button if we are iframe content. Use only in documents
+ which are swapped in by using the OLswapIframeSrc function.
+*/
+function OLiframeBack(){
+ if(parent==self){
+ alert('This feature is only for iframe content');
+ return;
+ }
+ history.back();
+}
diff --git a/fs_selfservice/FS-SelfService/cgi/login.html b/fs_selfservice/FS-SelfService/cgi/login.html
index e5daec8..eef412d 100644
--- a/fs_selfservice/FS-SelfService/cgi/login.html
+++ b/fs_selfservice/FS-SelfService/cgi/login.html
@@ -1,11 +1,18 @@
-<HTML><HEAD><TITLE>Login</TITLE></HEAD>
-<BODY BGCOLOR="#e8e8e8"><FONT SIZE=5>Login</FONT><BR><BR>
+<HTML>
+ <HEAD>
+ <TITLE>Login</TITLE>
+ <%= $head %>
+ </HEAD>
+ <BODY BGCOLOR="<%= $body_bgcolor || '#eeeeee' %>">
+ <%= $body_header %>
+
+<FONT SIZE=5>Login</FONT><BR><BR>
<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
<FORM ACTION="<%= $self_url %>" METHOD=POST>
<INPUT TYPE="hidden" NAME="session" VALUE="login">
-<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+<TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=2 CELLPADDING=0>
<TR>
<TH ALIGN="right">Username </TH>
@@ -50,13 +57,15 @@ if ( $single_domain ) {
if ( $phone_login ) {
+ $box_bgcolor ||= '#c0c0c0';
+
$OUT .= qq(
<B>OR</B><BR><BR>
<FORM ACTION="$self_url" METHOD=POST>
<INPUT TYPE="hidden" NAME="session" VALUE="login">
- <TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+ <TABLE BGCOLOR="$box_bgcolor" BORDER=0 CELLSPACING=2 CELLPADDING=0>
<TR>
<TH ALIGN="right">Phone number </TH>
<TD>
@@ -82,4 +91,4 @@ if ( $phone_login ) {
%>
-</BODY></HTML>
+<%= $body_footer %>
diff --git a/fs_selfservice/FS-SelfService/cgi/logout.html b/fs_selfservice/FS-SelfService/cgi/logout.html
index 0e774e9..5e22ad8 100644
--- a/fs_selfservice/FS-SelfService/cgi/logout.html
+++ b/fs_selfservice/FS-SelfService/cgi/logout.html
@@ -1,5 +1,13 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
+<HTML>
+ <HEAD>
+ <TITLE>MyAccount</TITLE>
+ <%= $head %>
+ </HEAD>
+ <BODY BGCOLOR="<%= $body_bgcolor || '#eeeeee' %>">
+ <%= $body_header %>
+
+ <FONT SIZE=5>MyAccount</FONT><BR><BR>
You have been logged out.
-</BODY></HTML>
+
+<%= $body_footer %>
diff --git a/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html b/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html
index 2394c10..8802a5d 100644
--- a/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html
+++ b/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html
@@ -1,21 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee">
-<script language="JavaScript"><!--
- var mywindow = -1;
- function myopen(filename,windowname,properties) {
- myclose();
- mywindow = window.open(filename,windowname,properties);
- }
- function myclose() {
- if ( mywindow != -1 )
- mywindow.close();
- mywindow = -1
- }
-//--></script>
-<FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Make a payment</FONT><BR><BR>
<FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
@@ -54,5 +39,5 @@
<INPUT TYPE="hidden" NAME="paybatch" VALUE="<%=$paybatch%>">
<INPUT TYPE="submit" NAME="process" VALUE="Process payment"> <!-- onClick="this.disabled=true"> -->
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html
index a468d99..96a17ba 100644
--- a/fs_selfservice/FS-SelfService/cgi/make_payment.html
+++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html
@@ -1,44 +1,29 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee">
-<script language="JavaScript"><!--
- var mywindow = -1;
- function myopen(filename,windowname,properties) {
- myclose();
- mywindow = window.open(filename,windowname,properties);
- }
- function myclose() {
- if ( mywindow != -1 )
- mywindow.close();
- mywindow = -1
- }
-//--></script>
-<FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Make a payment</FONT><BR><BR>
<FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
<INPUT TYPE="hidden" NAME="action" VALUE="payment_results">
<TABLE BGCOLOR="#cccccc">
<TR>
- <TD ALIGN="right">Amount&nbsp;Due</TD>
- <TD>
+ <TH ALIGN="right">Amount&nbsp;Due</TH>
+ <TD COLSPAN=7>
<TABLE><TR><TD BGCOLOR="#ffffff">
$<%=sprintf("%.2f",$balance)%>
</TD></TR></TABLE>
</TD>
</TR>
<TR>
- <TD ALIGN="right">Payment&nbsp;amount</TD>
- <TD>
+ <TH ALIGN="right">Payment&nbsp;amount</TH>
+ <TD COLSPAN=7>
<TABLE><TR><TD BGCOLOR="#ffffff">
$<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<%=sprintf("%.2f",$balance)%>">
</TD></TR></TABLE>
</TD>
</TR><TR>
- <TD ALIGN="right">Card&nbsp;type</TD>
- <TD>
+ <TH ALIGN="right">Card&nbsp;type</TH>
+ <TD COLSPAN=7>
<SELECT NAME="card_type"><OPTION></OPTION>
<%= foreach ( keys %card_types ) {
$selected = $card_type eq $card_types{$_} ? ' SELECTED' : '';
@@ -49,12 +34,12 @@
</TR>
<%= include('card') %>
<TR>
- <TD COLSPAN=2>
+ <TD COLSPAN=8>
<INPUT TYPE="checkbox" CHECKED NAME="save" VALUE="1">
Remember this information
</TD>
</TR><TR>
- <TD COLSPAN=2>
+ <TD COLSPAN=8>
<INPUT TYPE="checkbox"<%= $payby eq 'CARD' ? ' CHECKED' : '' %> NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }">
Charge future payments to this card automatically
</TD>
@@ -64,5 +49,5 @@
<INPUT TYPE="hidden" NAME="paybatch" VALUE="<%=$paybatch%>">
<INPUT TYPE="submit" NAME="process" VALUE="Process payment"> <!-- onClick="this.disabled=true"> -->
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html b/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
new file mode 100755
index 0000000..b2900b1
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
@@ -0,0 +1,37 @@
+<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= include('header') %>
+
+<SCRIPT TYPE="text/javascript">
+ function popcollect() {
+ overlib( OLiframeContent('<%= $popup_url %>', 336, 550, 'Secure Payment Area', 0, 'auto' ), CAPTION, 'Pay now', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close' );
+ return false;
+ }
+</SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_iframe.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_draggable.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_crossframe.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="iframecontentmws.js"></SCRIPT>
+
+<FONT SIZE=4>Pay now</FONT><BR><BR>
+
+<%= if ( $error ) {
+ $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
+}else{
+ $OUT .= <<EOF;
+ You are about to contact our payment processor to pay $amount.<BR><BR>
+ Your transaction reference number is $reference <BR><BR>
+ <FORM NAME="collect_popper" method="post" action="javascript:void(0)" onSubmit="popcollect()">
+EOF
+
+ my %itemhash = @collectitems;
+ foreach my $input (keys %itemhash) {
+ $OUT .= qq!<INPUT NAME="$input" TYPE="hidden" VALUE="$itemhash{$input}">!;
+ }
+
+ $OUT .= qq!<INPUT NAME="submit" type="submit" value="Pay now">!;
+ $OUT .= qq!</FORM>!;
+}
+%>
+
+<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/misc/counties.cgi b/fs_selfservice/FS-SelfService/cgi/misc/counties.cgi
new file mode 100755
index 0000000..476fe09
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/misc/counties.cgi
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+use strict;
+use CGI;
+use FS::SelfService qw( mason_comp );
+
+my $cgi = new CGI;
+
+my $rv = mason_comp( 'comp' => '/misc/counties.cgi',
+ 'query_string' => $cgi->query_string, #pass CGI params...
+ );
+
+#hmm.
+my $output = $rv->{'error'} || $rv->{'output'};
+
+print $cgi->header( '-expires' => 'now' ).
+ $output;
+
diff --git a/fs_selfservice/FS-SelfService/cgi/misc/part_svc-columns.cgi b/fs_selfservice/FS-SelfService/cgi/misc/part_svc-columns.cgi
new file mode 100755
index 0000000..4ee83ca
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/misc/part_svc-columns.cgi
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+use strict;
+use CGI;
+use FS::SelfService qw( mason_comp );
+
+my $cgi = new CGI;
+
+my $rv = mason_comp( 'comp' => '/misc/part_svc-columns.cgi',
+ 'query_string' => $cgi->query_string, #pass CGI params...
+ );
+
+#hmm.
+my $output = $rv->{'error'} || $rv->{'output'};
+
+print $cgi->header( '-expires' => 'now' ).
+ $output;
+
diff --git a/fs_selfservice/FS-SelfService/cgi/misc/states.cgi b/fs_selfservice/FS-SelfService/cgi/misc/states.cgi
new file mode 100755
index 0000000..f75f2ae
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/misc/states.cgi
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+use strict;
+use CGI;
+use FS::SelfService qw( mason_comp );
+
+my $cgi = new CGI;
+
+my $rv = mason_comp( 'comp' => '/misc/states.cgi',
+ 'query_string' => $cgi->query_string, #pass CGI params...
+ );
+
+#hmm.
+my $output = $rv->{'error'} || $rv->{'output'};
+
+print $cgi->header( '-expires' => 'now' ).
+ $output;
+
diff --git a/fs_selfservice/FS-SelfService/cgi/misc/svc_acct-domains.cgi b/fs_selfservice/FS-SelfService/cgi/misc/svc_acct-domains.cgi
new file mode 100755
index 0000000..c5413ba
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/misc/svc_acct-domains.cgi
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+use strict;
+use CGI;
+use FS::SelfService qw( mason_comp );
+
+my $cgi = new CGI;
+
+my $rv = mason_comp( 'comp' => '/misc/svc_acct-domains.cgi',
+ 'query_string' => $cgi->query_string, #pass CGI params...
+ );
+
+#hmm.
+my $output = $rv->{'error'} || $rv->{'output'};
+
+print $cgi->header( '-expires' => 'now' ).
+ $output;
+
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html
index cb5ed35..d6527fe 100644
--- a/fs_selfservice/FS-SelfService/cgi/myaccount.html
+++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html
@@ -1,14 +1,21 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
Hello <%= $name %>!<BR><BR>
<%= $small_custview %>
<BR>
+<%= if ( $pkgnum ) {
+ $OUT .= qq!Balance: <B>\$$balance</B><BR><BR>!;
+ }
+ '';
+%>
+
<%= if ( $balance > 0 ) {
- $OUT .= qq! <B><A HREF="${url}make_payment">Make a payment</A></B><BR><BR>!;
+ if (scalar(grep $_, @hide_payment_fields)) {
+ $OUT .= qq! <B><A HREF="${url}make_thirdparty_payment&payby_method=CC">Make a payment</A></B><BR><BR>!;
+ } else {
+ $OUT .= qq! <B><A HREF="${url}make_payment">Make a payment</A></B><BR><BR>!;
+ }
} %>
<%=
if ( @open_invoices ) {
@@ -90,5 +97,4 @@ Hello <%= $name %>!<BR><BR>
}
%>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
index ec5a8fa..617ae3e 100644
--- a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
+++ b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
@@ -1,60 +1,93 @@
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
<TABLE BORDER=0><TR>
-<TD VALIGN="top" HEIGHT="100%" BGCOLOR="#dddddd">
+<TD VALIGN="top" HEIGHT="100%" BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>">
<TABLE CELLSPACING=0 BORDER=0 HEIGHT="100%">
<%=
my @menu = (
-{ title=>' ' },
-{ title=>'Overview', url=>'myaccount', size=>'+1', },
-{ title=>' ' },
-
-{ title=>'Purchase', size=>'+1', },
- { title=>'Purchase additional package',
- url=>'customer_order_pkg', 'indent'=>2 },
+ { title=>' ' },
+ { title=>'Overview', url=>'myaccount', size=>'+1', },
+ { title=>' ' },
+ { title=>'Purchase', size=>'+1', },
);
+unless ( $pkgnum ) {
+ push @menu,
+ { title=>'Purchase additional package',
+ url=>'customer_order_pkg', 'indent'=>2 };
+}
+
if ( 1 ) { #XXXFIXME "enable selfservice prepay features" flag or something, eventually per-pkg or something really fancy
- push @menu, (
- { title=>'Recharge my account with a credit card',
- url=>'make_payment', indent=>2 },
- { title=>'Recharge my account with a check',
- url=>'make_ach_payment', indent=>2 },
- { title=>'Recharge my account with a prepaid card',
- url=>'recharge_prepay', indent=>2 },
- );
+ #XXXFIXME still a bit sloppy for multi-gateway of differing namespace
+ my $i = 0;
+ while($i < scalar(@cust_paybys)) { last if $cust_paybys[$i] =~ /^CARD/; $i++ }
+ if ( $cust_paybys[$i] =~ /^CARD/ ) {
+ push @menu, { title => 'Recharge my account with a credit card',
+ url => $hide_payment_fields[$i]
+ ? 'make_thirdparty_payment&payby_method=CC'
+ : 'make_payment',
+ indent => 2,
+ }
+ }
-}
+ $i = 0;
+ while($i < scalar(@cust_paybys)) { last if $cust_paybys[$i] =~ /^CHEK/; $i++ }
+ if ( $cust_paybys[$i] =~ /^CHEK/ ) {
+ push @menu, { title => 'Recharge my account with a check',
+ url => $hide_payment_fields[$i]
+ ? 'make_thirdparty_payment&payby_method=ECHECK'
+ : 'make_ach_payment',
+ indent => 2,
+ }
+ }
-push @menu, (
+ push @menu, { title => 'Recharge my account with a prepaid card',
+ url => 'recharge_prepay',
+ indent => 2,
+ }
+ if grep(/^PREP/, @cust_paybys);
-{ title=>' ' },
+}
-{ title=>'View my usage', url=>'view_usage', size=>'+1', },
-{ title=>'Setup my services', url=>'provision', size=>'+1', },
+push @menu,
+ { title=>' ' },
+ { title=>'View my usage', url=>'view_usage', size=>'+1', },
+;
-{ title=>' ' },
+unless ( $pkgnum ) {
+ push @menu,
+ { title=>'Setup my services', url=>'provision', size=>'+1', },
+ ;
+}
-{ title=>'Change my information', size=>'+1', },
- { title=>'Change billing address', url=>'change_bill', indent=>2 },
- { title=>'Change service address', url=>'change_ship', indent=>2 },
- { title=>'Change payment information', url=>'change_pay', indent=>2 },
- { title=>'Change password(s)', url=>'change_password', indent=>2 },
+push @menu,
+ { title=>' ' };
-{ title=>' ' },
+push @menu,
+ { title=>'Change my information', size=>'+1', };
-{ title=>'Logout', url=>'logout', size=>'+1', },
+unless ( $pkgnum ) {
+ push @menu,
+ { title=>'Change billing address', url=>'change_bill', indent=>2 },
+ { title=>'Change service address', url=>'change_ship', indent=>2 },
+ { title=>'Change payment information', url=>'change_pay', indent=>2 },
+ ;
+}
-);
+push @menu,
+ { title=>'Change password(s)', url=>'change_password', indent=>2 },
+ { title=>' ' },
+ { title=>'Logout', url=>'logout', size=>'+1', },
+;
foreach my $item ( @menu ) {
$OUT .= '<TR><TD';
if ( exists $item->{'url'} && $action eq $item->{'url'} ) {
- $OUT .= ' BGCOLOR="#eeeeee" '.
+ $OUT .= ' BGCOLOR="'. ( $body_bgcolor || '#eeeeee' ). '" '.
' STYLE="border-top: 1px solid black;'.
' border-left: 1px solid black;'.
' border-bottom: 1px solid black"';
@@ -63,15 +96,15 @@ foreach my $item ( @menu ) {
}
$OUT.='>';
- $OUT .= '<FONT SIZE="'. $item->{'size'}. '">'
- if exists $item->{'size'};
-
$OUT .= '&nbsp;' x $item->{'indent'}
if exists $item->{'indent'};
$OUT .= '<A HREF="'. $url. $item->{'url'}. '">'
if exists $item->{'url'} && $action ne $item->{'url'};
+ $OUT .= '<FONT SIZE="'. $item->{'size'}. '">'
+ if exists $item->{'size'};
+
$item->{'title'} =~ s/ /&nbsp;/g;
$OUT .= $item->{'title'};
diff --git a/fs_selfservice/FS-SelfService/cgi/order_pkg.html b/fs_selfservice/FS-SelfService/cgi/order_pkg.html
index 9cdd4cd..4abfd84 100644
--- a/fs_selfservice/FS-SelfService/cgi/order_pkg.html
+++ b/fs_selfservice/FS-SelfService/cgi/order_pkg.html
@@ -1,6 +1,6 @@
<SCRIPT TYPE="text/javascript">
function enable_order_pkg () {
- if ( document.OrderPkgForm.pkgpart.selectedIndex > 0 ) {
+ if ( document.OrderPkgForm.pkgpart_svcpart.selectedIndex > 0 ) {
document.OrderPkgForm.submit.disabled = false;
} else {
document.OrderPkgForm.submit.disabled = true;
@@ -16,46 +16,16 @@ function enable_order_pkg () {
<INPUT TYPE="hidden" NAME="action" VALUE="process_order_pkg">
<INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>">
<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
-<TR>
- <TD COLSPAN=2><SELECT NAME="pkgpart" onChange="enable_order_pkg()">
- <OPTION VALUE="">
-
- <%=
- foreach my $part_pkg ( @part_pkg ) {
- $OUT .= '<OPTION VALUE="'. $part_pkg->{'pkgpart'}. '"';
- $OUT .= ' SELECTED' if $pkgpart && $part_pkg->{'pkgpart'} == $pkgpart;
- $OUT .= '>'. $part_pkg->{'pkg'};
- }
- %>
- </SELECT></TD>
-</TR>
-<TR>
- <TD ALIGN="right">Username</TD>
- <TD><INPUT TYPE="text" NAME="username" VALUE="<%= $username %>"></TD>
-</TR>
-<TR>
- <TD ALIGN="right">Password</TD>
- <TD><INPUT TYPE="password" NAME="_password" VALUE="<%= $_password %>"></TD>
-</TR>
-<TR>
- <TD ALIGN="right">Re-enter Password</TD>
- <TD><INPUT TYPE="password" NAME="_password2" VALUE="<%= $_password2 %>"></TD>
-</TR>
-<%=
- if ( $security_phrase ) {
- $OUT .= <<ENDOUT;
<TR>
- <TD ALIGN="right">Security Phrase</TD>
- <TD><INPUT TYPE="text" NAME="sec_phrase" VALUE="$sec_phrase">
+ <TD COLSPAN=2>
+ <TABLE><TR><TD> <%= $pkg_selector %>
+
</TD>
</TR>
-ENDOUT
- } else {
- $OUT .= '<INPUT TYPE="hidden" NAME="sec_phrase" VALUE="">';
- }
-%>
+
<%=
+ if ( 0 ) {
if ( @svc_acct_pop ) {
$OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'.
popselector( 'popnum' => $popnum,
@@ -68,8 +38,10 @@ ENDOUT
} else {
$OUT .= popselector(popnum=>$popnum, pops=>\@svc_acct_pop);
}
+ }
+ '';
%>
</TABLE>
-<INPUT NAME="submit" TYPE="submit" VALUE="Purchase" disabled>
+<INPUT NAME="submit" TYPE="submit" VALUE="Purchase" DISABLED>
</FORM>
diff --git a/fs_selfservice/FS-SelfService/cgi/overlibmws.js b/fs_selfservice/FS-SelfService/cgi/overlibmws.js
new file mode 100644
index 0000000..df2bd1d
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/overlibmws.js
@@ -0,0 +1,620 @@
+/*
+ Do not remove or change this notice.
+ overlibmws.js core module - Copyright Foteos Macrides 2002-2008. All rights reserved.
+ Initial: August 18, 2002 - Last Revised: March 22, 2008
+ This module is subject to the same terms of usage as for Erik Bosrup's overLIB,
+ though only a minority of the code and API now correspond with Erik's version.
+ See the overlibmws Change History and Command Reference via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+ Give credit on sites that use overlibmws and submit changes so others can use them as well.
+ You can get Erik's version via: http://www.bosrup.com/web/overlib/
+*/
+
+// PRE-INIT -- Ignore these lines, configuration is below.
+var OLloaded=0,OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0,
+OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLmodalPI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0,OLprintPI=0,
+pmCnt=1,pMtr=new Array(),OLcmdLine=new Array(),OLrunTime=new Array(),OLv,OLudf,OLrefXY,
+OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%");if(typeof OLgateOK=='undefined')var OLgateOK=1;
+var OLp1or2c='inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,pady,below,above,vcenter,donothing',
+OLp1or2co='nofollow,background,offsetx,offsety,fgcolor,bgcolor,cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,'
++'base,status,autostatus,snapx,snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
++'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,vauto,nojustx,nojusty,fgclass,'
++'bgclass,cgclass,capbelow,textpadding,textfontclass,captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,'
++'closecolor,closefont,closesize,closeclick,closetitle,closefontclass,decode',OLp1or2o='text,cap,close,hpos,vpos,padxl,'
++'padxr,padyt,padyb',OLp1co='label',OLp1or2=OLp1or2co+','+OLp1or2o,OLp1=OLp1co+','+'frame';
+OLregCmds(OLp1or2c+','+OLp1or2co+','+OLp1co);
+function OLud(v){return eval('typeof ol_'+v+'=="undefined"')?1:0;}
+
+// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions
+if(OLud('fgcolor'))var ol_fgcolor="#ccccff";
+if(OLud('bgcolor'))var ol_bgcolor="#333399";
+if(OLud('cgcolor'))var ol_cgcolor="#333399";
+if(OLud('textcolor'))var ol_textcolor="#000000";
+if(OLud('capcolor'))var ol_capcolor="#ffffff";
+if(OLud('closecolor'))var ol_closecolor="#eeeeff";
+if(OLud('textfont'))var ol_textfont="Verdana,Arial,Helvetica";
+if(OLud('captionfont'))var ol_captionfont="Verdana,Arial,Helvetica";
+if(OLud('closefont'))var ol_closefont="Verdana,Arial,Helvetica";
+if(OLud('textsize'))var ol_textsize=1;
+if(OLud('captionsize'))var ol_captionsize=1;
+if(OLud('closesize'))var ol_closesize=1;
+if(OLud('fgclass'))var ol_fgclass="";
+if(OLud('bgclass'))var ol_bgclass="";
+if(OLud('cgclass'))var ol_cgclass="";
+if(OLud('textpadding'))var ol_textpadding=2;
+if(OLud('textfontclass'))var ol_textfontclass="";
+if(OLud('captionpadding'))var ol_captionpadding=2;
+if(OLud('captionfontclass'))var ol_captionfontclass="";
+if(OLud('closefontclass'))var ol_closefontclass="";
+if(OLud('close'))var ol_close="Close";
+if(OLud('closeclick'))var ol_closeclick=0;
+if(OLud('closetitle'))var ol_closetitle="Click to Close";
+if(OLud('text'))var ol_text="Default Text";
+if(OLud('cap'))var ol_cap="";
+if(OLud('capbelow'))var ol_capbelow=0;
+if(OLud('background'))var ol_background="";
+if(OLud('width'))var ol_width=200;
+if(OLud('wrap'))var ol_wrap=0;
+if(OLud('wrapmax'))var ol_wrapmax=0;
+if(OLud('height'))var ol_height= -1;
+if(OLud('border'))var ol_border=1;
+if(OLud('base'))var ol_base=0;
+if(OLud('offsetx'))var ol_offsetx=10;
+if(OLud('offsety'))var ol_offsety=10;
+if(OLud('sticky'))var ol_sticky=0;
+if(OLud('nofollow'))var ol_nofollow=0;
+if(OLud('noclose'))var ol_noclose=0;
+if(OLud('mouseoff'))var ol_mouseoff=0;
+if(OLud('offdelay'))var ol_offdelay=300;
+if(OLud('hpos'))var ol_hpos=RIGHT;
+if(OLud('vpos'))var ol_vpos=BELOW;
+if(OLud('status'))var ol_status="";
+if(OLud('autostatus'))var ol_autostatus=0;
+if(OLud('snapx'))var ol_snapx=0;
+if(OLud('snapy'))var ol_snapy=0;
+if(OLud('fixx'))var ol_fixx= -1;
+if(OLud('fixy'))var ol_fixy= -1;
+if(OLud('relx'))var ol_relx=null;
+if(OLud('rely'))var ol_rely=null;
+if(OLud('midx'))var ol_midx=null;
+if(OLud('midy'))var ol_midy=null;
+if(OLud('ref'))var ol_ref="";
+if(OLud('refc'))var ol_refc='UL';
+if(OLud('refp'))var ol_refp='UL';
+if(OLud('refx'))var ol_refx=0;
+if(OLud('refy'))var ol_refy=0;
+if(OLud('fgbackground'))var ol_fgbackground="";
+if(OLud('bgbackground'))var ol_bgbackground="";
+if(OLud('cgbackground'))var ol_cgbackground="";
+if(OLud('padxl'))var ol_padxl=1;
+if(OLud('padxr'))var ol_padxr=1;
+if(OLud('padyt'))var ol_padyt=1;
+if(OLud('padyb'))var ol_padyb=1;
+if(OLud('fullhtml'))var ol_fullhtml=0;
+if(OLud('capicon'))var ol_capicon="";
+if(OLud('frame'))var ol_frame=self;
+if(OLud('timeout'))var ol_timeout=0;
+if(OLud('delay'))var ol_delay=0;
+if(OLud('hauto'))var ol_hauto=0;
+if(OLud('vauto'))var ol_vauto=0;
+if(OLud('nojustx'))var ol_nojustx=0;
+if(OLud('nojusty'))var ol_nojusty=0;
+if(OLud('label'))var ol_label="";
+if(OLud('decode'))var ol_decode=0;
+// ARRAY CONFIGURATION - See overlibConfig.txt for descriptions.
+if(OLud('texts'))var ol_texts=new Array("Text 0","Text 1");
+if(OLud('caps'))var ol_caps=new Array("Caption 0","Caption 1");
+// END CONFIGURATION -- Don't change anything below, all configuration is above.
+
+// INIT -- Runtime variables.
+var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0,o3_offdelay=300,o3_hpos=RIGHT,
+o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="",o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",
+o3_width=200,o3_wrap=0,o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0,o3_snapy=0,
+o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null,o3_ref="",o3_refc='UL',o3_refp='UL',o3_refx=0,
+o3_refy=0,o3_fgbackground="",o3_bgbackground="",o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,
+o3_vpos=BELOW,o3_capicon="",o3_textfont="Verdana,Arial,Helvetica",o3_captionfont="",o3_closefont="",o3_textsize=1,OLcC=null,
+o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0,o3_hauto=0,o3_vauto=0,o3_nojustx=0,o3_nojusty=0,
+o3_close="",o3_closeclick=0,o3_closetitle="",o3_fgclass="",o3_bgclass="",o3_cgclass="",o3_textpadding=2,o3_textfontclass="",
+o3_captionpadding=2,o3_captionfontclass="",o3_closefontclass="",o3_capbelow=0,o3_label="",o3_decode=0,
+CSSOFF=DONOTHING,CSSCLASS=DONOTHING,over=null,OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0,OLfnRef="",OLhover=0,OLx=0,OLy=0,
+OLshowingsticky=0,OLallowmove=0,OLoverHTML="",OLover2HTML="",OLifRef="",OLo2Ref="",OLifX=0,OLifY=0,
+OLua=(OLv=navigator.userAgent)?OLv.toLowerCase():'',
+OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4)?1:0,
+OLns6=(document.getElementById)?1:0,
+OLie4=(document.all)?1:0,
+OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0,
+OLmac=(OLua.indexOf('mac')>=0)?1:0,
+OLsaf=(OLua.indexOf('safari')>=0)?1:0,
+OLkon=(OLua.indexOf('konqueror')>=0)?1:0,
+OLkht=(OLsaf||OLkon)?1:0,
+OLopr=(OLua.indexOf('opera')>=0)?1:0,
+OLop7=(OLopr&&document.createTextNode)?1:0;
+if(OLopr){OLns4=OLns6=OLgek=0;OLie4=(OLop7)?1:0;}
+var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0,
+OLie5=0,OLie55=0;OLie7=0;if(OLie4&&!OLop7){
+if((OLv=OLua.match(/msie (\d\.\d+)\.*/i))&&(OLv=parseFloat(OLv[1]))>=5.0){
+OLie5=1;OLns6=0;if(OLv>=5.5)OLie55=1;if(OLv>=7.0)OLie7=1;}if(OLns6)OLie4=0;}
+if(OLns4)window.onresize=function(){location.reload();};var OLchkMh=1,OLdw;
+if(OLns4||OLie4||OLns6){OLmh();if(window.addEventListener)window.addEventListener("unload",
+OLulCl,false);}else{overlib=nd=cClick=OLpageDefaults=no_overlib;}
+function OLulCl(){if(over)cClick();window.removeEventListener("unload",OLulCl,false);}
+
+/*
+ PUBLIC FUNCTIONS
+*/
+// Loads defaults then args into runtime variables.
+function overlib(){
+if(!(OLloaded&&OLgateOK))return;if((OLexclusivePI)&&OLisExclusive(arguments))return true;if(OLchkMh)OLmh();
+if(OLndt&&!OLtimerid)OLndt=0;if(over)cClick();if(parent!=self){if(parent.OLo2Ref){parent.OLeval(parent.OLo2Ref);
+parent.OLo2Ref="";}if(parent.OLifRef){parent.OLeval(parent.OLifRef);parent.OLifRef="";}}if(OLo2Ref){eval(OLo2Ref);
+OLo2Ref="";}if(OLifRef){eval(OLifRef);OLifRef="";}OLload(OLp1or2);OLload(OLp1);OLfnRef="";OLifX=0;OLifY=0;OLhover=0;
+OLsetRunTimeVar();OLparseTokens('o3_',arguments);if(!(over=OLmkLyr()))return false;if(o3_decode)OLdecode();if(OLprintPI)
+OLchkPrint();if(OLbubblePI)OLchkForBubbleEffect();if(OLdebugPI)OLsetDebugCanShow();if(OLshadowPI)OLinitShadow();
+if(OLiframePI)OLinitIfs();if(OLfilterPI)OLinitFilterLyr();if(OLexclusivePI&&o3_exclusive&&o3_exclusivestatus!="")
+o3_status=o3_exclusivestatus;else if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;else if(o3_autostatus==1&&o3_text!="")
+o3_status=o3_text;if(!o3_delay){return OLmain();}else{OLdelayid=setTimeout("OLmain()",o3_delay);if(o3_status!=""){
+self.status=o3_status;return true;}else if(!(OLop7&&event&&event.type=='mouseover'))return false;}
+}
+function OLeval(s){eval(s);}
+
+// Clears popups if appropriate
+function nd(time){
+if(OLloaded&&OLgateOK){if(!((OLexclusivePI)&&OLisExclusive())){if(time&&over&&!o3_delay){
+if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=(OLhover&&o3_frame==self&&!OLcursorOff())?0:
+setTimeout("cClick()",(o3_timeout=OLndt=time));}else{if(!OLshowingsticky){OLallowmove=0;
+if(over)OLhideObject(over);}}}}return false;
+}
+
+// Close function for stickies
+function cClick(){
+if(OLloaded&&OLgateOK){OLhover=0;if(over){if(OLo2Ref){eval(OLo2Ref);OLo2Ref="";}if(OLovertwoPI&&over==over2)cClick2();
+OLhideObject(over);OLshowingsticky=0;OLallowmove=0;}if(OLmodalPI)OLclearModal();}return false;
+}
+
+// Sets page-specific defaults.
+function OLpageDefaults(){
+OLparseTokens('ol_',arguments);
+}
+
+// Gets object referenced by its id or name
+function OLgetRef(l,d){var r=OLgetRefById(l,d);return (r)?r:OLgetRefByName(l,d);}
+
+// For unsupported browsers.
+function no_overlib(){return false;}
+
+/*
+ OVERLIB MAIN FUNCTION SET
+*/
+function OLmain(){
+o3_delay=0;if(parent!=self&&o3_frame==parent&&parent.OLscrollPI&&parent.over)parent.OLclearScroll();if(o3_frame==self){
+if(o3_noclose)OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);}if(o3_sticky){OLshowingsticky=1;if(OLfnRef&&
+parent!=self&&o3_frame==parent&&parent.overlib){parent.OLifRef=OLfnRef+'cClick()';}}OLdoLyr();OLallowmove=0;if(o3_timeout>0){
+if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_timeout);}OLchkRef();OLdisp(o3_status);
+if(OLdraggablePI)OLcheckDrag();if(o3_status!="")return true;else if(!(OLop7&&event&&event.type=='mouseover'))return false;
+}
+function OLchkRef(){
+if(o3_ref){OLrefXY=OLgetRefXY(o3_ref);if(OLrefXY[0]==null&&OLcrossframePI)OLchkIfRef();
+if(OLrefXY[0]==null){o3_ref="";o3_midx=0;o3_midy=0;}}
+}
+
+// Loads o3_ variables
+function OLload(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=ol_'+m[i]);}
+
+// Chooses LGF
+function OLdoLGF(){
+return (o3_background!=''||o3_fullhtml)?OLcontentBackground(o3_text,o3_background,o3_fullhtml):(o3_cap=="")?
+OLcontentSimple(o3_text):(o3_sticky)?OLcontentCaption(o3_text,o3_cap,o3_close):OLcontentCaption(o3_text,o3_cap,'');
+}
+
+// Makes Layer
+function OLmkLyr(id,f,z){
+id=(id||'overDiv');f=(f||o3_frame);z=(z||1000);var fd=f.document,d=OLgetRefById(id,fd);
+if(!d){if(OLns4)d=fd.layers[id]=new Layer(1024,f);else if(OLie4&&!OLop7){
+fd.body.insertAdjacentHTML('AfterBegin','<div id="'+id+'"></div>');d=fd.all[id];}else{d=fd.createElement('div');
+if(d){d.id=id;fd.body.appendChild(d);}}if(!d)return null;if(OLns4)d.zIndex=z;else{var o=d.style;o.position='absolute';
+o.visibility='hidden';o.zIndex=z;}}return d;
+}
+
+// Creates and writes layer content
+function OLdoLyr(){
+if(o3_sticky&&OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}if(o3_background==''&&!o3_fullhtml){
+if(o3_fgbackground!='')o3_fgbackground=' background="'+o3_fgbackground+'"';
+if(o3_bgbackground!='')o3_bgbackground=' background="'+o3_bgbackground+'"';
+if(o3_cgbackground!='')o3_cgbackground=' background="'+o3_cgbackground+'"';
+if(o3_fgcolor!='')o3_fgcolor=' bgcolor="'+o3_fgcolor+'"';if(o3_bgcolor!='')o3_bgcolor=' bgcolor="'+o3_bgcolor+'"';
+if(o3_cgcolor!='')o3_cgcolor=' bgcolor="'+o3_cgcolor+'"';if(o3_height>0)o3_height=' height="'+o3_height+'"';
+else o3_height='';}if(!OLns4)OLrepositionTo(over,(OLns6?20:0),0);var lyrHtml=OLdoLGF();
+if(o3_wrap&&!o3_fullhtml){OLlayerWrite(lyrHtml);o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLie4){
+var w=OLfd().clientWidth;if(o3_width>=w){if(OLop7){if(OLovertwoPI&&over==over2){var z=over2.style.zIndex;
+o3_frame.document.body.removeChild(over);over2=OLmkLyr('overDiv2',o3_frame,z);over=over2;}else{
+o3_frame.document.body.removeChild(over);over=OLmkLyr();}}o3_width=w-20;}}
+if(o3_wrapmax<1&&o3_frame.innerWidth)o3_wrapmax=o3_frame.innerWidth-40;
+if(o3_wrapmax>0&&o3_width>o3_wrapmax)o3_width=o3_wrapmax;o3_wrap=0;lyrHtml=OLdoLGF();}OLlayerWrite(lyrHtml);
+o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLbubblePI)OLgenerateBubble(lyrHtml);
+}
+
+/*
+ LAYER GENERATION FUNCTIONS
+*/
+// Makes simple table without caption
+function OLcontentSimple(txt){
+var t=OLbgLGF()+OLfgLGF(txt)+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// Makes table with caption and optional close link
+function OLcontentCaption(txt,title,close){
+var closing=(OLprintPI?OLprintCapLGF():''),closeevent='onmouseover',caption,t,cC='javascript:return '+OLfnRef
++(OLovertwoPI&&over==over2?'cClick2();':'cClick();');if(o3_closeclick)closeevent=(o3_closetitle?'title="'
++o3_closetitle+'" ':'')+'onclick';if(o3_capicon!=''&&o3_capicon.indexOf('<img')!=0)o3_capicon='<img src="'+o3_capicon
++'" /> ';if(close){closing+='<td align="right"><a href="'+cC+'" '+closeevent+'="'+cC+'"'+(o3_closefontclass?' class="'
++o3_closefontclass+'">':(OLns4?'><':'')+OLlgfUtil(0,1,'','a',o3_closecolor,o3_closefont,o3_closesize))+close+
+(o3_closefontclass?'':(OLns4?OLlgfUtil(1,1,'','a'):''))+'</a></td>';}caption='<table id="overCap'
++(OLovertwoPI&&over==over2?'2':'')+'"'+OLwd(0)+' border="0" cellpadding="'+o3_captionpadding+'" cellspacing="0"'
++(o3_cgclass?' class="'+o3_cgclass+'"':o3_cgcolor+o3_cgbackground)+'><tr><td'+OLwd(0)+(o3_cgclass?' class="'
++o3_cgclass+'">':'>')+(o3_captionfontclass?'<div'+OLhL(1)+' class="'+o3_captionfontclass+'">':OLlgfUtil(0,1,'','div',
+o3_capcolor,o3_captionfont,o3_captionsize))+o3_capicon+title+OLlgfUtil(1,1,'','div')+'</td>'+closing+'</tr></table>';
+t=OLbgLGF()+(o3_capbelow?OLfgLGF(txt)+caption:caption+OLfgLGF(txt))+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// For BACKGROUND and FULLHTML commands
+function OLcontentBackground(txt,image,hasfullhtml){
+var t;if(hasfullhtml){t=txt;}else{t='<table'+OLwd(1)+' border="0" cellpadding="0" '+'cellspacing="0" '+'height="'
++o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="top"'
++OLwd(2)+'>'+OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+OLlgfUtil(1,0,'','div')
++'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';}
+OLsetBackground(image);return t;
+}
+
+// LGF utilities
+function OLbgLGF(){
+return '<table'+OLwd(1)+o3_height+' border="0" cellpadding="'+o3_border+'" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':o3_bgcolor+o3_bgbackground)+'><tr><td>';
+}
+function OLfgLGF(t){
+return '<table'+OLwd(0)+o3_height+' border="0" cellpadding="'+o3_textpadding+'" cellspacing="0"'+(o3_fgclass?' class="'
++o3_fgclass+'"':o3_fgcolor+o3_fgbackground)+'><tr><td valign="top"'+(o3_fgclass?' class="'+o3_fgclass+'"':'')+'>'
++OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t+(OLprintPI?OLprintFgLGF():'')
++OLlgfUtil(1,0,'','div')+'</td></tr></table>';
+}
+function OLlgfUtil(end,stg,tfc,ele,col,fac,siz){
+if(end)return('</'+(OLns4?'font'+(stg?'></strong':''):ele)+'>');else return(tfc?'<div'+OLhL(1)+' class="'+tfc+'">':
+((ele=='a'?'':'<')+(OLns4?(stg?'strong><':'')+'font color="'+col+'" face="'+OLquoteMultiNameFonts(fac)+'" size="'
++siz:(ele=='a'?'':ele)+' style="'+((ele=='div')?OLhL(0):'')+'color:'+col+(stg?';font-weight:bold':'')+';font-family:'
++OLquoteMultiNameFonts(fac)+';font-size:'+siz+';'+(ele=='span'?'text-decoration:underline;':''))+'">'));
+}
+function OLquoteMultiNameFonts(f){
+var i,v,pM=f.split(',');for(i=0;i<pM.length;i++){v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');
+if(/\s/.test(v) && !/['"]/.test(v)){v="\'"+v+"\'";pM[i]=v;}}return pM.join();
+}
+function OLbaseLGF(){
+return ((o3_base>0&&!o3_wrap)?('<table width="100%" border="0" cellpadding="0" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':'')+'><tr><td height="'+o3_base+'"></td></tr></table>'):'')+'</td></tr></table>';
+}
+function OLwd(a){return(o3_wrap?'':' width="'+(!a?'100%':(a==1?o3_width:(o3_width-o3_padxl-o3_padxr)))+'"');}
+function OLhL(s){return(s?' style="width:100%;"':'width:100%;');}
+
+// Loads image into the div.
+function OLsetBackground(i){
+if(i==''){if(OLns4)over.background.src=null;else{if(OLns6)over.style.width='';over.style.backgroundImage='none';}}
+else{if(OLns4)over.background.src=i;else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i+')';}}
+}
+
+/*
+ HANDLING FUNCTIONS
+*/
+// Displays layer
+function OLdisp(s){
+if(OLmodalPI&&!o3_modalscroll)OLchkModal();if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();
+OLplaceLayer();if(OLmodalPI&&o3_modalscroll)OLchkModal();if(OLndt)OLshowObject(over);
+else OLshowid=setTimeout("OLshowObject(over)",1);OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;
+}
+
+// Decides placement of layer.
+function OLplaceLayer(){
+var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,o=OLfd(),
+nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
+if(!OLkht&&o&&o.clientWidth)iWd=o.clientWidth;
+else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));
+if(SB>20)SB=20;iWd=o3_frame.innerWidth;}
+pgLeft=(OLie4)?o.scrollLeft:o3_frame.pageXOffset;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);
+LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);}
+if(o3_ref!=""||o3_fixx> -1||o3_relx!=null||o3_midx!=null){
+if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='UR'||o3_refp=='LR')X-=5;}
+else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
+if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else
+if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}
+}else{if(o3_midx!=null){
+X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);
+}else{if(o3_relx!=null){
+if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;
+}else{X=o3_fixx+LM;}}}
+}else{
+if(o3_hauto){
+if(o3_hpos==LEFT&&OLx-pgLeft+OLifX<iWd/2&&OLx-pWd-o3_offsetx+OLifX<pgLeft+LM)o3_hpos=RIGHT;else
+if(o3_hpos==RIGHT&&OLx-pgLeft+OLifX>iWd/2&&OLx+pWd+o3_offsetx+OLifX>pgLeft+iWd-SB)o3_hpos=LEFT;}
+X=(o3_hpos==CENTER)?parseInt(OLx-((pWd+CX)/2)+o3_offsetx):
+(o3_hpos==LEFT)?OLx-o3_offsetx-pWd:OLx+o3_offsetx;
+if(o3_snapx>1){
+snp=X % o3_snapx;
+if(o3_hpos==LEFT){X=X-(o3_snapx+snp);}else{X=X+(o3_snapx-snp);}}X+=OLifX;}
+if(!o3_nojustx&&X+pWd>pgLeft+iWd-SB)
+X=iWd+pgLeft-pWd-SB;if(!o3_nojustx&&X-LM<pgLeft)X=pgLeft+LM;
+pgTop=OLie4?o.scrollTop:o3_frame.pageYOffset;
+if(!OLkht&&!nsb&&o&&o.clientHeight)iHt=o.clientHeight;
+else if(o3_frame.innerHeight)iHt=o3_frame.innerHeight;
+if(OLbubblePI&&o3_bubble)pHt=OLbubbleHt;else pHt=OLns4?over.clip.height:over.offsetHeight;
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){TM=(o3_shadowy<0)?Math.abs(o3_shadowy):0;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)BM=CY=5;else
+BM=(o3_shadowy>0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);}
+if(o3_ref!=""||o3_fixy> -1||o3_rely!=null||o3_midy!=null){
+if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
+if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else
+if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}
+}else{if(o3_midy!=null){
+Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);
+}else{if(o3_rely!=null){
+if(o3_rely>=0)Y=pgTop+o3_rely+TM;else Y=pgTop+o3_rely+iHt-pHt-BM;}else{
+Y=o3_fixy+TM;}}}
+}else{
+if(o3_vauto){
+if(o3_vpos==ABOVE&&OLy-pgTop+OLifY<iHt/2&&OLy-pHt-o3_offsety+OLifY<pgTop)o3_vpos=BELOW;else
+if(o3_vpos==BELOW&&OLy-pgTop+OLifY>iHt/2&&OLy+pHt+o3_offsety+((OLns4||OLkht)?17:0)+OLifY>pgTop+iHt-BM)
+o3_vpos=ABOVE;}Y=(o3_vpos==VCENTER)?parseInt(OLy-((pHt+CY)/2)+o3_offsety):
+(o3_vpos==ABOVE)?OLy-(pHt+o3_offsety+BM):OLy+o3_offsety+TM;
+if(o3_snapy>1){
+snp=Y % o3_snapy;
+if(pHt>0&&o3_vpos==ABOVE){Y=Y-(o3_snapy+snp);}else{Y=Y+(o3_snapy-snp);}}Y+=OLifY;}
+if(!o3_nojusty&&Y+pHt+BM>pgTop+iHt)Y=pgTop+iHt-pHt-BM;if(!o3_nojusty&&Y-TM<pgTop)Y=pgTop+TM;
+OLrepositionTo(over,X,Y);
+if(OLshadowPI)OLrepositionShadow(X,Y);if(OLiframePI)OLrepositionIfs(X,Y);
+if(OLns6&&o3_frame.innerHeight){iHt=o3_frame.innerHeight;OLrepositionTo(over,X,Y);}
+if(OLscrollPI)OLchkScroll(X-pgLeft,Y-pgTop);
+}
+
+// Chooses body or documentElement
+function OLfd(f){
+var fd=((f)?f:o3_frame).document,fdc=fd.compatMode,fdd=fd.documentElement;
+return (!OLop7&&fdc&&fdc!='BackCompat'&&fdd&&fdd.clientWidth)?fd.documentElement:fd.body;
+}
+
+// Gets location of REFerence object
+function OLgetRefXY(r,d){
+var o=OLgetRef(r,d),ob=o,rXY=[o3_refx,o3_refy],of;if(!o)return [null,null];if(OLns4){
+if(typeof o.length!='undefined'&&o.length>1){ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;}else{
+if((o.toString().indexOf('Image')!= -1)||(o.toString().indexOf('Anchor')!= -1)){rXY[0]+=o.x;rXY[1]+=o.y;}
+else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');}
+of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];return rXY;
+}
+
+// Seeks REFerence by id
+function OLgetRefById(l,d){
+l=(l||'overDiv');d=(d||o3_frame.document);var j,r;if(d.getElementById)return d.getElementById(l);
+if(OLie4&&d.all)return d.all[l];if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
+for(j=0;j<d.layers.length;j++){r=OLgetRefById(l,d.layers[j].document);if(r)return r;}}return null;
+}
+
+// Seeks REFerence by name
+function OLgetRefByName(l,d){
+d=(d||o3_frame.document);var j,r,v=OLie4?d.all.tags('iframe'):OLns6?d.getElementsByTagName('iframe'):null;
+if(typeof d.images!='undefined'&&d.images[l])return d.images[l];
+if(typeof d.anchors!='undefined'&&d.anchors[l])return d.anchors[l];
+if(v)for(j=0;j<v.length;j++)if(v[j].name==l)return v[j];if(d.layers&&d.layers.length>0)for(j=0;j<d.layers.length;j++){
+r=OLgetRefByName(l,d.layers[j].document);if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}return null;
+}
+
+// Gets layer vs REFerence offsets
+function OLgetRefOffsets(o){
+var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];pW=(OLbubblePI&&o3_bubble)?
+o3_width:OLns4?over.clip.width:over.offsetWidth;pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?
+over.clip.height:over.offsetHeight;if((!OLop7)&&o.toString().indexOf('Image')!= -1){W=o.width;H=o.height;}
+else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){c=o3_refc='UL';}else{W=(OLns4)?o.clip.width:o.offsetWidth;
+H=(OLns4)?o.clip.height:o.offsetHeight;}if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);
+H+=2*parseInt(o.border);}if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];}else if(c=='UR'){
+of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:
+(p=='LR')?[-pW,H-pH]:[0,H];}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:[W,H];}return of;
+}
+
+// Gets x or y location of object
+function OLpageLoc(o,t){
+var l=0,s=o;while(o.offsetParent&&o.offsetParent.tagName.toLowerCase()!='html'){l+=o['offset'+t];o=o.offsetParent;}
+l+=o['offset'+t];while(s=s.parentNode){if((s['scroll'+t]>0)&&s.tagName.toLowerCase()=='div')l-=s['scroll'+t];}return l;
+}
+
+// Moves layer
+function OLmouseMove(e){
+var e=(e||event);OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);OLx=(e.pageX||e.clientX+OLfd().scrollLeft);
+OLy=(e.pageY||e.clientY+OLfd().scrollTop);if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById()||(OLovertwoPI&&
+over2==over&&over==OLgetRefById('overDiv2')))){OLplaceLayer();if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}if(OLhover&&over&&
+o3_frame==self&&OLcursorOff())if(o3_offdelay<1)OLcC();else{if(OLtimerid>0)clearTimeout(OLtimerid);
+OLtimerid=setTimeout("OLcC()",o3_offdelay);}
+}
+
+// Capture mouse and chain other scripts.
+function OLmh(){
+var fN,f,j,k,s,mh=OLmouseMove,w=(OLns4&&window.onmousemove),re=/function[ ]*(\w*)\(/;OLdw=document;if(document.onmousemove||
+w){if(w)OLdw=window;f=OLdw.onmousemove.toString();fN=f.match(re);if(!fN||fN[1]=='anonymous'||fN[1]=='OLmouseMove'){OLchkMh=0;
+return;}if(fN[1])s=fN[1]+'(e)';else{j=f.indexOf('{');k=f.lastIndexOf('}')+1;s=f.substring(j,k);}s+=';OLmouseMove(e);';
+mh=new Function('e',s);}OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE);
+}
+
+/*
+ PARSING
+*/
+function OLparseTokens(pf,ar){
+var i,v,md= -1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
+for(i=0;i<ar.length;i++){if(md<0){if(typeof ar[i]=='number'){OLudf=(par?1:0);i--;}
+else{switch(pf){case 'ol_':ol_text=ar[i];break;default:o3_text=ar[i];}}md=0;}else{
+if(ar[i]==INARRAY){OLudf=0;eval(pf+'text=ol_texts['+ar[++i]+']');continue;}
+if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[++i]+']');continue;}
+if(ar[i]==CAPTION){q(ar[++i],pf+'cap');continue;}
+if(Math.abs(ar[i])==STICKY){t(ar[i],pf+'sticky');continue;}
+if(Math.abs(ar[i])==NOFOLLOW){t(ar[i],pf+'nofollow');continue;}
+if(ar[i]==BACKGROUND){q(ar[++i],pf+'background');continue;}
+if(Math.abs(ar[i])==NOCLOSE){t(ar[i],pf+'noclose');continue;}
+if(Math.abs(ar[i])==MOUSEOFF){t(ar[i],pf+'mouseoff');continue;}
+if(ar[i]==OFFDELAY){p(ar[++i],pf+'offdelay');continue;}
+if(ar[i]==RIGHT||ar[i]==LEFT||ar[i]==CENTER){p(ar[i],pf+'hpos');continue;}
+if(ar[i]==OFFSETX){p(ar[++i],pf+'offsetx');continue;}
+if(ar[i]==OFFSETY){p(ar[++i],pf+'offsety');continue;}
+if(ar[i]==FGCOLOR){q(ar[++i],pf+'fgcolor');continue;}
+if(ar[i]==BGCOLOR){q(ar[++i],pf+'bgcolor');continue;}
+if(ar[i]==CGCOLOR){q(ar[++i],pf+'cgcolor');continue;}
+if(ar[i]==TEXTCOLOR){q(ar[++i],pf+'textcolor');continue;}
+if(ar[i]==CAPCOLOR){q(ar[++i],pf+'capcolor');continue;}
+if(ar[i]==CLOSECOLOR){q(ar[++i],pf+'closecolor');continue;}
+if(ar[i]==WIDTH){p(ar[++i],pf+'width');continue;}
+if(Math.abs(ar[i])==WRAP){t(ar[i],pf+'wrap');continue;}
+if(ar[i]==WRAPMAX){p(ar[++i],pf+'wrapmax');continue;}
+if(ar[i]==HEIGHT){p(ar[++i],pf+'height');continue;}
+if(ar[i]==BORDER){p(ar[++i],pf+'border');continue;}
+if(ar[i]==BASE){p(ar[++i],pf+'base');continue;}
+if(ar[i]==STATUS){q(ar[++i],pf+'status');continue;}
+if(Math.abs(ar[i])==AUTOSTATUS){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
+if(Math.abs(ar[i])==AUTOSTATUSCAP){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
+if(ar[i]==CLOSETEXT){q(ar[++i],pf+'close');continue;}
+if(ar[i]==SNAPX){p(ar[++i],pf+'snapx');continue;}
+if(ar[i]==SNAPY){p(ar[++i],pf+'snapy');continue;}
+if(ar[i]==FIXX){p(ar[++i],pf+'fixx');continue;}
+if(ar[i]==FIXY){p(ar[++i],pf+'fixy');continue;}
+if(ar[i]==RELX){p(ar[++i],pf+'relx');continue;}
+if(ar[i]==RELY){p(ar[++i],pf+'rely');continue;}
+if(ar[i]==MIDX){p(ar[++i],pf+'midx');continue;}
+if(ar[i]==MIDY){p(ar[++i],pf+'midy');continue;}
+if(ar[i]==REF){q(ar[++i],pf+'ref');continue;}
+if(ar[i]==REFC){q(ar[++i],pf+'refc');continue;}
+if(ar[i]==REFP){q(ar[++i],pf+'refp');continue;}
+if(ar[i]==REFX){p(ar[++i],pf+'refx');continue;}
+if(ar[i]==REFY){p(ar[++i],pf+'refy');continue;}
+if(ar[i]==FGBACKGROUND){q(ar[++i],pf+'fgbackground');continue;}
+if(ar[i]==BGBACKGROUND){q(ar[++i],pf+'bgbackground');continue;}
+if(ar[i]==CGBACKGROUND){q(ar[++i],pf+'cgbackground');continue;}
+if(ar[i]==PADX){p(ar[++i],pf+'padxl');p(ar[++i],pf+'padxr');continue;}
+if(ar[i]==PADY){p(ar[++i],pf+'padyt');p(ar[++i],pf+'padyb');continue;}
+if(Math.abs(ar[i])==FULLHTML){t(ar[i],pf+'fullhtml');continue;}
+if(ar[i]==BELOW||ar[i]==ABOVE||ar[i]==VCENTER){p(ar[i],pf+'vpos');continue;}
+if(ar[i]==CAPICON){q(ar[++i],pf+'capicon');continue;}
+if(ar[i]==TEXTFONT){q(ar[++i],pf+'textfont');continue;}
+if(ar[i]==CAPTIONFONT){q(ar[++i],pf+'captionfont');continue;}
+if(ar[i]==CLOSEFONT){q(ar[++i],pf+'closefont');continue;}
+if(ar[i]==TEXTSIZE){q(ar[++i],pf+'textsize');continue;}
+if(ar[i]==CAPTIONSIZE){q(ar[++i],pf+'captionsize');continue;}
+if(ar[i]==CLOSESIZE){q(ar[++i],pf+'closesize');continue;}
+if(ar[i]==TIMEOUT){p(ar[++i],pf+'timeout');continue;}
+if(ar[i]==DELAY){p(ar[++i],pf+'delay');continue;}
+if(Math.abs(ar[i])==HAUTO){t(ar[i],pf+'hauto');continue;}
+if(Math.abs(ar[i])==VAUTO){t(ar[i],pf+'vauto');continue;}
+if(Math.abs(ar[i])==NOJUSTX){t(ar[i],pf+'nojustx');continue;}
+if(Math.abs(ar[i])==NOJUSTY){t(ar[i],pf+'nojusty');continue;}
+if(Math.abs(ar[i])==CLOSECLICK){t(ar[i],pf+'closeclick');continue;}
+if(ar[i]==CLOSETITLE){q(ar[++i],pf+'closetitle');continue;}
+if(ar[i]==FGCLASS){q(ar[++i],pf+'fgclass');continue;}
+if(ar[i]==BGCLASS){q(ar[++i],pf+'bgclass');continue;}
+if(ar[i]==CGCLASS){q(ar[++i],pf+'cgclass');continue;}
+if(ar[i]==TEXTPADDING){p(ar[++i],pf+'textpadding');continue;}
+if(ar[i]==TEXTFONTCLASS){q(ar[++i],pf+'textfontclass');continue;}
+if(ar[i]==CAPTIONPADDING){p(ar[++i],pf+'captionpadding');continue;}
+if(ar[i]==CAPTIONFONTCLASS){q(ar[++i],pf+'captionfontclass');continue;}
+if(ar[i]==CLOSEFONTCLASS){q(ar[++i],pf+'closefontclass');continue;}
+if(Math.abs(ar[i])==CAPBELOW){t(ar[i],pf+'capbelow');continue;}
+if(ar[i]==LABEL){q(ar[++i],pf+'label');continue;}
+if(Math.abs(ar[i])==DECODE){t(ar[i],pf+'decode');continue;}
+if(ar[i]==DONOTHING){continue;}
+i=OLparseCmdLine(pf,i,ar);}}
+if((OLfunctionPI)&&OLudf&&o3_function)o3_text=o3_function();
+if(pf=='o3_')OLfontSize();
+}
+function OLpar(a,v){eval(v+'='+a);}
+function OLparQuo(a,v){eval(v+"='"+OLescSglQt(a)+"'");}
+function OLescSglQt(s){return s.toString().replace(/\\/g,"\\\\").replace(/'/g,"\\'");}
+function OLtoggle(a,v){eval(v+'=('+v+'==0&&'+a+'>=0)?1:0');}
+function OLhasDims(s){return /[%\-a-z]+$/.test(s);}
+function OLfontSize(){
+var i;if(OLhasDims(o3_textsize)){if(OLns4)o3_textsize="2";}else
+if(!OLns4){i=parseInt(o3_textsize);o3_textsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else
+if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else
+if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLprintPI)OLprintDims();
+}
+function OLdecode(){
+var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)&&typeof decodeURIComponent?
+decodeURIComponent:u;if(typeof(window.TypeError)=='function'){if(re.test(t)){eval(new Array('try{','o3_text=d(t);',
+'}catch(e){','o3_text=u(t);','}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){',
+'o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}
+}
+
+/*
+ LAYER FUNCTIONS
+*/
+// Writes to layer
+function OLlayerWrite(t){
+t+="\n";if(OLns4){over.document.write(t);over.document.close();}else if(typeof over.innerHTML!='undefined'){
+if(OLieM)over.innerHTML='';over.innerHTML=t;}else{var range=o3_frame.document.createRange();range.setStartAfter(over);
+var domfrag=range.createContextualFragment(t);while(over.hasChildNodes()){over.removeChild(over.lastChild);}
+over.appendChild(domfrag);}if(OLovertwoPI&&over==over2)OLover2HTML=t;else OLoverHTML=t;
+if(OLprintPI)over.print=o3_print?t:null;
+}
+
+// Makes object visible
+function OLshowObject(o){
+OLshowid=0;o=(OLns4)?o:o.style;if(((OLfilterPI)&&!OLchkFilter(o))||!OLfilterPI)o.visibility="visible";
+if(OLshadowPI)OLshowShadow();if(OLiframePI)OLshowIfs();if(OLhidePI)OLhideUtil(1,1,0);
+}
+
+// Hides object
+function OLhideObject(o){
+if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;}if(OLtimerid>0)clearTimeout(OLtimerid);
+if(OLdelayid>0)clearTimeout(OLdelayid);OLtimerid=0;OLdelayid=0;self.status="";o3_label=ol_label;
+if(o3_frame!=self)o=OLgetRefById();if(o){if(o.onmouseover)o.onmouseover=null;if(OLscrollPI&&o==over)OLclearScroll();
+if(OLdraggablePI)OLclearDrag();if(OLfilterPI)OLcleanupFilter(o);if(OLshadowPI)OLhideShadow();var os=(OLns4)?o:o.style;
+if(((OLfilterPI)&&!OLchkFadeOut(os))||!OLfilterPI){os.visibility="hidden";if(!OLie55||!OLfilterPI||!o3_filter||
+o3_fadeout<0)o.innerHTML='';}if(OLhidePI&&o==over)OLhideUtil(0,0,1);if(OLiframePI)OLhideIfs(o);}
+}
+
+// Moves layer
+function OLrepositionTo(o,xL,yL){
+o=(OLns4)?o:o.style;o.left=(OLns4?xL:xL+'px');o.top=(OLns4?yL:yL+'px');
+}
+
+// Handle NOCLOSE-MOUSEOFF
+function OLoptMOUSEOFF(c){
+if(!c)o3_close="";
+over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}
+}
+function OLcursorOff(){
+var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,left=parseInt(o.left),top=parseInt(o.top),
+right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
+if(OLx<left||OLx>right||OLy<top||OLy>bottom)return true;return false;
+}
+
+/*
+ REGISTRATION
+*/
+function OLsetRunTimeVar(){
+if(OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
+}
+function OLparseCmdLine(pf,i,ar){
+if(OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){var j=OLcmdLine[k](pf,i,ar);if(j>-1){i=j;break;}}}return i;
+}
+function OLregCmds(c){
+if(typeof c!='string')return;var pM=c.split(',');pMtr=pMtr.concat(pM);
+for(var i=0;i<pM.length;i++)eval(pM[i].toUpperCase()+'='+pmCnt++);
+}
+function OLregRunTimeFunc(f){
+if(typeof f=='object')OLrunTime=OLrunTime.concat(f);else OLrunTime[OLrunTime.length++]=f;
+}
+function OLregCmdLineFunc(f){
+if(typeof f=='object')OLcmdLine=OLcmdLine.concat(f);else OLcmdLine[OLcmdLine.length++]=f;
+}
+
+OLloaded=1;
diff --git a/fs_selfservice/FS-SelfService/cgi/overlibmws_crossframe.js b/fs_selfservice/FS-SelfService/cgi/overlibmws_crossframe.js
new file mode 100644
index 0000000..dd64223
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/overlibmws_crossframe.js
@@ -0,0 +1,53 @@
+/*
+ overlibmws_crossframe.js plug-in module - Copyright Foteos Macrides 2003-2008. All rights reserved.
+ For support of FRAME.
+ Initial: August 3, 2003 - Last Revised: January 16, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('frame');
+
+function OLparseCrossframe(pf,i,ar){
+var k=i,v;
+if(k<ar.length){
+if(ar[k]==FRAME){v=ar[++k];if(pf=='ol_')ol_frame=v;else OLoptFRAME(v);return k;}}
+return -1;
+}
+
+function OLgetFrameRef(thisFrame,ofrm){
+var i,v,retVal='';for(i=0;i<thisFrame.length;i++){if((((thisFrame[i].length>0)))&&(((OLns4))||
+((OLie4)&&(v=thisFrame[i].document.all.tags('iframe'))!=null&&v.length==0)||
+((OLns6)&&(v=thisFrame[i].document.getElementsByTagName('iframe'))!=null&&v.length==0))){
+retVal=OLgetFrameRef(thisFrame[i],ofrm);if(retVal=='')continue;}
+else if(thisFrame[i]!=ofrm)continue;retVal='['+i+']'+retVal;break;}
+return retVal;
+}
+
+function OLoptFRAME(frm){
+o3_frame=OLmkLyr('overDiv',frm)?frm:self;if(o3_frame!=self){var l,tFrm=OLgetFrameRef(top.frames,o3_frame),
+sFrm=OLgetFrameRef(top.frames,ol_frame);if(sFrm.length==tFrm.length) {l=tFrm.lastIndexOf('[');if(l){
+while(sFrm.substring(0,l)!=tFrm.substring(0,l))l=tFrm.lastIndexOf('[',l-1);tFrm=tFrm.substr(l);sFrm=sFrm.substr(l);}}
+var i,k,cnt=0,p='',str=tFrm;while((k=str.lastIndexOf('['))!= -1){cnt++;str=str.substring(0,k);}
+for(i=0;i<cnt;i++)p=p+'parent.';OLfnRef=p+'frames'+sFrm+'.';var n=window.name,o;
+if((n&&parent!=self&&o3_frame==parent)&&(o=OLgetRef(n,parent.document))){if(OLie4&&!OLop7){
+OLx=event.clientX+OLfd().scrollLeft;OLy=event.clientY+OLfd().scrollTop;}
+OLifX=OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd().scrollLeft:self.pageXOffset);
+OLifY=OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd().scrollTop:self.pageYOffset);}}
+}
+
+function OLchkIfRef(){
+var n=(parent!=self&&o3_frame==parent)?window.name:'',o=n?OLgetRef(n):null;
+if(o){var oR=OLgetRef(o3_ref,document);if(oR){OLrefXY=OLgetRefXY(o3_ref,document);
+OLrefXY[0]+=(OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd(self).scrollLeft:self.pageXOffset));
+OLrefXY[1]+=(OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd(self).scrollTop:self.pageYOffset));}}
+}
+
+OLregCmdLineFunc(OLparseCrossframe);
+
+OLcrossframePI=1;
+OLloaded=1;
diff --git a/fs_selfservice/FS-SelfService/cgi/overlibmws_draggable.js b/fs_selfservice/FS-SelfService/cgi/overlibmws_draggable.js
new file mode 100644
index 0000000..1bf0ecf
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/overlibmws_draggable.js
@@ -0,0 +1,85 @@
+/*
+ overlibmws_draggable.js plug-in module - Copyright Foteos Macrides 2002-2008. All rights reserved.
+ For support of the DRAGGABLE feature.
+ Initial: August 24, 2002 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLdraggableCmds='draggable,dragcap,dragid';
+OLregCmds(OLdraggableCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('draggable'))var ol_draggable=0;
+if(OLud('dragcap'))var ol_dragcap=0;
+if(OLud('dragid'))var ol_dragid='';
+// END CONFIGURATION
+
+var o3_draggable=0,o3_dragcap=0,o3_dragid='',o3_dragging=0,OLdrg=null,OLmMv,
+OLcX,OLcY,OLcbX,OLcbY;function OLloadDraggable(){OLload(OLdraggableCmds);}
+function OLparseDraggable(pf,i,ar){var t=OLtoggle,k=i;if(k<ar.length){
+if(Math.abs(ar[k])==DRAGGABLE){t(ar[k],pf+'draggable');return k;}
+if(Math.abs(ar[k])==DRAGCAP){t(ar[k],pf+'dragcap');return k;}
+if(ar[k]==DRAGID){OLparQuo(ar[++k],pf+'dragid');return k;}}return -1;
+}
+
+function OLcheckDrag(){
+if(o3_draggable){if(o3_sticky&&(o3_frame==self))OLinitDrag();else o3_draggable=0;}
+}
+function OLinitDrag(){
+OLmMv=OLdw.onmousemove;o3_dragging=0;
+if(OLns4){document.captureEvents(Event.MOUSEDOWN|Event.CLICK);
+document.onmousedown=OLgrabEl;document.onclick=function(e){return routeEvent(e);}}
+else{var dvido=(o3_dragid)?OLgetRef(o3_dragid):null,capid=(OLovertwoPI&&over==over2?
+'overCap2':'overCap');if(dvido)dvido.onscroll=function(){OLdw.onmousemove=OLmMv;
+OLinitDrag();};OLdrg=(o3_cap&&o3_dragcap)?OLgetRef(capid):over;
+if(!OLdrg||!OLdrg.style)OLdrg=over;OLdrg.onmousedown=OLgrabEl;OLsetDrgCur(1);}
+}
+function OLsetDrgCur(d){if(!OLns4&&OLdrg)OLdrg.style.cursor=(d?'move':'auto');}
+
+function OLgrabEl(e){
+var e=(e||event);
+var cKy=(OLns4?e.modifiers&Event.ALT_MASK:(e.altKey||(OLop7&&e.ctrlKey)));o3_dragging=1;
+if(cKy){OLsetDrgCur(0);document.onmouseup=function(){OLsetDrgCur(1);o3_dragging=0;}
+return(OLns4?routeEvent(e):true);}
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(OLie4)over.onselectstart=function(){return false;}
+if(OLns4){OLcX=OLx;OLcY=OLy;document.captureEvents(Event.MOUSEUP)}else{
+OLcX=OLx-(OLns4?over.left:parseInt(over.style.left));
+OLcY=OLy-(OLns4?over.top:parseInt(over.style.top));
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLcbX=OLx-(parseInt(bkdrop.style.left));
+OLcbY=OLy-(parseInt(bkdrop.style.top));}}OLdw.onmousemove=OLmoveEl;
+document.onmouseup=function(){
+if(OLie4)over.onselectstart=null;o3_dragging=0;OLdw.onmousemove=OLmMv;}
+return(OLns4?routeEvent(e):false);
+}
+
+function OLmoveEl(e){
+var e=(e||event);
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(o3_dragging){if(OLns4){over.moveBy(OLx-OLcX,OLy-OLcY);
+if(OLshadowPI&&bkdrop&&o3_shadow)bkdrop.moveBy(OLx-OLcX,OLy-OLcY);}
+else{OLrepositionTo(over,OLx-OLcX,OLy-OLcY);
+if((OLiframePI)&&OLie55&&OLifsP1)OLrepositionTo(OLifsP1,OLx-OLcX,OLy-OLcY);
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLrepositionTo(bkdrop,OLx-OLcbX,OLy-OLcbY);
+if((OLiframePI)&&OLie55&&OLifsSh)OLrepositionTo(OLifsSh,OLx-OLcbX,OLy-OLcbY);}}
+if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}if(OLns4){OLcX=OLx;OLcY=OLy;}
+return false;
+}
+
+function OLclearDrag(){
+if(OLns4){document.releaseEvents(Event.MOUSEDOWN|Event.MOUSEUP|Event.CLICK);
+document.onmousedown=document.onclick=null;}else{
+if(OLdrg)OLdrg.onmousedown=null;over.onmousedown=null;OLsetDrgCur(0);}
+document.onmouseup=null;o3_dragging=0;
+}
+
+OLregRunTimeFunc(OLloadDraggable);
+OLregCmdLineFunc(OLparseDraggable);
+
+OLdraggablePI=1;
+OLloaded=1;
diff --git a/fs_selfservice/FS-SelfService/cgi/overlibmws_iframe.js b/fs_selfservice/FS-SelfService/cgi/overlibmws_iframe.js
new file mode 100644
index 0000000..4c937d3
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/overlibmws_iframe.js
@@ -0,0 +1,93 @@
+/*
+ overlibmws_iframe.js plug-in module - Copyright Foteos Macrides 2003-2008. All rights reserved.
+ Masks system controls to prevent obscuring of popops for IE v5.5 or higher.
+ Initial: October 19, 2003 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+
+var OLifsP1=null,OLifsSh=null,OLifsP2=null;
+
+// IFRAME SHIM SUPPORT FUNCTIONS
+function OLinitIfs(){
+if(!OLie55)return;
+if((OLovertwoPI)&&over2&&over==over2){
+var o=o3_frame.document.all['overIframeOvertwo'];
+if(!o||OLifsP2!=o){OLifsP2=null;OLgetIfsP2Ref();}return;}
+o=o3_frame.document.all['overIframe'];
+if(!o||OLifsP1!=o){OLifsP1=null;OLgetIfsRef();}
+if((OLshadowPI)&&o3_shadow){o=o3_frame.document.all['overIframeShadow'];
+if(!o||OLifsSh!=o){OLifsSh=null;OLgetIfsShRef();}}
+}
+
+function OLsetIfsRef(o,i,z){
+o.id=i;o.src='javascript:false;';o.scrolling='no';var os=o.style;os.position='absolute';
+os.top='0px';os.left='0px';os.width='1px';os.height='1px';os.visibility='hidden';
+os.zIndex=over.style.zIndex-z;os.filter='Alpha(style=0,opacity=0)';
+}
+
+function OLgetIfsRef(){
+if(OLifsP1||!OLie55)return;
+OLifsP1=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP1,'overIframe',2);
+o3_frame.document.body.appendChild(OLifsP1);
+}
+
+function OLgetIfsShRef(){
+if(OLifsSh||!OLie55)return;
+OLifsSh=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsSh,'overIframeShadow',3);
+o3_frame.document.body.appendChild(OLifsSh);
+}
+
+function OLgetIfsP2Ref(){
+if(OLifsP2||!OLie55)return;
+OLifsP2=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP2,'overIframeOvertwo',1);
+o3_frame.document.body.appendChild(OLifsP2);
+}
+
+function OLsetDispIfs(o,w,h){
+var os=o.style;
+os.width=w+'px';os.height=h+'px';os.clip='rect(0px '+w+'px '+h+'px 0px)';
+o.filters.alpha.enabled=true;
+}
+
+function OLdispIfs(){
+if(!OLie55)return;
+var wd=over.offsetWidth,ht=over.offsetHeight;
+if(OLfilterPI&&o3_filter&&o3_filtershadow){wd+=5;ht+=5;}
+if((OLovertwoPI)&&over2&&over==over2){
+if(!OLifsP2)return;
+OLsetDispIfs(OLifsP2,wd,ht);return;}
+if(!OLifsP1)return;
+OLsetDispIfs(OLifsP1,wd,ht);
+if((!OLshadowPI)||!o3_shadow||!OLifsSh)return;
+OLsetDispIfs(OLifsSh,wd,ht);
+}
+
+function OLshowIfs(){
+if(OLifsP1){OLifsP1.style.visibility="visible";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="visible";}
+}
+
+function OLhideIfs(o){
+if(!OLie55||o!=over)return;
+if(OLifsP1)OLifsP1.style.visibility="hidden";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="hidden";
+}
+
+function OLrepositionIfs(X,Y){
+if(OLie55){if((OLovertwoPI)&&over2&&over==over2){
+if(OLifsP2)OLrepositionTo(OLifsP2,X,Y);}
+else{if(OLifsP1){OLrepositionTo(OLifsP1,X,Y);if((OLshadowPI)&&o3_shadow&&OLifsSh)
+OLrepositionTo(OLifsSh,X+o3_shadowx,Y+o3_shadowy);}}}
+}
+
+OLiframePI=1;
+OLloaded=1;
diff --git a/fs_selfservice/FS-SelfService/cgi/passwd.cgi b/fs_selfservice/FS-SelfService/cgi/passwd.cgi
index 87e5e68..1e6e2e5 100755
--- a/fs_selfservice/FS-SelfService/cgi/passwd.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/passwd.cgi
@@ -2,7 +2,6 @@
#!/usr/bin/perl -Tw
use strict;
-use Getopt::Std;
use FS::SelfService qw(passwd);
use CGI;
use CGI::Carp qw(fatalsToBrowser);
diff --git a/fs_selfservice/FS-SelfService/cgi/payment_results.html b/fs_selfservice/FS-SelfService/cgi/payment_results.html
index 62419d1..987b97e 100644
--- a/fs_selfservice/FS-SelfService/cgi/payment_results.html
+++ b/fs_selfservice/FS-SelfService/cgi/payment_results.html
@@ -1,13 +1,11 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Payment results</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error processing your payment: $error</FONT>!;
} else {
$OUT .= 'Your payment was processed successfully. Thank you.';
} %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_change_bill.html b/fs_selfservice/FS-SelfService/cgi/process_change_bill.html
index 93e05cf..a440284 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_change_bill.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_change_bill.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Information updated successfully.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_change_password.html b/fs_selfservice/FS-SelfService/cgi/process_change_password.html
index bfd2312..ffe0cab 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_change_password.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_change_password.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Password changed for <%= $value %> <%= $label %>.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_change_pay.html b/fs_selfservice/FS-SelfService/cgi/process_change_pay.html
index 93e05cf..a440284 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_change_pay.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_change_pay.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Information updated successfully.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_change_pkg.html b/fs_selfservice/FS-SelfService/cgi/process_change_pkg.html
index 7c0f0a6..c7c69f0 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_change_pkg.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_change_pkg.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Package change successful.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_change_ship.html b/fs_selfservice/FS-SelfService/cgi/process_change_ship.html
index 93e05cf..a440284 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_change_ship.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_change_ship.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Information updated successfully.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_order_pkg.html b/fs_selfservice/FS-SelfService/cgi/process_order_pkg.html
index 3e4471d..b868937 100755
--- a/fs_selfservice/FS-SelfService/cgi/process_order_pkg.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_order_pkg.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Package order successful.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html b/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html
index ef0516a..9dfc328 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4><%= $svc %> recharged successfully.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html b/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html
index 813521f..39920cb 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4><%= $svc %> setup successfully.</FONT>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/process_svc_external.html b/fs_selfservice/FS-SelfService/cgi/process_svc_external.html
index 1d2937b..103eb9e 100644
--- a/fs_selfservice/FS-SelfService/cgi/process_svc_external.html
+++ b/fs_selfservice/FS-SelfService/cgi/process_svc_external.html
@@ -1,12 +1,8 @@
-<HTML><HEAD><TITLE><%= $error ? 'MyAccount' : sprintf("Your serial number is %010d-$title", $id) %></TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4><%= $svc %> setup successfully.</FONT>
<BR><BR>Your serial number is <%= sprintf("%010d-$title", $id) %>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/provision.html b/fs_selfservice/FS-SelfService/cgi/provision.html
index 5ae7b42..f5b2c2b 100644
--- a/fs_selfservice/FS-SelfService/cgi/provision.html
+++ b/fs_selfservice/FS-SelfService/cgi/provision.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<%= include('provision_list') %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html b/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html
index 550493b..bffd22f 100644
--- a/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html
+++ b/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<%= include('svc_acct') %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/recharge_prepay.html b/fs_selfservice/FS-SelfService/cgi/recharge_prepay.html
index 3de4c87..6f0aa1f 100644
--- a/fs_selfservice/FS-SelfService/cgi/recharge_prepay.html
+++ b/fs_selfservice/FS-SelfService/cgi/recharge_prepay.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Recharge with prepaid card</FONT><BR><BR>
<FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
@@ -29,5 +27,5 @@
<INPUT TYPE="hidden" NAME="paybatch" VALUE="<%=$paybatch%>">
<INPUT TYPE="submit" NAME="process" VALUE="Recharge"> <!-- onClick="this.disabled=true"> -->
</FORM>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/recharge_results.html b/fs_selfservice/FS-SelfService/cgi/recharge_results.html
index 6d928e3..af15365 100644
--- a/fs_selfservice/FS-SelfService/cgi/recharge_results.html
+++ b/fs_selfservice/FS-SelfService/cgi/recharge_results.html
@@ -1,8 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
+
<FONT SIZE=4>Recharge results</FONT><BR><BR>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error processing your prepaid card: $error</FONT>!;
@@ -17,5 +15,5 @@
$OUT .= 'Thank you.';
} %>
-</TD></TR></TABLE>
+
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
index 865b5ce..ec8d6d8 100644
--- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
@@ -9,15 +9,16 @@ use Text::Template;
use HTML::Entities;
use Date::Format;
use Number::Format 1.50;
-use FS::SelfService qw( login_info login customer_info edit_info invoice
- payment_info process_payment
- process_prepay
- list_pkgs order_pkg signup_info order_recharge
- part_svc_info provision_acct provision_external
- unprovision_svc change_pkg domainselector
- list_svcs list_svc_usage list_support_usage
- myaccount_passwd
- );
+use FS::SelfService qw(
+ access_info login_info login customer_info edit_info invoice
+ payment_info process_payment realtime_collect process_prepay
+ list_pkgs order_pkg signup_info order_recharge
+ part_svc_info provision_acct provision_external
+ unprovision_svc change_pkg domainselector
+ list_svcs list_svc_usage list_cdr_usage list_support_usage
+ myaccount_passwd
+ mason_comp
+);
$template_dir = '.';
@@ -72,7 +73,7 @@ $session_id = $cgi->param('session');
#order|pw_list XXX ???
$cgi->param('action') =~
- /^(myaccount|view_invoice|make_payment|make_ach_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|change_pay|process_change_bill|process_change_ship|process_change_pay|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|view_support_details|change_password|process_change_password)$/
+ /^(myaccount|view_invoice|make_payment|make_ach_payment|make_thirdparty_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|change_pay|process_change_bill|process_change_ship|process_change_pay|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|view_cdr_details|view_support_details|change_password|process_change_password)$/
or die "unknown action ". $cgi->param('action');
my $action = $1;
@@ -98,6 +99,7 @@ warn "processing template $action\n"
do_template($action, {
'session_id' => $session_id,
'action' => $action, #so the menu knows what tab we're on...
+ #%{ payment_info( 'session_id' => $session_id ) }, # cust_paybys for the menu
%{$result}
});
@@ -163,13 +165,18 @@ sub process_change_ship {
sub process_change_pay {
my $postal = $cgi->param( 'postal_invoicing' );
+ my $payby = $cgi->param( 'payby' );
my @list =
qw( payby payinfo payinfo1 payinfo2 month year payname
address1 address2 city county state zip country auto paytype
paystate ss stateid stateid_state invoicing_list
);
push @list, 'postal_invoicing' if $postal;
- unless ( $postal || $cgi->param( 'invoicing_list' ) ) {
+ unless ( $payby ne 'BILL'
+ || $postal
+ || $cgi->param( 'invoicing_list' )
+ )
+ {
$action = 'change_pay';
return {
%{&change_pay()},
@@ -198,11 +205,24 @@ sub customer_order_pkg {
my $customer_info = customer_info( 'session_id' => $session_id );
return $customer_info if ( $customer_info->{'error'} );
+ my $pkgselect = mason_comp(
+ 'session_id' => $session_id,
+ 'comp' => '/edit/cust_main/first_pkg/select-part_pkg.html',
+ 'args' => [ 'password_verify' => 1,
+ 'onchange' => 'enable_order_pkg()',
+ 'relurls' => 1,
+ 'empty_label' => 'Select package',
+ ],
+ );
+
+ $pkgselect = $pkgselect->{'error'} || $pkgselect->{'output'};
+
return {
( map { $_ => $init_data->{$_} }
qw( part_pkg security_phrase svc_acct_pop ),
),
%$customer_info,
+ 'pkg_selector' => $pkgselect,
};
}
@@ -228,23 +248,46 @@ sub process_order_pkg {
my $results = '';
- unless ( length($cgi->param('_password')) ) {
- my $init_data = signup_info( 'customer_session_id' => $session_id );
- $results = { 'error' => $init_data->{msgcat}{empty_password} };
- $results = { 'error' => $init_data->{error} } if($init_data->{error});
+ my @params = (qw( custnum pkgpart ));
+ my $svcdb = '';
+ if ( $cgi->param('pkgpart_svcpart') =~ /^(\d+)_(\d+)$/ ) {
+ $cgi->param('pkgpart', $1);
+ $cgi->param('svcpart', $2);
+ push @params, 'svcpart';
+ $svcdb = $cgi->param('svcdb');
+ push @params, 'domsvc' if $svcdb eq 'svc_acct';
+ } else {
+ $svcdb = 'svc_acct';
}
- if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
- my $init_data = signup_info( 'customer_session_id' => $session_id );
- $results = { 'error' => $init_data->{msgcat}{passwords_dont_match} };
- $results = { 'error' => $init_data->{error} } if($init_data->{error});
- $cgi->param('_password', '');
- $cgi->param('_password2', '');
+
+ if ( $svcdb eq 'svc_acct' ) {
+
+ push @params, qw( username _password _password2 sec_phrase popnum );
+
+ unless ( length($cgi->param('_password')) ) {
+ my $init_data = signup_info( 'customer_session_id' => $session_id );
+ $results = { 'error' => $init_data->{msgcat}{empty_password} };
+ $results = { 'error' => $init_data->{error} } if($init_data->{error});
+ }
+ if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
+ my $init_data = signup_info( 'customer_session_id' => $session_id );
+ $results = { 'error' => $init_data->{msgcat}{passwords_dont_match} };
+ $results = { 'error' => $init_data->{error} } if($init_data->{error});
+ $cgi->param('_password', '');
+ $cgi->param('_password2', '');
+ }
+
+ } elsif ( $svcdb eq 'svc_phone' ) {
+
+ push @params, qw( phonenum sip_password pin phone_name );
+
+ } else {
+ die "$svcdb not handled on process_order_pkg yet";
}
$results ||= order_pkg (
'session_id' => $session_id,
- map { $_ => $cgi->param($_) }
- qw( custnum pkgpart username _password _password2 sec_phrase popnum )
+ map { $_ => $cgi->param($_) } @params
);
@@ -318,7 +361,7 @@ sub make_payment {
sub payment_results {
- use Business::CreditCard;
+ use Business::CreditCard 0.30;
#we should only do basic checking here for DoS attacks and things
#that couldn't be constructed by the web form... let process_payment() do
@@ -329,14 +372,16 @@ sub payment_results {
my $amount = $1;
my $payinfo = $cgi->param('payinfo');
- $payinfo =~ s/\D//g;
- $payinfo =~ /^(\d{13,16})$/
+ $payinfo =~ s/[^\dx]//g;
+ $payinfo =~ /^([\dx]{13,16})$/
#or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
or die "illegal card"; #!!!
$payinfo = $1;
- validate($payinfo)
- #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
- or die "invalid card"; #!!!
+ unless ( $payinfo =~ /x/ ) {
+ validate($payinfo)
+ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ or die "invalid card"; #!!!
+ }
if ( $cgi->param('card_type') ) {
cardtype($payinfo) eq $cgi->param('card_type')
@@ -364,12 +409,15 @@ sub payment_results {
$cgi->param('city') =~ /^(.{0,80})$/ or die "illegal city";
my $city = $1;
- $cgi->param('state') =~ /^(.{2})$/ or die "illegal state";
+ $cgi->param('state') =~ /^(.{0,80})$/ or die "illegal state";
my $state = $1;
$cgi->param('zip') =~ /^(.{0,10})$/ or die "illegal zip";
my $zip = $1;
+ $cgi->param('country') =~ /^(.{0,2})$/ or die "illegal country";
+ my $country = $1;
+
my $save = 0;
$save = 1 if $cgi->param('save');
@@ -393,6 +441,7 @@ sub payment_results {
'city' => $city,
'state' => $state,
'zip' => $zip,
+ 'country' => $country,
'save' => $save,
'auto' => $auto,
'paybatch' => $paybatch,
@@ -415,14 +464,16 @@ sub ach_payment_results {
my $amount = $1;
my $payinfo1 = $cgi->param('payinfo1');
- $payinfo1=~ /^(\d+)$/
+ $payinfo1 =~ s/[^\dx]//g;
+ $payinfo1 =~ /^([\dx]+)$/
or die "illegal account"; #!!!
- $payinfo1= $1;
+ $payinfo1 = $1;
my $payinfo2 = $cgi->param('payinfo2');
- $payinfo2=~ /^(\d+)$/
+ $payinfo2 =~ s/[^\dx]//g;
+ $payinfo2 =~ /^([\dx]+)$/
or die "illegal ABA/routing code"; #!!!
- $payinfo2= $1;
+ $payinfo2 = $1;
$cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname";
my $payname = $1;
@@ -472,6 +523,12 @@ sub ach_payment_results {
}
+sub make_thirdparty_payment {
+ $cgi->param('payby_method') =~ /^(CC|ECHECK)$/
+ or die "illegal payby method";
+ realtime_collect( 'session_id' => $session_id, 'method' => $1 );
+}
+
sub recharge_prepay {
customer_info( 'session_id' => $session_id );
}
@@ -557,7 +614,7 @@ sub delete_svc {
sub view_usage {
list_svcs(
'session_id' => $session_id,
- 'svcdb' => 'svc_acct',
+ 'svcdb' => [ 'svc_acct', 'svc_phone' ],
'ncancelled' => 1,
);
}
@@ -571,6 +628,15 @@ sub view_usage_details {
);
}
+sub view_cdr_details {
+ list_cdr_usage(
+ 'session_id' => $session_id,
+ 'svcnum' => $cgi->param('svcnum'),
+ 'beginning' => $cgi->param('beginning') || '',
+ 'ending' => $cgi->param('ending') || '',
+ );
+}
+
sub view_support_details {
list_support_usage(
'session_id' => $session_id,
@@ -625,6 +691,11 @@ sub do_template {
$fill_in->{'selfurl'} = $cgi->self_url;
$fill_in->{'cgi'} = \$cgi;
+ my $access_info = $session_id
+ ? access_info( 'session_id' => $session_id )
+ : {};
+ $fill_in->{$_} = $access_info->{$_} foreach keys %$access_info;
+
my $source = "$template_dir/$name.html";
#warn "creating template for $source\n";
my $template = new Text::Template( TYPE => 'FILE',
@@ -647,7 +718,7 @@ package FS::SelfService::_selfservicecgi;
#use FS::SelfService qw(regionselector expselect popselector);
use HTML::Entities;
-use FS::SelfService qw(regionselector popselector domainselector);
+use FS::SelfService qw(regionselector popselector domainselector location_form);
#false laziness w/agent.cgi
sub include {
diff --git a/fs_selfservice/FS-SelfService/cgi/signup.cgi b/fs_selfservice/FS-SelfService/cgi/signup.cgi
index 47857f0..fb4a7c5 100755
--- a/fs_selfservice/FS-SelfService/cgi/signup.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/signup.cgi
@@ -8,11 +8,12 @@ use vars qw( @payby $cgi $init_data
$ieak_file $ieak_template
$signup_html $signup_template
$success_html $success_template
+ $collect_html $collect_template
$decline_html $decline_template
);
use subs qw( print_form print_okay print_decline
- success_default decline_default
+ success_default collect_default decline_default
);
use CGI;
#use CGI::Carp qw(fatalsToBrowser);
@@ -35,6 +36,9 @@ $signup_html = -e 'signup.html'
$success_html = -e 'success.html'
? 'success.html'
: '/usr/local/freeside/success.html';
+$collect_html = -e 'collect.html'
+ ? 'collect.html'
+ : '/usr/local/freeside/collect.html';
$decline_html = -e 'decline.html'
? 'decline.html'
: '/usr/local/freeside/decline.html';
@@ -97,6 +101,24 @@ if ( -e $success_html ) {
or die $Text::Template::ERROR;
}
+if ( -e $collect_html ) {
+ my $collect_txt = Text::Template::_load_text($collect_html)
+ or die $Text::Template::ERROR;
+ $collect_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+ $collect_txt = $1;
+ $collect_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => $collect_txt,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+} else {
+ $collect_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => &collect_default,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+}
+
if ( -e $decline_html ) {
my $decline_txt = Text::Template::_load_text($decline_html)
or die $Text::Template::ERROR;
@@ -122,9 +144,10 @@ $init_data = signup_info( 'agentnum' => $agentnum,
'reg_code' => uc(scalar($cgi->param('reg_code'))),
);
-if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' )
- || ( defined($cgi->param('action')) && $cgi->param('action') eq 'process_signup' )
- ) {
+my $magic = $cgi->param('magic') || '';
+my $action = $cgi->param('action') || '';
+
+if ( $magic eq 'process' || $action eq 'process_signup' ) {
$error = '';
@@ -206,6 +229,7 @@ if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' )
invoicing_list referral_custnum promo_code reg_code
pkgpart refnum agentnum
username sec_phrase _password popnum
+ mac_addr
countrycode phonenum sip_password pin
),
grep { /^snarf_/ } $cgi->param
@@ -218,6 +242,10 @@ if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' )
if ( $error eq '_decline' ) {
print_decline();
+ } elsif ( $error eq '_collect' ) {
+ map { $cgi->param($_, $rv->{$_}) }
+ qw( popup_url reference collectitems amount );
+ print_collect();
} elsif ( $error ) {
#fudge the snarf info
no strict 'refs';
@@ -230,6 +258,16 @@ if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' )
);
}
+} elsif ( $magic eq 'success' || $action eq 'success' ) {
+
+ $cgi->param('username', 'username'); #hmmm temp kludge
+ $cgi->param('_password', 'password');
+ print_okay( map { /^([\w ]+)$/ ? ( $_ => $1 ) : () } $cgi->param ); #hmmm
+
+} elsif ( $magic eq 'decline' || $action eq 'decline' ) {
+
+ print_decline();
+
} else {
$error = '';
print_form;
@@ -258,6 +296,27 @@ sub print_form {
);
}
+sub print_collect {
+
+ $error = "Error: $error" if $error;
+
+ my $r = {
+ $cgi->Vars,
+ %{$init_data},
+ 'error' => $error,
+ };
+
+ $r->{pkgpart} ||= $r->{default_pkgpart};
+
+ $r->{referral_custnum} = $r->{'ref'};
+ $r->{self_url} = $cgi->self_url;
+
+ print $cgi->header( '-expires' => 'now' ),
+ $collect_template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi',
+ HASH => $r
+ );
+}
+
sub print_decline {
print $cgi->header( '-expires' => 'now' ),
$decline_template->fill_in();
@@ -369,6 +428,37 @@ Package: <%= $pkg %><BR>
END
}
+sub collect_default { #html to use if there is a collect phase
+ <<'END';
+<HTML><HEAD><TITLE>Pay now</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Pay now</FONT><BR><BR>
+<SCRIPT TYPE="text/javascript">
+ function popcollect() {
+ overlib( OLiframeContent('<%= $popup_url %>', 336, 550, 'Secure Payment Area', 0, 'auto' ), CAPTION, 'Pay now', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close' );
+ return false;
+ }
+</SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_iframe.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_draggable.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="overlibmws_crossframe.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="iframecontentmws.js"></SCRIPT>
+You are about to contact our payment processor to pay <%= $amount %> for
+<%= $pkg %>.<BR><BR>
+Your transaction reference number is <%= $reference %><BR><BR>
+<FORM NAME="collect_popper" method="post" action="javascript:void(0)" onSubmit="popcollect()">
+<%=
+ my %itemhash = @collectitems;
+ foreach my $input (keys %itemhash) {
+ $OUT .= qq!<INPUT NAME="$input" TYPE="hidden" VALUE="$itemhash{$input}">!;
+ }
+%>
+<INPUT NAME="submit" type="submit" value="Pay now">
+</FORM>
+</BODY></HTML>
+END
+}
+
sub decline_default { #html to use if there is a decline
<<'END';
<HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup.html b/fs_selfservice/FS-SelfService/cgi/signup.html
index 1b97121..3f8e4a3 100755
--- a/fs_selfservice/FS-SelfService/cgi/signup.html
+++ b/fs_selfservice/FS-SelfService/cgi/signup.html
@@ -38,7 +38,7 @@
%>
<%=
- $OUT = join("\n", map { qq|<input type="hidden" name="$_" />| } qw / promo_code reg_code pkgpart username _password _password2 sec_phrase popnum countrycode phonenum sip_password pin / );
+ $OUT = join("\n", map { qq|<input type="hidden" name="$_" />| } qw / promo_code reg_code pkgpart username _password _password2 sec_phrase popnum mac_addr countrycode phonenum sip_password pin / );
%>
Where did you hear about our service? <SELECT NAME="refnum">
@@ -46,7 +46,7 @@ Where did you hear about our service? <SELECT NAME="refnum">
$OUT .= '<OPTION VALUE="">' unless $refnum;
foreach my $part_referral ( @part_referral ) {
$OUT .= '<OPTION VALUE="'. $part_referral->{'refnum'}. '"';
- $OUT .= ' SELECTED' if $part_referral->{'refnum'} eq $refnum;
+ $OUT .= ' SELECTED' if $part_referral->{'refnum'} == $refnum;
$OUT .= '>'. $part_referral->{'referral'};
}
%>
@@ -245,7 +245,7 @@ HTML::Widgets::SelectLayers->new(
form_name => 'dummy',
html_between => '</td></tr></table>',
form_action => 'dummy.cgi',
- layer_callback => sub { my $layer = shift; return $paybychecked{$layer}. '</TABLE>'; },
+ layer_callback => sub { my $layer = shift; return ( shift @hide_payment_fields ? '' : $paybychecked{$layer} ) . '</TABLE>'; },
)->html;
@@ -316,6 +316,18 @@ SECPHRASE
$OUT .= '<INPUT TYPE="hidden" NAME="sec_phrase" VALUE="">';
}
+ if ( $nomadix ) {
+
+ warn $mac_addr;
+ $mac_addr ||= $MA;
+ warn $mac_addr;
+
+ $OUT .= <<NOMADIX;
+ <INPUT TYPE="hidden" NAME="mac_addr" VALUE="$mac_addr">
+NOMADIX
+
+ }
+
}
if ( @svc_acct_pop ) {
@@ -380,6 +392,7 @@ function fixup_form() {
var signup_elements = new Array (
'promo_code', 'reg_code', 'pkgpart',
'username', '_password', '_password2', 'sec_phrase', 'popnum',
+ 'mac_addr',
'countrycode', 'phonenum', 'sip_password', 'pin'
);
diff --git a/fs_selfservice/FS-SelfService/cgi/success.html b/fs_selfservice/FS-SelfService/cgi/success.html
index 92185c3..8105e41 100644
--- a/fs_selfservice/FS-SelfService/cgi/success.html
+++ b/fs_selfservice/FS-SelfService/cgi/success.html
@@ -18,7 +18,7 @@ Signup information for <%= $email_name %>:
if ($signup_service eq 'svc_acct' || !$signup_service ) { #just in case
$OUT .= <<END
Username: $username<BR>
- Password: $password><BR>
+ Password: $password<BR>
Access number: ($ac) / $exch - $local <BR>
END
} elsif ( $signup_service eq 'svc_phone' ) {
diff --git a/fs_selfservice/FS-SelfService/cgi/verify.cgi b/fs_selfservice/FS-SelfService/cgi/verify.cgi
new file mode 100755
index 0000000..d9346b8
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/verify.cgi
@@ -0,0 +1,177 @@
+#!/usr/bin/perl -T
+#!/usr/bin/perl -Tw
+
+use strict;
+use vars qw( $cgi $self_url $error
+ $verify_html $verify_template
+ $success_html $success_template
+ $decline_html $decline_template
+ );
+
+use subs qw( print_verify print_okay print_decline
+ verify_default success_default decline_default
+ );
+use CGI;
+use Text::Template;
+use FS::SelfService qw( capture_payment );
+
+$verify_html = -e 'verify.html'
+ ? 'verify.html'
+ : '/usr/local/freeside/verify.html';
+$success_html = -e 'verify_success.html'
+ ? 'success.html'
+ : '/usr/local/freeside/success.html';
+$decline_html = -e 'verify_decline.html'
+ ? 'decline.html'
+ : '/usr/local/freeside/decline.html';
+
+
+if ( -e $verify_html ) {
+ my $verify_txt = Text::Template::_load_text($verify_html)
+ or die $Text::Template::ERROR;
+ $verify_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+ $verify_txt = $1;
+ $verify_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => $verify_txt,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+} else {
+ $verify_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => &verify_default,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+}
+
+if ( -e $success_html ) {
+ my $success_txt = Text::Template::_load_text($success_html)
+ or die $Text::Template::ERROR;
+ $success_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+ $success_txt = $1;
+ $success_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => $success_txt,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+} else {
+ $success_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => &success_default,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+}
+
+if ( -e $decline_html ) {
+ my $decline_txt = Text::Template::_load_text($decline_html)
+ or die $Text::Template::ERROR;
+ $decline_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+ $decline_txt = $1;
+ $decline_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => $decline_txt,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+} else {
+ $decline_template = new Text::Template ( TYPE => 'STRING',
+ SOURCE => &decline_default,
+ DELIMITERS => [ '<%=', '%>' ],
+ )
+ or die $Text::Template::ERROR;
+}
+
+$cgi = new CGI;
+
+my $rv = capture_payment(
+ data => { 'manual' => 1,
+ map { $_ => scalar($cgi->param($_)) } $cgi->param
+ },
+ url => $cgi->self_url,
+);
+
+$error = $rv->{error};
+
+if ( $error eq '_decline' ) {
+ print_decline();
+} elsif ( $error ) {
+ print_verify();
+} else {
+ print_okay(%$rv);
+}
+
+
+sub print_verify {
+
+ $error = "Error: $error" if $error;
+
+ my $r = { $cgi->Vars, 'error' => $error };
+
+ $r->{self_url} = $cgi->self_url;
+
+ print $cgi->header( '-expires' => 'now' ),
+ $verify_template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi',
+ HASH => $r
+ );
+}
+
+sub print_decline {
+ print $cgi->header( '-expires' => 'now' ),
+ $decline_template->fill_in();
+}
+
+sub print_okay {
+ my %param = @_;
+
+ my @success_url = split '/', $cgi->url(-path);
+ pop @success_url;
+
+ my $success_url = join '/', @success_url;
+ if ($param{session_id}) {
+ my $session_id = lc($param{session_id});
+ $success_url .= "/selfservice.cgi?action=myaccount&session=$session_id";
+ } else {
+ $success_url .= '/signup.cgi?action=success';
+ }
+
+ print $cgi->header( '-expires' => 'now' ),
+ $success_template->fill_in( HASH => { success_url => $success_url } );
+}
+
+sub success_default { #html to use if you don't specify a success file
+ <<'END';
+<HTML><HEAD><TITLE>Signup successful</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Signup successful</FONT><BR><BR>
+Thanks for signing up!
+<BR><BR>
+<SCRIPT TYPE="text/javascript">
+ window.top.location="<%= $success_url %>";
+</SCRIPT>
+</BODY></HTML>
+END
+}
+
+sub verify_default { #html to use for verification response
+ <<'END';
+<HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Processing error</FONT><BR><BR>
+There has been an error processing your account. Please contact customer
+support.
+</BODY></HTML>
+END
+}
+
+sub decline_default { #html to use if there is a decline
+ <<'END';
+<HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Processing error</FONT><BR><BR>
+There has been an error processing your account. Please contact customer
+support.
+</BODY></HTML>
+END
+}
+
+# subs for the templates...
+
+package FS::SelfService::_signupcgi;
+use HTML::Entities;
+
diff --git a/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
new file mode 100644
index 0000000..32bd632
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
@@ -0,0 +1,54 @@
+<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= include('header') %>
+
+<FONT SIZE=4>Call usage for
+<%= Date::Format::time2str('%b&nbsp;%o&nbsp;%Y', $beginning) %> -
+<%= Date::Format::time2str('%b&nbsp;%o&nbsp;%Y', $ending) %>
+</FONT><BR><BR>
+
+<%= if ( $error ) {
+ $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
+} ''; %>
+
+<TABLE WIDTH="100%">
+ <TR>
+ <TD WIDTH="50%">
+<%= if ($previous < $beginning) {
+ $OUT .= qq!<A HREF="${url}view_cdr_details;svcnum=$svcnum;beginning=!;
+ $OUT .= qq!$previous;ending=$beginning">Previous period</A>!;
+ }else{
+ '';
+ } %>
+ </TD>
+ <TD WIDTH="50%" ALIGN="right">
+<%= if ($next > $ending) {
+ $OUT .= qq!<A HREF="${url}view_cdr_details;svcnum=$svcnum;beginning=!;
+ $OUT .= qq!$ending;ending=$next">Next period</A>!;
+ }else{
+ '';
+ }%>
+ </TD>
+ </TR>
+</TABLE>
+<TABLE BGCOLOR="#cccccc">
+ <TR>
+<%= foreach my $header (@header) {
+ $OUT .= qq(<TH ALIGN="right">$header</TH>);
+ }
+%>
+ </TR>
+<%= my $total = 0;
+ my $utotal = 0;
+ my $dtotal = 0;
+ foreach my $usage ( @usage ) {
+ $OUT .= '<TR>';
+ $OUT .= qq(<TD>$_</TD>) foreach @{$usage};
+ $OUT .= '</TR>';
+ }
+%>
+
+</TABLE>
+<BR>
+
+</TD></TR></TABLE>
+<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/view_invoice.html b/fs_selfservice/FS-SelfService/cgi/view_invoice.html
index 8fa5fb7..8a1c1c7 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_invoice.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_invoice.html
@@ -1,10 +1,6 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<%= $invoice_html %>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/view_usage.html b/fs_selfservice/FS-SelfService/cgi/view_usage.html
index b78f997..b492102 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_usage.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_usage.html
@@ -1,24 +1,30 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
-
-<FONT SIZE=4>Service usage</FONT><BR><BR>
+<%= $url = "$selfurl?session=$session_id;action=";
+ @svc_acct = grep { $_->{svcdb} eq 'svc_acct' } @svcs;
+ @svc_phone = grep { $_->{svcdb} eq 'svc_phone' } @svcs;
+ '';
+%>
+<%= include('header') %>
<%= if ( $error ) {
$OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
} ''; %>
-<TABLE BGCOLOR="#cccccc">
- <TR>
- <TH ALIGN="left">Account</TH>
- <TH ALIGN="right">Time remaining</TH>
- <TH ALIGN="right">Upload remaining</TH>
- <TH ALIGN="right">Download remaining</TH>
- <TH ALIGN="right">Total remaining</TH>
- </TR>
-<%= foreach my $svc ( @svcs ) {
+<%= if ( @svc_acct ) {
+ $OUT.= '<FONT SIZE="4">Account usage</FONT><BR><BR>
+ <TABLE BGCOLOR="#cccccc">
+ <TR>
+ <TH ALIGN="left">Account</TH>
+ <TH ALIGN="right">Time remaining</TH>
+ <TH ALIGN="right">Upload remaining</TH>
+ <TH ALIGN="right">Download remaining</TH>
+ <TH ALIGN="right">Total remaining</TH>
+ </TR>';
+ } else {
+ $OUT .= '';
+ }
+%>
+
+<%= foreach my $svc ( @svc_acct ) {
my $link = "${url}view_usage_details;".
"svcnum=$svc->{'svcnum'};beginning=0;ending=0";
$OUT .= '<TR><TD>';
@@ -48,11 +54,33 @@
$OUT .= $svc->{'recharge_totalbytes'} if $svc->{'recharge_totalbytes'};
$OUT .= '</TD></TR>';
}
- } %>
+ }
+%>
-</TABLE>
-<BR>
+<%= scalar(@svc_acct) ? '</TABLE><BR><BR>' : '' %>
-</TD></TR></TABLE>
+<%= if ( @svc_phone ) {
+ $OUT.= '<FONT SIZE="4">Call usage</FONT><BR><BR>
+ <TABLE BGCOLOR="#cccccc">
+ <TR>
+ <TH ALIGN="left">Number</TH>'; #"Account" ?
+ #what else?
+ $OUT .= '</TR>';
+ } else {
+ $OUT .= '';
+ }
+%>
+<%= foreach my $svc_phone ( @svc_phone ) {
+ my $link = "${url}view_cdr_details;".
+ "svcnum=$svc_phone->{'svcnum'};beginning=0;ending=0";
+ $OUT .= '<TR><TD>';
+ $OUT .= qq!<A HREF="$link">!. $svc_phone->{'label'}. ': '. $svc_phone->{'value'}.'</A>';
+ $OUT .= '</TD></TR>';
+ }
+%>
+
+<%= scalar(@svc_phone) ? '</TABLE><BR><BR>' : '' %>
+
+</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/cgi/view_usage_details.html b/fs_selfservice/FS-SelfService/cgi/view_usage_details.html
index 6bac748..9f02eba 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_usage_details.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_usage_details.html
@@ -1,8 +1,5 @@
-<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
-<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('myaccount_menu') %>
-<TD VALIGN="top">
+<%= include('header') %>
<FONT SIZE=4>Service usage details for
<%= Date::Format::time2str('%b&nbsp;%o&nbsp;%Y', $beginning) %> -
@@ -80,5 +77,4 @@
</TABLE>
<BR>
-</TD></TR></TABLE>
<%= include('footer') %>
diff --git a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
index bdc8e15..0819d9d 100644
--- a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
+++ b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
@@ -13,6 +13,7 @@ use Storable 2.09 qw(nstore_fd fd_retrieve);
use IO::Handle qw(_IONBF);
use IO::Select;
use IO::File;
+use Text::CSV_XS;
#STDOUT->setbuf('');
@@ -36,6 +37,7 @@ my $lock_file = "/usr/local/freeside/selfservice$tag.writelock";
$|=1;
$SIG{__WARN__} = \&_logmsg;
+#$SIG{__DIE__} = sub { &_logmsg(@_); exit };
#read data to be cached or something
#warn "$me Reading init data\n" if $Debug;
@@ -75,6 +77,8 @@ nstore_fd( { _packet => '_enable_keepalive' } , \*STDOUT );
warn "entering main loop\n" if $Debug;
my %kids;
+my %ftp_scan_dir;
+my %ftp_scan_map;
my $s = new IO::Select;
$s->add(\*STDIN);
@@ -124,7 +128,18 @@ while (1) {
: '' )
if $Debug;
- if ( exists($kids{$token}) ) {
+ if ( $token eq '_ftp_scan' ) {
+ if ( $ftp_scan_dir{$packet->{dir}} ) {
+ warn "already processing ". $packet->{dir}. "\n" if $Debug;
+ } else {
+ $ftp_scan_dir{$packet->{dir}} = 1;
+ spawn \&ftp_scan, $packet;
+ }
+ $undisp = 1;
+ next;
+ }
+
+ if ( exists($kids{$token}) ) {
warn "sending return packet to $token via $kids{$token}\n"
if $Debug;
nstore_fd($packet, $kids{$token});
@@ -158,29 +173,11 @@ while (1) {
#handle some commands weirdly?
$packet->{_token}=$$;
- warn "[child-$$] locking write stream\n" if $Debug > 1;
- lock_write;
-
- warn "[child-$$] sending packet to remote server\n" if $Debug > 1;
- nstore_fd($packet, \*STDOUT) or die "FATAL: can't send response: $!";
-
- warn "[child-$$] flushing write stream\n" if $Debug > 1;
- STDOUT->flush or die "FATAL: can't flush: $!";
-
- warn "[child-$$] releasing write lock\n" if $Debug > 1;
- unlock_write;
+ my $rv = send_and_wait( $packet );
warn "[child-$$] closing write stream\n" if $Debug > 1;
close STDOUT or die "FATAL: can't close write stream: $!"; #??!
- warn "[child-$$] waiting for response from parent\n" if $Debug > 1;
- my $w = new IO::Select;
- $w->add(\*STDIN);
- until ( $w->can_read ) {
- warn "[child-$$] WARNING: interrupted select: $!\n";
- }
- my $rv = fd_retrieve(\*STDIN);
-
#close STDIN;
warn "[child-$$] sending response to local client" if $Debug > 1;
@@ -210,13 +207,17 @@ sub reap_kids {
if ( $kid > 0 ) {
close $kids{$kid};
delete $kids{$kid};
+ if ( $ftp_scan_map{$kid} ) {
+ delete($ftp_scan_dir{$ftp_scan_map{$kid}});
+ delete($ftp_scan_map{$kid});
+ }
}
}
#warn "done reaping\n";
}
sub spawn {
- my $coderef = shift;
+ my ( $coderef, $packet ) = ( shift, shift );
unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
use Carp;
@@ -231,6 +232,7 @@ sub spawn {
return;
} elsif ($pid) {
warn "begat $pid" if $Debug;
+ $ftp_scan_map{$pid} = $packet->{dir} if $coderef == \&ftp_scan;
$kids{$pid} = $kid;
#$kids{$pid}->autoflush;
return; # I'm the parent
@@ -240,7 +242,7 @@ sub spawn {
# open(STDIN, "<&Client") || die "can't dup client to stdin";
# open(STDOUT, ">&Client") || die "can't dup client to stdout";
# open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
- exit &$coderef();
+ exit &$coderef($packet);
}
sub _logmsg {
@@ -254,6 +256,31 @@ sub _logmsg {
close $log;
}
+sub send_and_wait {
+ my $packet = shift;
+
+ warn "[child-$$] locking write stream\n" if $Debug > 1;
+ lock_write;
+
+ warn "[child-$$] sending packet to remote server\n" if $Debug > 1;
+ nstore_fd($packet, \*STDOUT) or die "FATAL: can't send response: $!";
+
+ warn "[child-$$] flushing write stream\n" if $Debug > 1;
+ STDOUT->flush or die "FATAL: can't flush: $!";
+
+ warn "[child-$$] releasing write lock\n" if $Debug > 1;
+ unlock_write;
+
+ warn "[child-$$] waiting for response from parent\n" if $Debug > 1;
+ my $w = new IO::Select;
+ $w->add(\*STDIN);
+ until ( $w->can_read ) {
+ warn "[child-$$] WARNING: interrupted select: $!\n";
+ }
+
+ fd_retrieve(\*STDIN);
+}
+
sub lock_write {
#broken on freebsd?
#flock(STDOUT, LOCK_EX) or die "FATAL: can't lock write stream: $!";
@@ -270,3 +297,81 @@ sub unlock_write {
flock(LOCKFILE, LOCK_UN) or die "FATAL: can't unlock $lock_file: $!";
}
+
+sub ftp_scan {
+ my $packet = shift;
+
+ warn "[child-$$] performing ftp scan" if $Debug > 1;
+
+ warn "[child-$$] packet received:\n".
+ join('', map { " $_=>$packet->{$_}\n" } keys %$packet )
+ if $Debug > 2;
+
+ $packet->{_token}=$$;
+
+ my $dir;
+ $packet->{dir} =~ /^(.*)$/ && ($dir = $1); # we trust ourselves
+ opendir(DIR, $dir) or die "failed to open directory $dir: $!\n";
+ my @files = grep(/\.csv$/, readdir(DIR));
+ closedir(DIR);
+
+ foreach my $file ( @files ) {
+ warn "Processing $file ...\n";
+ my $csv = Text::CSV_XS->new();
+ my $err = "";
+ my @records = ();
+ open(CSV, "<$dir/$file") or die "can't open input file for $file: $!\n";
+ open(RESULT, ">$dir/result/$file")
+ or die "can't open result file for $file: $!\n";
+
+ while (<CSV>) {
+ if ( $csv->parse($_) ) {
+ my @columns = $csv->fields();
+ push(@records, \@columns);
+ } else {
+ $err = $csv->error_input;
+ last;
+ }
+ }
+ close(CSV);
+ if ( $err ) {
+ rename("$dir/$file", "$dir/rejected/$file");
+ } else {
+ foreach my $record ( @records ) {
+
+ $packet->{row} = $record;
+ $packet->{_packet} = 'Bulk/processrow';
+ my $result = send_and_wait( $packet );
+
+ if ( $result->{error} ) {
+ my $name;
+ $record->[1] =~ /^(\w+)$/ && ( $name = $1 );
+
+ if ($name) {
+ my $filename = "$dir/rejected/$name";
+ open(REC, ">$filename") or die "can't open $filename: $!\n";
+ print REC join(',', @$record);
+ close REC or die $!;
+ open(ERR, ">$filename.err") or die "can't open $filename.err: $!\n";
+ print ERR $result->{error};
+ close ERR or die $!;
+ }else{
+ warn "bad agent_custid";
+ }
+
+ }
+ print RESULT $result->{message}, "\n";
+ }
+
+ rename("$dir/$file", "$dir/processed/$file");
+ warn "$file processed.\n" if $Debug;
+ }
+ close(RESULT);
+ }
+
+ close STDOUT or die "FATAL: can't close write stream: $!"; #??!
+
+ warn "[child-$$] child exiting" if $Debug > 1;
+ exit;
+
+}
diff --git a/fs_selfservice/FS-SelfService/freeside-selfservice-soap-server b/fs_selfservice/FS-SelfService/freeside-selfservice-soap-server
new file mode 100644
index 0000000..869a8ae
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/freeside-selfservice-soap-server
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+#
+# freeside-selfservice-soap-server
+#
+
+use strict;
+use Fcntl qw(:flock);
+use POSIX;
+use Getopt::Std;
+use SOAP::Transport::HTTP;
+use FS::SelfService;
+
+use vars qw( $opt_p $opt_d $opt_s );
+use vars qw( $DEBUG );
+
+getopts("s:p:d");
+$DEBUG = $opt_d;
+my $tag = $opt_s ? $opt_s : '';
+$tag = ($opt_s ? ':' : '') . $opt_p ? ':'.$opt_p : '';
+
+my $log_file = "/usr/local/freeside/selfservice.soap$tag.log";
+
+my $pid = fork;
+defined($pid) or die "Can't fork to start: $!";
+print "Started daemon with pid $pid\n" if $pid;
+exit if $pid;
+
+POSIX::setsid();
+open STDIN, "/dev/null" or die "Can't get rid of STDIN";
+open STDOUT, ">/dev/null" or die "Can't get rid of STDOUT";
+open STDERR, ">&STDOUT" or die "Can't get rid of STDERR";
+
+$SIG{__WARN__} = \&_logmsg;
+$SIG{__DIE__} = sub { &_logmsg(@_); exit };
+
+my $daemon = SOAP::Transport::HTTP::Daemon
+ ->new($opt_s ? (LocalAddr => $opt_s) : (), LocalPort => $opt_p ? $opt_p : 8080)
+ ->dispatch_to('/usr/local/freeside/SOAP/') #, 'FS::SelfService'
+ ->objects_by_reference('iZoomOnlineProvisionService')
+ ->handle;
+
+warn "Handling request at ", $daemon->url, "\n";
+$daemon->handle;
+
+sub _logmsg {
+ chomp( my $msg = shift );
+ my $log = new IO::File ">>$log_file";
+ flock($log, LOCK_EX);
+ seek($log, 0, 2);
+ print $log "[". scalar(localtime). "] [$$] $msg\n";
+ flock($log, LOCK_UN);
+ close $log;
+}
diff --git a/fs_selfservice/FS-SelfService/iZoomOnlineProvisionService.pm b/fs_selfservice/FS-SelfService/iZoomOnlineProvisionService.pm
new file mode 100644
index 0000000..f4c5869
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/iZoomOnlineProvisionService.pm
@@ -0,0 +1,75 @@
+package iZoomOnlineProvisionService;
+
+use strict;
+
+#BEGIN { push @INC, '/usr/lib/perl/5.8.8/' };
+use FS::SelfService qw( bulk_processrow check_username agent_login );
+
+=begin WSDL
+
+_IN agent_username $string agent username
+_IN agent_password $string agent password
+_IN agent_custid $string customer id in agent system
+_IN username $string customer service username
+_IN password $string customer service password
+_IN daytime $string phone number
+_IN first $string first name
+_IN last $string last name
+_IN address1 $string address line 1
+_IN address2 $string address line 2
+_IN city $string city
+_IN state $string state
+_IN zip $string zip
+_IN pkg $string package name
+_IN action $string one of (R|P|D|S)(reconcile, provision, provision with disk, send disk)
+_IN adjourn $string day to terminate service
+_IN mobile $string mobile phone
+_IN sms $string (T|F) acceptable to send SMS messages to mobile?
+_IN ship_addr1 $string shipping address line 1
+_IN ship_addr2 $string shipping address line 2
+_IN ship_city $string shipping address city
+_IN ship_state $string shipping address state
+_IN ship_zip $string shipping address zip
+_RETURN @string array [status, message]. status is one of OK, ERR
+
+=cut
+
+my $DEBUG = 0;
+
+sub Provision {
+ my $class = shift;
+
+ my $session = agent_login( map { $_ => shift @_ } qw( username password ) );
+ return [ 'ERR', $session->{error} ] if $session->{error};
+
+ my $result =
+ bulk_processrow( session_id => $session->{session_id}, row => [ @_ ] );
+
+ return $result->{error} ? [ 'ERR', $result->{error} ]
+ : [ 'OK', $result->{message} ];
+}
+
+=begin WSDL
+
+_IN agent_username $string agent username
+_IN agent_password $string agent password
+_IN username $string customer service username
+_IN domain $string user domain name
+_RETURN @string [OK|ERR]
+
+=cut
+sub CheckUserName {
+ my $class = shift;
+
+ my $session = agent_login( map { $_ => shift @_ } qw( username password ) );
+ return [ 'ERR', $session->{error} ] if $session->{error};
+
+ my $result = check_username( session_id => $session->{session_id},
+ map { $_ => shift @_ } qw( user domain )
+ );
+
+ return $result->{error} ? [ 'ERR', $result->{error} ]
+ : [ 'OK', $result->{message} ];
+}
+
+1;
diff --git a/htetc/freeside-base1.99.conf b/htetc/freeside-base1.99.conf
index 8e890e6..ce3c3f2 100644
--- a/htetc/freeside-base1.99.conf
+++ b/htetc/freeside-base1.99.conf
@@ -8,6 +8,9 @@ PerlModule HTML::Mason::ApacheHandler
PerlRequire "%%%MASON_HANDLER%%%"
+#Locale::SubCountry
+AddDefaultCharset ISO-8859-1
+
<Directory %%%FREESIDE_DOCUMENT_ROOT%%%>
AuthName Freeside
AuthType Basic
diff --git a/htetc/freeside-base1.conf b/htetc/freeside-base1.conf
index 73962a7..7b8d9da 100644
--- a/htetc/freeside-base1.conf
+++ b/htetc/freeside-base1.conf
@@ -2,6 +2,9 @@
PerlModule HTML::Mason
+#Locale::SubCountry
+AddDefaultCharset ISO-8859-1
+
<Directory %%%FREESIDE_DOCUMENT_ROOT%%%>
AuthName Freeside
AuthType Basic
diff --git a/htetc/freeside-base2.conf b/htetc/freeside-base2.conf
index 6606129..1cd1cc5 100644
--- a/htetc/freeside-base2.conf
+++ b/htetc/freeside-base2.conf
@@ -8,6 +8,9 @@ PerlModule HTML::Mason::ApacheHandler
PerlRequire "%%%MASON_HANDLER%%%"
+#Locale::SubCountry
+AddDefaultCharset ISO-8859-1
+
<Directory %%%FREESIDE_DOCUMENT_ROOT%%%>
AuthName Freeside
AuthType Basic
diff --git a/htetc/handler.pl b/htetc/handler.pl
index 1dd16ec..952d620 100644
--- a/htetc/handler.pl
+++ b/htetc/handler.pl
@@ -44,7 +44,8 @@ sub handler
###Module::Refresh->refresh;###
- $r->content_type('text/html');
+ #$r->content_type('text/html; charset=utf-8');
+ $r->content_type('text/html; charset=iso-8859-1');
#eorar
my $headers = $r->headers_out;
@@ -69,6 +70,15 @@ sub handler
} else {
+ local $SIG{__WARN__};
+ local $SIG{__DIE__};
+
+ RT::Init() if $RT::VERSION; #for lack of something else
+
+ #we don't want the RT error handlers under FS
+ undef $SIG{__WARN__} if defined($SIG{__WARN__});
+ undef $SIG{__DIE__} if defined($SIG{__DIE__} );
+
$ah->interp($fs_interp);
}
diff --git a/httemplate/browse/agent.cgi b/httemplate/browse/agent.cgi
index 0a516ed..1c06f1b 100755
--- a/httemplate/browse/agent.cgi
+++ b/httemplate/browse/agent.cgi
@@ -20,8 +20,6 @@ full offerings (via their type).<BR><BR>
% my $bgcolor1 = '#eeeeee';
% my $bgcolor2 = '#ffffff';
% my $bgcolor = '';
-%
-
<TR>
<TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<% ( $cgi->param('showdisabled') || !dbdef->table('agent')->column('disabled') ) ? 2 : 3 %>>Agent</TH>
@@ -34,18 +32,17 @@ full offerings (via their type).<BR><BR>
<TH CLASS="grid" BGCOLOR="#cccccc">Reports</TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Registration<BR>codes</FONT></TH>
<TH CLASS="grid" BGCOLOR="#cccccc">Prepaid cards</TH>
-% if ( $conf->config('ticket_system') ) {
+% if ( $conf->config('ticket_system') ) {
<TH CLASS="grid" BGCOLOR="#cccccc">Ticketing</TH>
% }
<TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Payment Gateway Overrides</FONT></TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Configuration Overrides</FONT></TH>
</TR>
-%
+
%# <TH><FONT SIZE=-1>Agent #</FONT></TH>
%# <TH>Agent</TH>
-%
%foreach my $agent ( sort {
% #$a->getfield('agentnum') <=> $b->getfield('agentnum')
% $a->getfield('agent') cmp $b->getfield('agent')
@@ -61,9 +58,6 @@ full offerings (via their type).<BR><BR>
% } else {
% $bgcolor = $bgcolor1;
% }
-%
-%
-
<TR>
@@ -366,7 +360,7 @@ Unused
? ' for '. $override->taxclass. ' only'
: ''
%>
- <FONT SIZE=-1><A HREF="<%$p%>misc/delete-agent_payment_gateway.cgi?<% $override->agentgatewaynum %>">(delete)</A></FONT>
+ <FONT SIZE=-1><A HREF="javascript:areyousure('delete this payment gateway override', '<%$p%>misc/delete-agent_payment_gateway.cgi?<% $override->agentgatewaynum %>')">(delete)</A></FONT>
</TD>
</TR>
% }
@@ -386,7 +380,7 @@ Unused
<TR>
<TD>
- <% $override->name %>&nbsp;<FONT SIZE=-1><A HREF="<%$p%>config/config-delete.cgi?<% $override->confnum %>">(delete)</A></FONT>
+ <% $override->name %>&nbsp;<FONT SIZE=-1><A HREF="javascript:areyousure('delete this configuration override', '<%$p%>config/config-delete.cgi?confnum=<% $override->confnum %>')">(delete)</A></FONT>
</TD>
</TR>
% }
@@ -402,6 +396,14 @@ Unused
</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+ function areyousure(what, href) {
+ if ( confirm("Are you sure you want to " + what + "?") == true )
+ window.location.href = href;
+ }
+</SCRIPT>
+
</BODY>
</HTML>
<%init>
diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi
index d64ff18..f07a651 100755
--- a/httemplate/browse/agent_type.cgi
+++ b/httemplate/browse/agent_type.cgi
@@ -44,7 +44,9 @@ my $agent_type = shift;
[
{
#'data' => $part_pkg->pkg. ' - '. $part_pkg->comment,
- 'data' => $type_pkgs->pkg. ' - '. $type_pkgs->comment,
+ 'data' => $type_pkgs->pkg. ' - '.
+ ( $type_pkgs->custom ? '(CUSTOM) ' : '' ).
+ $type_pkgs->comment,
'align' => 'left',
'link' => $p. 'edit/part_pkg.cgi?'. $type_pkgs->pkgpart,
},
diff --git a/httemplate/browse/cust_main_county.cgi b/httemplate/browse/cust_main_county.cgi
index 736d7fd..232e688 100755
--- a/httemplate/browse/cust_main_county.cgi
+++ b/httemplate/browse/cust_main_county.cgi
@@ -23,10 +23,6 @@
'link_onclicks' => \@link_onclicks,
)
%>
-%
-% # <FONT SIZE=-1><A HREF="<% $p %>edit/process/cust_main_county-collapse.cgi?<% $hashref->{taxnum} %>">collapse state</A></FONT>
-% # % }
-%
<%once>
my $conf = new FS::Conf;
@@ -102,6 +98,17 @@ sub expand_link {
'</FONT>';
}
+sub collapse_link {
+ my %param = @_;
+
+ my $taxnum = $param{'row'}->taxnum;
+ my $url = "${p}edit/process/cust_main_county-collapse.cgi?$taxnum";
+ $url = "javascript:collapse_areyousure('$url')";
+
+ qq(<FONT SIZE="-1"><A HREF="$url">$param{'label'}</A></FONT>);
+}
+
+
sub separate_taxclasses_link {
my( $row ) = @_;
my $taxnum = $row->taxnum;
@@ -110,6 +117,8 @@ sub separate_taxclasses_link {
qq!<FONT SIZE="-1"><A HREF="$url">!;
}
+#un-separate taxclasses too
+
</%once>
<%init>
@@ -122,9 +131,18 @@ my $enable_taxclasses = $conf->exists('enable_taxclasses');
my @menubar;
-my $html_init =
- "Click on <u>add states</u> to specify a country's tax rates by state or province.
- <BR>Click on <u>add counties</u> to specify a state's tax rates by county.";
+my $html_init = <<END;
+ <SCRIPT>
+ function collapse_areyousure(href) {
+ if (confirm("Are you sure you want to remove all county tax rates for this state?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+ Click on <u>add states</u> to specify a country's tax rates by state or province.
+ <BR>Click on <u>add counties</u> to specify a state's tax rates by county, or <u>remove counties</u> to remove per-county tax rates.
+END
+
$html_init .= "<BR>Click on <u>separate taxclasses</u> to specify taxes per taxclass."
if $enable_taxclasses;
$html_init .= '<BR><BR>';
@@ -360,11 +378,16 @@ my @fields = (
)
)
},
- sub { $_[0]->county || '(all)&nbsp'.
- expand_link( desc => 'Add Counties',
- row => $_[0],
- label => 'add&nbsp;counties',
- )
+ sub { $_[0]->county
+ ? $_[0]->county. '&nbsp'.
+ collapse_link( label=> 'remove&nbsp;counties',
+ row => $_[0],
+ )
+ : '(all)&nbsp'.
+ expand_link( desc => 'Add Counties',
+ row => $_[0],
+ label => 'add&nbsp;counties',
+ );
},
);
diff --git a/httemplate/browse/part_device.html b/httemplate/browse/part_device.html
new file mode 100644
index 0000000..5c8fde3
--- /dev/null
+++ b/httemplate/browse/part_device.html
@@ -0,0 +1,27 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Phone device types',
+ 'name' => 'phone device types',
+ 'menubar' => [ 'Add a new device type' =>
+ $p.'edit/part_device.html',
+ 'Import device types' =>
+ $p.'misc/part_device-import.html',
+ ],
+ 'query' => { 'table' => 'part_device', },
+ 'count_query' => 'SELECT COUNT(*) FROM part_device',
+ 'header' => [ '#', 'Device type' ],
+ 'fields' => [ 'devicepart',
+ 'devicename',
+ ],
+ 'links' => [ $link,
+ $link,
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $link = [ "${p}edit/part_device.html?", 'devicepart' ];
+
+</%init>
diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
index 801c09f..c6cbb81 100755
--- a/httemplate/browse/part_pkg.cgi
+++ b/httemplate/browse/part_pkg.cgi
@@ -1,16 +1,17 @@
<% include( 'elements/browse.html',
'title' => 'Package Definitions',
'html_init' => $html_init,
+ 'html_posttotal' => $html_posttotal,
'name' => 'package definitions',
'disableable' => 1,
- 'disabled_statuspos' => 3,
+ 'disabled_statuspos' => 4,
'agent_virt' => 1,
'agent_null_right' => [ $edit, $edit_global ],
'agent_null_right_link' => $edit_global,
- 'agent_pos' => 5,
+ 'agent_pos' => 6,
'query' => { 'select' => $select,
'table' => 'part_pkg',
- 'hashref' => {},
+ 'hashref' => \%hash,
'extra_sql' => $extra_sql,
'order_by' => "ORDER BY $orderby"
},
@@ -41,16 +42,48 @@ my $money_char = $conf->config('money_char') || '$';
my $select = '*';
my $orderby = 'pkgpart';
+my %hash = ();
+my $extra_count = '';
+
if ( $cgi->param('active') ) {
$orderby = 'num_active DESC';
}
-my $extra_sql = '';
+my @where = ();
+
+#if ( $cgi->param('activeONLY') ) {
+# push @where, ' WHERE num_active > 0 '; #XXX doesn't affect count...
+#}
+
+if ( $cgi->param('recurring') ) {
+ $hash{'freq'} = { op=>'!=', value=>'0' };
+ $extra_count = " freq != '0' ";
+}
-unless ( $acl_edit_global ) {
- $extra_sql .= ' WHERE '. FS::part_pkg->curuser_pkgs_sql;
+my $classnum = '';
+if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
+ $classnum = $1;
+ push @where, $classnum ? "classnum = $classnum"
+ : "classnum IS NULL";
+}
+$cgi->delete('classnum');
+
+if ( $cgi->param('missing_recur_fee') ) {
+ push @where, "0 = ( SELECT COUNT(*) FROM part_pkg_option
+ WHERE optionname = 'recur_fee'
+ AND part_pkg_option.pkgpart = part_pkg.pkgpart
+ AND CAST ( optionvalue AS NUMERIC ) > 0
+ )";
}
+push @where, FS::part_pkg->curuser_pkgs_sql
+ unless $acl_edit_global;
+
+my $extra_sql = scalar(@where)
+ ? ( scalar(keys %hash) ? ' AND ' : ' WHERE ' ).
+ join( 'AND ', @where)
+ : '';
+
my $agentnums = join(',', $curuser->agentnums);
my $count_cust_pkg = "
SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )
@@ -94,14 +127,49 @@ my $html_init;
!;
#}
+$cgi->param('dummy', 1);
+
+my $filter_change =
+ qq(\n<SCRIPT TYPE="text/javascript">\n).
+ "function filter_change() {".
+ " window.location = '". $cgi->self_url.
+ ";classnum=' + document.getElementById('classnum').options[document.getElementById('classnum').selectedIndex].value".
+ "}".
+ "\n</SCRIPT>\n";
+
+#restore this so pagination works
+$cgi->param('classnum', $classnum) if length($classnum);
+
+my $html_posttotal =
+ "$filter_change\n<BR>( show class: ".
+ include('/elements/select-pkg_class.html',
+ #'curr_value' => $classnum,
+ 'value' => $classnum, #insist on 0 :/
+ 'onchange' => 'filter_change()',
+ 'pre_options' => [ '-1' => 'all',
+ '0' => '(none)', ],
+ 'disable_empty' => 1,
+ ).
+ ' )';
+
+my $recur_toggle = $cgi->param('recurring') ? 'show' : 'hide';
+$cgi->param('recurring', $cgi->param('recurring') ^ 1 );
+
+$html_posttotal .=
+ '( <A HREF="'. $cgi->self_url.'">'. "$recur_toggle one-time charges</A> )";
+
+$cgi->param('recurring', $cgi->param('recurring') ^ 1 ); #put it back
+
# ------
my $link = [ $p.'edit/part_pkg.cgi?', 'pkgpart' ];
-my @header = ( '#', 'Package', 'Comment' );
-my @fields = ( 'pkgpart', 'pkg', 'comment' );
-my $align = 'rll';
-my @links = ( $link, $link, '' );
+my @header = ( '#', 'Package', 'Comment', 'Custom' );
+my @fields = ( 'pkgpart', 'pkg', 'comment',
+ sub{ '<B><FONT COLOR="#0000CC">'.$_[0]->custom.'</FONT></B>' }
+ );
+my $align = 'rllc';
+my @links = ( $link, $link, '', '' );
unless ( 0 ) { #already showing only one class or something?
push @header, 'Class';
@@ -188,9 +256,7 @@ if ( $acl_edit_global ) {
my $typelink = $p. 'edit/agent_type.cgi?';
push @fields, sub { my $part_pkg = shift;
[
- map { warn $_;
- my $agent_type = $_->agent_type;
- warn $agent_type;
+ map { my $agent_type = $_->agent_type;
[
{ 'data' => $agent_type->atype, #escape?
'align' => 'left',
@@ -362,6 +428,10 @@ $align .= 'lrl'; #rr';
# --------
-my $count_query = "SELECT COUNT(*) FROM part_pkg $extra_sql";
+my $count_extra_sql = $extra_sql;
+$count_extra_sql =~ s/^\s*AND /WHERE /i;
+$extra_count = ( $count_extra_sql ? ' AND ' : ' WHERE ' ). $extra_count
+ if $extra_count;
+my $count_query = "SELECT COUNT(*) FROM part_pkg $count_extra_sql $extra_count";
</%init>
diff --git a/httemplate/browse/part_pkg_report_option.html b/httemplate/browse/part_pkg_report_option.html
new file mode 100644
index 0000000..90540bc
--- /dev/null
+++ b/httemplate/browse/part_pkg_report_option.html
@@ -0,0 +1,28 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Package optional report classes',
+ 'html_init' => $html_init,
+ 'name' => 'package optional report classes',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'query' => { 'table' => 'part_pkg_report_option',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY name',
+ },
+ 'count_query' => 'SELECT COUNT(*) FROM part_pkg_report_option',
+ 'header' => [ '#', 'Class' ],
+ 'fields' => [ 'num', 'name' ],
+ 'links' => [ $link, $link ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ 'Package optional report classes define groups of packages, for reporting purposes.'.
+ qq!<BR><BR><A HREF="${p}edit/part_pkg_report_option.html"><I>Add a class</I></A><BR><BR>!;
+
+my $link = [ $p.'edit/part_pkg_report_option.html?', 'num' ];
+
+</%init>
diff --git a/httemplate/browse/part_pkg_taxclass.html b/httemplate/browse/part_pkg_taxclass.html
new file mode 100644
index 0000000..04e0e23
--- /dev/null
+++ b/httemplate/browse/part_pkg_taxclass.html
@@ -0,0 +1,27 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Tax Classes',
+ 'name_singular' => 'tax class',
+ 'menubar' => [ 'Add a new tax class' =>
+ $p.'edit/part_pkg_taxclass.html',
+ ],
+ 'query' => { 'table' => 'part_pkg_taxclass', },
+ 'count_query' => 'SELECT COUNT(*) FROM part_pkg_taxclass',
+ 'header' => [ '#', 'Device type' ],
+ 'fields' => [ 'taxclassnum',
+ 'taxclass',
+ ],
+ 'links' => [ $link,
+ $link,
+ ],
+ 'disableable' => 1,
+ 'disabled_statuspos' => 1,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $link = [ "${p}edit/part_pkg_taxclass.html?", 'taxclassnum' ];
+
+</%init>
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
index f1b2836..94afdef 100755
--- a/httemplate/browse/part_svc.cgi
+++ b/httemplate/browse/part_svc.cgi
@@ -55,6 +55,8 @@ function part_export_areyousure(href) {
<TH CLASS="grid" BGCOLOR="#cccccc">Field</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Label</TH>
+
<TH COLSPAN=2 CLASS="grid" BGCOLOR="#cccccc">Modifier</TH>
</TR>
@@ -65,8 +67,15 @@ function part_export_areyousure(href) {
% my @dfields = $svc_x->fields;
% push @dfields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
% my @fields =
-% grep { $svc_x->pvf($_)
-% or $_ ne 'svcnum' && $part_svc->part_svc_column($_)->columnflag }
+% grep { my $col = $part_svc->part_svc_column($_);
+% my $def = FS::part_svc->svc_table_fields($svcdb)->{$_};
+% $svc_x->pvf($_)
+% or $_ ne 'svcnum' && (
+% $col->columnflag || ( $col->columnlabel !~ /^\S*$/
+% && $col->columnlabel ne $def->{'label'}
+% )
+% )
+% }
% @dfields ;
% my $rowspan = scalar(@fields) || 1;
% my $url = "${p}edit/part_svc.cgi?". $part_svc->svcpart;
@@ -128,21 +137,25 @@ function part_export_areyousure(href) {
</TD>
% unless ( @fields ) {
-% for ( 1..3 ) {
+% for ( 1..4 ) {
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"</TD>
% }
% }
%
% my($n1)='';
% foreach my $field ( @fields ) {
-% my $formatter =
-% FS::part_svc->svc_table_fields($svcdb)->{$field}->{format}
-% || sub { shift };
-% my $flag = $part_svc->part_svc_column($field)->columnflag;
%
+% #a few lines of false laziness w/edit/part_svc.cgi
+% my $def = FS::part_svc->svc_table_fields($svcdb)->{$field};
+% my $formatter = $def->{format} || sub { shift };
+%
+% my $part_svc_column = $part_svc->part_svc_column($field);
+% my $label = $part_svc_column->columnlabel || $def->{'label'};
+% my $flag = $part_svc_column->columnflag;
<% $n1 %>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $field %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $label %></TD>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $flag{$flag} %></TD>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
diff --git a/httemplate/browse/payment_gateway.html b/httemplate/browse/payment_gateway.html
index 848c58a..a06e5cf 100644
--- a/httemplate/browse/payment_gateway.html
+++ b/httemplate/browse/payment_gateway.html
@@ -10,17 +10,21 @@
},
'count_query' => $count_query,
'header' => [ '#',
+ 'Type',
'Gateway',
'Username',
'Password',
'Action',
+ 'URL',
'Options',
],
'fields' => [ 'gatewaynum',
+ 'namespace_description',
$gateway_sub,
'gateway_username',
sub { ' - '; },
'gateway_action',
+ 'gateway_callback_url',
$options_sub,
],
)
diff --git a/httemplate/browse/pkg_category.html b/httemplate/browse/pkg_category.html
index 20bf1a8..e85c0dd 100644
--- a/httemplate/browse/pkg_category.html
+++ b/httemplate/browse/pkg_category.html
@@ -9,9 +9,9 @@
'extra_sql' => 'ORDER BY categorynum',
},
'count_query' => $count_query,
- 'header' => [ '#', 'Category' ],
- 'fields' => [ 'categorynum', 'categoryname' ],
- 'links' => [ $link, $link ],
+ 'header' => [ '#', 'Category', 'Weight' ],
+ 'fields' => [ 'categorynum', 'categoryname', 'weight' ],
+ 'links' => [ $link, $link, $link ],
)
%>
diff --git a/httemplate/browse/rate_region.html b/httemplate/browse/rate_region.html
index b454a9e..b7d9589 100644
--- a/httemplate/browse/rate_region.html
+++ b/httemplate/browse/rate_region.html
@@ -12,9 +12,11 @@
'order_by' => 'ORDER BY LOWER(regionname)',
},
'count_query' => $count_query,
- 'header' => [ '#', 'Region', 'Country code', 'Prefixes' ],
- 'fields' => [ 'regionnum', 'regionname', 'ccode', 'prefixes' ],
- 'links' => [ $link, $link, $link, $link ],
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'links' => \@links,
+ 'align' => \@align,
+ 'xls_format' => \@xls_format,
)
%>
<%once>
@@ -39,12 +41,12 @@ if ( driver_name =~ /^Pg/ ) {
" ELSE npa || '-' || nxx ".
" END";
my $prefixes_sql = "SELECT $prefix_sql $fromwhere AND npa IS NOT NULL";
- $select .= "( SELECT countrycode $fromwhere LIMIT 1 ) AS ccode,
- ARRAY_TO_STRING( ARRAY($prefixes_sql), ',' ) AS prefixes";
+ $select .= "( SELECT '+'||countrycode $fromwhere LIMIT 1 ) AS ccode,
+ ARRAY_TO_STRING( ARRAY($prefixes_sql), ', ' ) AS prefixes";
} elsif ( driver_name =~ /^mysql/i ) {
$join = 'LEFT JOIN rate_prefix USING ( regionnum )';
- $select .= "GROUP_CONCAT( DISTINCT countrycode ) AS ccode,
- GROUP_CONCAT( npa ORDER BY npa ) AS prefixes ";
+ $select .= "'+'||GROUP_CONCAT( DISTINCT countrycode ) AS ccode,
+ GROUP_CONCAT( npa ORDER BY npa SEPARATOR ', ' ) AS prefixes ";
$group_sql = 'GROUP BY regionnum, regionname';
} else {
die 'unknown database '. driver_name;
@@ -52,12 +54,20 @@ if ( driver_name =~ /^Pg/ ) {
my $base_count_sql = 'SELECT COUNT(*) FROM rate_region';
+tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
+
</%once>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+my @header = ( '#', 'Region', 'Country code', 'Prefixes' );
+my @fields = ( 'regionnum', 'regionname', 'ccode', 'prefixes' );
+my @links = ( ($link) x 4 );
+my @align = ( 'right', 'left', 'right', 'left' );
+my @xls_format = ( ({ locked=>1, bg_color=>22 }) x 4 );
+
$cgi->param('dummy', 1);
my $countrycode_filter_change =
"window.location = '".
@@ -76,6 +86,41 @@ if ( $cgi->param('countrycode') =~ /^(\d+)$/ ) {
$count_query .= " WHERE $ccode_sql = '$1'";
}
+sub _rate_detail_factory {
+ my( $rate, $field ) = @_;
+ return sub {
+ my $rate_detail = $rate->dest_detail(shift)
+ || new FS::rate_region { 'min_included' => 0,
+ 'min_charge' => 0,
+ 'sec_granularity' => 0,
+ };
+ my $value = $rate_detail->$field();
+ $field eq 'sec_granularity' ? $granularity{$value} : $value;
+ };
+}
+
+if ( $cgi->param('show_rates') ) {
+ foreach my $rate ( qsearch('rate', {}) ) {
+
+ my $label = $rate->ratenum.': '. $rate->ratename;
+ push @header, "$label: Included minutes/calls",
+ "$label: Charge per minute/call",
+ "$label: Granularity",
+ "$label: Usage class";
+
+ #closure me harder
+ push @fields, _rate_detail_factory($rate, 'min_included'),
+ _rate_detail_factory($rate, 'min_charge'),
+ _rate_detail_factory($rate, 'sec_granularity'),
+ _rate_detail_factory($rate, 'classnum');
+
+ push @links, ( ('') x 4 );
+ push @xls_format, ( ({}) x 4 );
+
+ }
+
+}
+
my $html_posttotal =
'(show country code: '.
qq(<SELECT NAME="countrycode" onChange="$countrycode_filter_change">).
diff --git a/httemplate/browse/svc_acct_pop.cgi b/httemplate/browse/svc_acct_pop.cgi
index c6e615d..501d362 100755
--- a/httemplate/browse/svc_acct_pop.cgi
+++ b/httemplate/browse/svc_acct_pop.cgi
@@ -23,6 +23,7 @@
$num_accounts_sub,
],
'align' => 'rllrrrr',
+ 'links' => [ map { $svc_acct_pop_link } (1..6) ],
)
%>
<%init>
diff --git a/httemplate/config/config-delete.cgi b/httemplate/config/config-delete.cgi
index cdac434..a05cb1e 100644
--- a/httemplate/config/config-delete.cgi
+++ b/httemplate/config/config-delete.cgi
@@ -2,14 +2,21 @@
die "access denied\n"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-die "No configuration item specified (bad URL)!" unless $cgi->keywords;
-my ($query) = $cgi->keywords;
-$query =~ /^(\d+)$/;
+$cgi->param('confnum') =~ /^(\d+)$/ or die "illegal or missing confnum";
my $confnum = $1;
my $conf = qsearchs('conf', {'confnum' => $confnum});
die "Configuration not found!" unless $conf;
$conf->delete;
+my $redirect = popurl(2);
+if ( $cgi->param('redirect') eq 'config_view_showagent' ) {
+ $redirect .= 'config/config-view.cgi?showagent=1#'. $conf->name;
+} elsif ( $cgi->param('redirect') eq 'config_view' ) {
+ $redirect .= 'config/config-view.cgi';
+} else {
+ $redirect .= 'browse/agent.cgi';
+}
+
</%init>
-<% $cgi->redirect(popurl(2) . "browse/agent.cgi") %>
+<% $cgi->redirect($redirect) %>
diff --git a/httemplate/config/config-image.cgi b/httemplate/config/config-image.cgi
index 892f7c6..0de9d42 100644
--- a/httemplate/config/config-image.cgi
+++ b/httemplate/config/config-image.cgi
@@ -1,4 +1,4 @@
-<% $conf->config_binary($name, $agentnum) %>
+<% $logo %>
<%init>
die "access denied"
@@ -16,4 +16,7 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
$agentnum = $1;
}
+my $logo = $conf->config_binary($name, $agentnum);
+$logo = eps2png($logo) if $name =~ /\.eps$/i;
+
</%init>
diff --git a/httemplate/config/config-process.cgi b/httemplate/config/config-process.cgi
index 84bfdef..a241de8 100644
--- a/httemplate/config/config-process.cgi
+++ b/httemplate/config/config-process.cgi
@@ -41,15 +41,18 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
} else {
push @delete, $i->key;
}
- } elsif ( $type eq 'text' || $type eq 'select' || $type eq 'select-sub' ) {
- if ( $cgi->param($i->key.$n) ne '' ) {
- $conf->set($i->key, $cgi->param($i->key.$n), $agentnum);
+ } elsif (
+ $type =~ /^(editlist|selectmultiple)$/
+ or ( $type =~ /^select(-(sub|part_svc|part_pkg))?$/ || $i->multiple )
+ ) {
+ if ( scalar(@{[ $cgi->param($i->key.$n) ]}) ) {
+ $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum);
} else {
$conf->delete($i->key, $agentnum);
}
- } elsif ( $type eq 'editlist' || $type eq 'selectmultiple' ) {
- if ( scalar(@{[ $cgi->param($i->key.$n) ]}) ) {
- $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum);
+ } elsif ( $type =~ /^(text|select(-(sub|part_svc|part_pkg))?)$/ ) {
+ if ( $cgi->param($i->key.$n) ne '' ) {
+ $conf->set($i->key, $cgi->param($i->key.$n), $agentnum);
} else {
$conf->delete($i->key, $agentnum);
}
@@ -65,7 +68,10 @@ $conf->delete($_, $agentnum) foreach @delete;
<SCRIPT TYPE="text/javascript">
% my $n = 0;
% foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
- var configCell = window.top.document.getElementById('<% $i->key. $n %>');
+ var configCell = window.top.document.getElementById('<% $agentnum. $i->key. $n %>');
+ if ( ! configCell ) {
+ window.top.location.reload();
+ }
//alert('found cell ' + configCell);
% if ( $type eq 'textarea'
% || $type eq 'editlist'
@@ -87,8 +93,22 @@ $conf->delete($_, $agentnum) foreach @delete;
configCell.style.backgroundColor = '#ff0000';
configCell.innerHTML = 'NO';
% }
+% } elsif ( $type eq 'select' && $i->select_hash ) {
+% my %hash;
+% if ( ref($i->select_hash) eq 'ARRAY' ) {
+% tie %hash, 'Tie::IxHash', '' => '', @{ $i->select_hash };
+% } else {
+% tie %hash, 'Tie::IxHash', '' => '', %{ $i->select_hash };
+% }
+ configCell.innerHTML = <% $conf->exists($i->key, $agentnum) ? $hash{ $conf->config($i->key, $agentnum) } : '' |js_string %>;
+
% } elsif ( $type eq 'text' || $type eq 'select' ) {
configCell.innerHTML = <% $conf->exists($i->key, $agentnum) ? $conf->config($i->key, $agentnum) : '' |js_string %>;
+% } elsif ( $type =~ /^select-(part_svc|part_pkg)$/ && ! $i->multiple ) {
+ configCell.innerHTML =
+ <% $conf->config($i->key, $agentnum) |js_string %>
+%# + ': ' +
+%# <% &{ $i->option_sub }( $conf->config($i->key, $agentnum) ) |js_string %>;
% } elsif ( $type eq 'select-sub' ) {
configCell.innerHTML =
<% $conf->config($i->key, $agentnum) |js_string %> + ': ' +
diff --git a/httemplate/config/config-view.cgi b/httemplate/config/config-view.cgi
index 0f5fd62..51535d7 100644
--- a/httemplate/config/config-view.cgi
+++ b/httemplate/config/config-view.cgi
@@ -3,6 +3,21 @@
Click on a configuration value to change it.
<BR><BR>
+% unless ( $page_agent ) {
+%
+% if ( $cgi->param('showagent') ) {
+% $cgi->param('showagent', 0);
+ ( <a href="<% $cgi->self_url %>">hide agent overrides</a> )
+% $cgi->param('showagent', 1);
+% } else {
+% $cgi->param('showagent', 1);
+ ( <a href="<% $cgi->self_url %>">show agent overrides</a> )
+% $cgi->param('showagent', 0);
+% }
+%
+% }
+<BR><BR>
+
<% include('/elements/init_overlib.html') %>
% if ($FS::UID::use_confcompat) {
@@ -33,7 +48,8 @@ Click on a configuration value to change it.
</tr>
% foreach my $i (@{ $section_items{$section} }) {
% my @types = ref($i->type) ? @{$i->type} : ($i->type);
-% my( $width, $height ) = ( 522, 336 );
+%# my( $width, $height ) = ( 522, 336 );
+% my( $width, $height ) = ( 600, 336 );
% if ( grep $_ eq 'textarea', @types ) {
% #800x600
% $width = 763;
@@ -42,6 +58,34 @@ Click on a configuration value to change it.
% #$width =
% #$height =
% }
+%
+% my @agents = ();
+% my @add_agents = ();
+% if ( $page_agent ) {
+% @agents = ( $page_agent );
+% } else {
+% @agents = ( '' );
+% if ( $i->per_agent ) {
+% foreach my $agent (@all_agents) {
+% if ( defined($conf->conf( $i->key, $agent->agentnum, 1 ) ) ) {
+% push @agents, $agent;
+% } else {
+% push @add_agents, $agent;
+% }
+% }
+% }
+% }
+%
+% foreach my $agent ( @agents ) {
+% my $agentnum = $agent ? $agent->agentnum : '';
+%
+% next if $section eq 'deprecated' && ! $conf->exists($i->key, $agentnum);
+%
+% my $label = $i->key;
+% $label = '['. $agent->agent. "] $label"
+% if $agent && $cgi->param('showagent');
+%
+% #indentation :/
<tr>
<td><% include('/elements/popup_link.html',
@@ -50,10 +94,24 @@ Click on a configuration value to change it.
'width' => $width,
'height' => $height,
'actionlabel' => 'Enter configuration value',
- 'label' => '<b>'. $i->key. '</b>',
- 'aname' => $i->key,
+ 'label' => "<b>$label</b>",
+ 'aname' => $i->key, #agentnum
+ # if $cgi->param('showagent')?
)
%>: <% $i->description %>
+% if ( $agent && $cgi->param('showagent') ) {
+% my $confnum = $conf->conf( $i->key, $agent->agentnum, 1 )->confnum;
+ (<A HREF="javascript:areyousure('delete this agent override', 'config-delete.cgi?confnum=<% $confnum %>;redirect=config_view_showagent')">delete agent override</A>)
+% } elsif ( $i->base_key
+% || ( $deleteable{$i->key} && $conf->exists($i->key) ) ) {
+% my $confnum =
+% $agent
+% ? $conf->conf( $i->key, $agent->agentnum, 1 )->confnum
+% : $conf->conf( $i->key )->confnum;
+% my $showagent = $cgi->param('showagent') ? '_showagent' : '';
+ (<A HREF="javascript:areyousure('delete this configuration item', 'config-delete.cgi?confnum=<% $confnum %>;redirect=config_view<%$showagent%>')">delete configuration item</A>)
+% }
+
</td>
<td><table border=0>
@@ -66,77 +124,181 @@ Click on a configuration value to change it.
<td><font color="#ff0000">no type</font></td>
</tr>
-% } elsif ( $type eq 'image' ) {
+% } elsif ( $type eq 'image' ) {
<tr>
-
- <% $conf->exists($i->key, $agentnum)
- ? '<img src="config-image.cgi?key='. $i->key.
- ';agentnum='. $agentnum. '">'
- : 'empty'
- %>
+ <td bgcolor='#ffffff'>
+ <% $conf->exists($i->key, $agentnum)
+ ? '<img src="config-image.cgi?key='. $i->key.
+ ';agentnum='. $agentnum. '">'
+ : 'empty'
+ %>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <% $conf->exists($i->key, $agentnum)
+ ? qq!<a href="config-download.cgi?key=!. $i->key. ';agentnum='. $agentnum. qq!">download</a>!
+ : ''
+ %>
+ </td>
</tr>
-% } elsif ( $type eq 'binary' ) {
+% } elsif ( $type eq 'binary' ) {
<tr>
-
- <% $conf->exists($i->key, $agentnum)
- ? qq!<a href="config-download.cgi?key=!. $i->key. ';agentnum='. $agentnum. qq!">download</a>!
- : 'empty'
- %>
+ <td>
+ <% $conf->exists($i->key, $agentnum)
+ ? qq!<a href="config-download.cgi?key=!. $i->key. ';agentnum='. $agentnum. qq!">download</a>!
+ : 'empty'
+ %>
+ </td>
</tr>
% } elsif ( $type eq 'textarea'
% || $type eq 'editlist'
-% || $type eq 'selectmultiple' ) {
+% || $type eq 'selectmultiple'
+% )
+% {
<tr>
- <td id="<% $i->key.$n %>" bgcolor="#ffffff">
-<font size="-2"><pre>
-<% encode_entities(join("\n",
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#ffffff">
+<font size="-2"><pre><% encode_entities(join("\n",
map { length($_) > 88 ? substr($_,0,88).'...' : $_ }
$conf->config($i->key, $agentnum)
) )
-%>
-</pre></font>
+%></pre></font>
</td>
</tr>
+
% } elsif ( $type eq 'checkbox' ) {
<tr>
- <td id="<% $i->key.$n %>" bgcolor="#<% $conf->exists($i->key, $agentnum) ? '00ff00">YES' : 'ff0000">NO' %></td>
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#<% $conf->exists($i->key, $agentnum) ? '00ff00">YES' : 'ff0000">NO' %></td>
</tr>
+
+% } elsif ( $type eq 'select' && $i->select_hash ) {
+%
+% my %hash;
+% if ( ref($i->select_hash) eq 'ARRAY' ) {
+% tie %hash, 'Tie::IxHash', '' => '', @{ $i->select_hash };
+% } else {
+% tie %hash, 'Tie::IxHash', '' => '', %{ $i->select_hash };
+% }
+
+ <tr>
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#ffffff">
+ <% $conf->exists($i->key, $agentnum) ? $hash{ $conf->config($i->key, $agentnum) } : '' %>
+ </td>
+ </tr>
+
% } elsif ( $type eq 'text' || $type eq 'select' ) {
<tr>
- <td id="<% $i->key.$n %>" bgcolor="#ffffff">
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#ffffff">
<% $conf->exists($i->key, $agentnum) ? $conf->config($i->key, $agentnum) : '' %>
- </td></tr>
-% } elsif ( $type eq 'select-sub' ) {
+ </td>
+ </tr>
+
+% } elsif ( $type eq 'select-sub' ) {
<tr>
- <td id="<% $i->key.$n %>" bgcolor="#ffffff">
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#ffffff">
<% $conf->config($i->key, $agentnum) %>:
<% &{ $i->option_sub }( $conf->config($i->key, $agentnum) ) %>
</td>
</tr>
-% } else {
+
+% } elsif ( $type =~ /^select-(part_svc|part_pkg)$/ ) {
+% my @keys = $conf->config($i->key, $agentnum);
+
+ <tr>
+ <td id="<% $agentnum.$i->key.$n %>" bgcolor="#ffffff">
+ <% join('<BR>', map { $_ # ': '. $svc, $pkg, whatever
+ }
+ @keys
+ )
+ %>
+ </td>
+ </tr>
+
+% } else {
<tr><td>
<font color="#ff0000">unknown type <% $type %></font>
</td></tr>
-% }
+% }
% $n++;
% }
</table></td>
</tr>
-% }
+
+% } # foreach my $agentnum
+
+% if ( @add_agents ) {
+
+ <tr>
+ <td>
+ <FORM>
+ Add <b><% $i->key %></b> override for
+ <% include('/elements/select-agent.html',
+ 'agents' => \@add_agents,
+ 'empty_label' => 'Select agent',
+ 'onchange' => "agent_changed",
+ 'id' => 'agent_'. $i->key,
+ )
+ %>
+ agent
+
+% my $agent_el = "document.getElementById('agent_". $i->key. "')";
+ <INPUT TYPE = "button"
+ VALUE = "Add"
+ ID = "add_<% $i->key %>"
+ DISABLED
+ onClick = "<%
+ include('/elements/popup_link_onclick.html',
+ 'action' =>
+ 'config.cgi?key='. $i->key.
+ ";agentnum=' + ".
+ "$agent_el.options[$agent_el.selectedIndex].value".
+ " + '",
+ 'width' => $width,
+ 'height' => $height,
+ 'actionlabel' => 'Enter configuration value',
+ )
+ %>"
+ >
+ </FORM>
+ </td>
+ </tr>
+
+% } #if @add_agents
+
+% } # foreach my $i
</table><br><br>
-% }
+% } # foreach my $nav_section
+
+<SCRIPT TYPE="text/javascript">
+
+ function agent_changed(what) {
+ var key = what.id.substring(6); // trim agent_
+ var button = document.getElementById('add_'+key);
+ if ( what.selectedIndex > 0 ) {
+ button.disabled = false;
+ } else {
+ button.disabled = true;
+ }
+ }
+
+ function areyousure(what, href) {
+ if ( confirm("Are you sure you want to " + what + "?") == true )
+ window.location.href = href;
+ }
+
+</SCRIPT>
</body></html>
<%init>
@@ -144,26 +306,29 @@ Click on a configuration value to change it.
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-my $agentnum = '';
+my $page_agent = '';
my $title;
my @menubar = ();
if ($cgi->param('agentnum') =~ /^(\d+)$/) {
- $agentnum = $1;
- my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
- die "Agent $agentnum not found!" unless $agent;
+ my $page_agentnum = $1;
+ $page_agent = qsearchs('agent', { 'agentnum' => $page_agentnum } );
+ die "Agent $page_agentnum not found!" unless $page_agent;
push @menubar, 'View all agents' => $p.'browse/agent.cgi';
- $title = 'Agent Configuration for '. $agent->agent;
+ $title = 'Agent Configuration for '. $page_agent->agent;
} else {
$title = 'Global Configuration';
}
my $conf = new FS::Conf;
-my @config_items = grep { $agentnum ? $_->per_agent : 1 }
- grep { $_->key != ~/^invoice_(html|latex|template)/ }
+my @config_items = grep { $page_agent ? $_->per_agent : 1 }
+ grep { $page_agent ? 1 : !$_->agentonly }
$conf->config_items;
+my @deleteable = qw( invoice_latexreturnaddress invoice_htmlreturnaddress );
+my %deleteable = map { $_ => 1 } @deleteable;
+
my @sections = qw(required billing username password UI session shell BIND );
push @sections, '', 'deprecated';
@@ -174,4 +339,10 @@ foreach my $section (@sections) {
@sections = grep scalar( @{ $section_items{$_} } ), @sections;
+my @all_agents = ();
+if ( $cgi->param('showagent') ) {
+ @all_agents = qsearch('agent', { 'disabled' => '' } );
+}
+warn 'all agents: '. join('-', @all_agents);
+
</%init>
diff --git a/httemplate/config/config.cgi b/httemplate/config/config.cgi
index f390c64..45d77ff 100644
--- a/httemplate/config/config.cgi
+++ b/httemplate/config/config.cgi
@@ -84,11 +84,9 @@ Setting <b><% $key %></b>
% '' => '', map { $_ => $_ } @{ $config_item->select_enum };
% } elsif ( $config_item->select_hash ) {
% if ( ref($config_item->select_hash) eq 'ARRAY' ) {
-% tie %hash, 'Tie::IxHash',
-% '' => '', @{ $config_item->select_hash };
+% tie %hash, 'Tie::IxHash', '' => '', @{ $config_item->select_hash };
% } else {
-% tie %hash, 'Tie::IxHash',
-% '' => '', %{ $config_item->select_hash };
+% tie %hash, 'Tie::IxHash', '' => '', %{ $config_item->select_hash };
% }
% } else {
% %hash = ( '' => 'WARNING: neither select_enum nor select_hash specified in Conf.pm for configuration option "'. $key. '"' );
@@ -269,9 +267,24 @@ Setting <b><% $key %></b>
<td><input type="button" value="add" onClick="doadd<% "$key$n" %>(this.form)"></td>
</tr></table>
+% } elsif ( $element_types{$type} ) {
+%
+% my %opt = ( 'element_name' => "$key$n",
+% 'empty_label' => ' ',
+% );
+% if ( $config_item->multiple ) {
+% $opt{'multiple'} = 1 if $config_item->multiple;
+% $opt{'curr_value'} = [ $conf->config($key, $agentnum) ];
+% } else {
+% $opt{'curr_value'} =
+% $conf->exists($key, $agentnum) ? $conf->config($key, $agentnum) : '';
+% }
+
+ <% include("/elements/$type.html", %opt ) %>
+
% } else {
- <font color="#ff0000">unknown type <% $type %></font>
+ <font color="#ff0000">unknown type <% $type %></font>
% }
% $n++;
@@ -291,10 +304,13 @@ Setting <b><% $key %></b>
<%once>
my $conf = new FS::Conf;
-my @config_items = grep { $_->key != ~/^invoice_(html|latex|template)/ }
- $conf->config_items;
+my @config_items = $conf->config_items;
my %confitems = map { $_->key => $_ } @config_items;
+my %element_types = map { $_ => 1 } qw(
+ select-part_svc select-part_pkg
+);
+
</%once>
<%init>
diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html
index dee4247..04af73d 100644
--- a/httemplate/docs/about.html
+++ b/httemplate/docs/about.html
@@ -1,17 +1,17 @@
-<% include('/elements/header-popup.html', 'Freeside') %>
+<% include('/elements/header-popup.html', { title=>'Freeside', nobr=>1 } ) %>
<% include('/elements/init_overlib.html') %>
<CENTER>
-<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER="0"><BR>
<H3>version <% $FS::VERSION %></H3>
</CENTER>
<CENTER>
-<FONT SIZE="-1">&copy; 2008 Freeside Internet Services, Inc.<BR>
+<FONT SIZE="-1">&copy; 2009 Freeside Internet Services, Inc.<BR>
All rights reserved.<BR>
Licensed under the terms of the<BR>
-GNU <i>Affero</i> General Public License.<BR>
+GNU <b>Affero</b> General Public License.<BR>
</FONT>
</CENTER>
<BR>
diff --git a/httemplate/docs/credits.html b/httemplate/docs/credits.html
index 3c5564d..d927722 100644
--- a/httemplate/docs/credits.html
+++ b/httemplate/docs/credits.html
@@ -24,17 +24,16 @@
<CENTER>Freeside</CENTER>
</FONT>
-<BR>
-
<CENTER>
-<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER="0"><BR>
<H3>version <% $FS::VERSION %></H3>
</CENTER>
<CENTER>
-<H3>Core team</H3>
+<H3>Core Team</H3>
Peter Bowen<BR>
+Jeremy Davis<BR>
Jeff Finucane<BR>
Jason Hall<BR>
Kristian Hoffman<BR>
@@ -42,6 +41,11 @@ Ivan Kohler<BR>
Richard Siddall<BR>
<BR>
+<H3>Core Emeritus</H3>
+Brian McCane<BR>
+Matt Simerson<BR>
+<BR>
+
<H3>Contributors</H3>
Stephen Amadei<BR>
Eric Arvidsson<BR>
@@ -74,19 +78,18 @@ Greg Kuhnert<BR>
Randall Lucas<BR>
Foteos Macrides<BR>
Roger Mangraviti<BR>
-Brian McCane<BR>
mimooh<BR>
Mack Nagashima<BR>
Matt Peterson<BR>
Luke Pfeifer<BR>
Ricardo Signes<BR>
-Matt Simerson<BR>
Steve Simitzis<BR>
Jason Spence<BR>
James Switzer<BR>
Audrey Tang<BR>
Jason Thomas<BR>
Jesse Vincent<BR>
+Johan Vromans<BR>
Mark Wells<BR>
Peter Wemm<BR>
Mark Williamson<BR>
@@ -147,7 +150,7 @@ function myHeight() {
return document.body.document.height;
else
*/
- return 1700; // approx height (add more per contributors)
+ return 1850; // approx height (add more per contributors)
}
document.body.style.overflow = 'hidden';
diff --git a/httemplate/docs/license.html b/httemplate/docs/license.html
index 5453730..fc3da69 100644
--- a/httemplate/docs/license.html
+++ b/httemplate/docs/license.html
@@ -1,12 +1,12 @@
-<% include('/elements/header-popup.html', 'Freeside') %>
+<% include('/elements/header-popup.html', { title=>'Freeside', nobr=>1 } ) %>
<CENTER>
-<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER="0"><BR>
<H3>version <% $FS::VERSION %></H3>
</CENTER>
<P>
-Copyright &copy; 2005-2008 Freeside Internet Services, Inc.<BR>
+Copyright &copy; 2005-2009 Freeside Internet Services, Inc.<BR>
Copyright &copy; 2000-2005 Ivan Kohler<BR>
Copyright &copy; 1999 Silicon Interactive Software Design<BR>
All rights reserved<BR>
@@ -100,6 +100,10 @@ terms of the BSD license.<BR>
&copy; 2005 modernmethod, inc<BR>
Perl backend version &copy; 2005 Nathan Schmidt
+<P>
+Contains code derived from eps2png by Johan Vromans, licensed under the same
+terms as Perl (GPL/Artistic).
+
<!-- artwork -->
<P>
diff --git a/httemplate/edit/REAL_cust_pkg.cgi b/httemplate/edit/REAL_cust_pkg.cgi
index b2c89c3..5752c8d 100755
--- a/httemplate/edit/REAL_cust_pkg.cgi
+++ b/httemplate/edit/REAL_cust_pkg.cgi
@@ -32,6 +32,11 @@
</TR>
<TR>
+ <TD ALIGN="right">Custom</TD>
+ <TD BGCOLOR="#ffffff"><% $part_pkg->custom %></TD>
+ </TR>
+
+ <TR>
<TD ALIGN="right">Comment</TD>
<TD BGCOLOR="#ffffff"><% $part_pkg->comment %></TD>
</TR>
@@ -41,6 +46,7 @@
<TD BGCOLOR="#ffffff"><% $cust_pkg->otaker %></TD>
</TR>
+ <& .row_edit, cust_pkg=>$cust_pkg, column=>'start_date', label=>'Start' &>
<& .row_edit, cust_pkg=>$cust_pkg, column=>'setup', label=>'Setup' &>
<& .row_edit, cust_pkg=>$cust_pkg, column=>'last_bill', label=>$last_bill_or_renewed &>
<& .row_edit, cust_pkg=>$cust_pkg, column=>'bill', label=>$next_bill_or_prepaid_until &>
diff --git a/httemplate/edit/agent.cgi b/httemplate/edit/agent.cgi
index 215542d..a0af9fa 100755
--- a/httemplate/edit/agent.cgi
+++ b/httemplate/edit/agent.cgi
@@ -46,13 +46,21 @@ Agent #<% $agent->agentnum ? $agent->agentnum : "(NEW)" %>
<TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $agent->disabled eq 'Y' ? ' CHECKED' : '' %>></TD>
</TR>
+% if ( $conf->exists('agent-invoice_template') ) {
+
<% include('/elements/tr-select-invoice_template.html',
'label' => 'Invoice template',
'field' => 'invoice_template',
'curr_value' => $agent->invoice_template,
)
%>
-
+
+% } else {
+
+ <INPUT TYPE="hidden" NAME="invoice_template" VALUE="<% $agent->invoice_template %>">
+
+% }
+
% if ( $conf->config('ticket_system') ) {
% my $default_queueid = $conf->config('ticket_system-default_queueid');
% my $default_queue = FS::TicketSystem->queue($default_queueid);
diff --git a/httemplate/edit/agent_type.cgi b/httemplate/edit/agent_type.cgi
index abf4bf8..8a6fbc2 100755
--- a/httemplate/edit/agent_type.cgi
+++ b/httemplate/edit/agent_type.cgi
@@ -20,7 +20,7 @@ Select which packages agents of this type may sell to customers<BR>
'source_obj' => $agent_type,
'link_table' => 'type_pkgs',
'target_table' => 'part_pkg',
- 'name_callback' => sub { $_[0]->pkg. ' - '. $_[0]->comment; },
+ 'name_callback' => sub { $_[0]->pkg_comment(nopkgpart => 1); },
'target_link' => $p.'edit/part_pkg.cgi?',
'disable-able' => 1,
diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi
index c9ca31f..5785a05 100755
--- a/httemplate/edit/cust_credit.cgi
+++ b/httemplate/edit/cust_credit.cgi
@@ -40,6 +40,16 @@ Credit
<TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD>
</TR>
+% if ( $conf->exists('pkg-balances') ) {
+ <% include('/elements/tr-select-cust_pkg-balances.html',
+ 'custnum' => $custnum,
+ 'cgi' => $cgi
+ )
+ %>
+% } else {
+ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="">
+% }
+
</TABLE>
<BR>
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index d3004f1..15c9f45 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -1,14 +1,18 @@
<% include('/elements/header.html',
"Customer $action",
'',
- ' onUnload="myclose()"'
+ ' onUnload="myclose()"' #hmm, in billing.html
) %>
-<% include('/elements/init_overlib.html') %>
-
<% include('/elements/error.html') %>
-<FORM NAME="topform" STYLE="margin-bottom: 0">
+<FORM NAME = "CustomerForm"
+ METHOD = "POST"
+ ACTION = "<% popurl(1) %>process/cust_main.cgi"
+%# STYLE = "margin-bottom: 0"
+%# STYLE="margin-top: 0; margin-bottom: 0">
+>
+
<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
% if ( $custnum ) {
@@ -19,101 +23,25 @@
<BR><BR>
% }
-<% &ntable("#cccccc") %>
-
-%# agent
-<% include('/elements/tr-select-agent.html',
- 'curr_value' => $cust_main->agentnum,
- 'label' => "<B>${r}Agent</B>",
- 'empty_label' => 'Select agent',
- 'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
- )
-%>
-
-%# agent_custid
-% if ( $conf->exists('cust_main-edit_agent_custid') ) {
-
- <TR>
- <TD ALIGN="right">Customer identifier</TD>
- <TD><INPUT TYPE="text" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>"></TD>
- </TR>
-
-% } else {
-
- <INPUT TYPE="hidden" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>">
-
-% }
-
-%# referral (advertising source)
-%my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
-%if ( $custnum && ! $conf->exists('editreferrals') ) {
-
- <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
-
-% } else {
-
- <% include('/elements/tr-select-part_referral.html',
- 'curr_value' => $refnum
- )
- %>
-% }
-
-
-%# referring customer
-%my $referring_cust_main = '';
-%if ( $cust_main->referral_custnum
-% and $referring_cust_main =
-% qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
-%) {
-
- <TR>
- <TD ALIGN="right">Referring customer</TD>
- <TD>
- <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
- </TD>
- </TR>
- <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
-% } elsif ( ! $conf->exists('disable_customer_referrals') ) {
-
-
- <TR>
- <TD ALIGN="right">Referring customer</TD>
- <TD>
- <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
- <% include('/elements/search-cust_main.html',
- 'field_name' => 'referral_custnum',
- )
- %>
- </TD>
- </TR>
-% } else {
-
-
- <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
-% }
-
-
-</TABLE>
-
-<!-- birthdate -->
+%# agent, agent_custid, refnum (advertising source), referral_custnum
+<% include('cust_main/top_misc.html', $cust_main, 'custnum' => $custnum ) %>
+%# birthdate
% if ( $conf->exists('cust_main-enable_birthdate') ) {
-
<BR>
- <% ntable("#cccccc", 2) %>
- <% include ('/elements/tr-input-date-field.html',
- 'birthdate',
- $cust_main->birthdate,
- 'Date of Birth',
- $conf->config('date_format') || "%m/%d/%Y",
- 1)
- %>
-
- </TABLE>
+ <% include('cust_main/birthdate.html', $cust_main) %>
+% }
+%# latitude and longitude
+% if ( $conf->exists('cust_main-require_censustract') ) {
+% my ($latitude, $longitude) = $cust_main->service_coordinates;
+% $latitude ||= $conf->config('company_latitude') || '';
+% $longitude ||= $conf->config('company_longitude') || '';
+ <INPUT NAME="latitude" TYPE="hidden" VALUE="<% $latitude |h %>">
+ <INPUT NAME="longitude" TYPE="hidden" VALUE="<% $longitude |h %>">
% }
-<!-- contact info -->
+%# contact info
% my $same_checked = '';
% my $ship_disabled = '';
@@ -128,8 +56,9 @@
% }
% }
-<BR><BR>
-Billing address
+<BR>
+<FONT SIZE="+1"><B>Billing address</B></FONT>
+
<% include('cust_main/contact.html',
'cust_main' => $cust_main,
'pre' => '',
@@ -199,7 +128,8 @@ function samechanged(what) {
</SCRIPT>
<BR>
-Service address
+<FONT SIZE="+1"><B>Service address</B></FONT>
+
(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$same_checked%>>same as billing address)
<% include('cust_main/contact.html',
'cust_main' => $cust_main,
@@ -209,528 +139,133 @@ Service address
)
%>
-
-<!-- billing info -->
-
+%# billing info
<% include( 'cust_main/billing.html', $cust_main,
'payinfo' => $payinfo,
'invoicing_list' => \@invoicing_list,
)
%>
-<% include( '/elements/xmlhttp.html',
- 'url' => $p.'misc/xmlhttp-cust_main-address_standardize.html',
- 'subs' => [ 'address_standardize' ],
- #'method' => 'POST', #could get too long?
- )
-%>
-
-<SCRIPT>
-function bottomfixup(what) {
-
- //i don't think we need to copy things between two forms anymore, modern
- //browsers are fine with DIVs inside FORMs
-
- var topvars = new Array(
- 'birthdate',
-
- 'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
-
- 'last', 'first', 'ss', 'company',
- 'address1', 'address2', 'city',
- 'county', 'state', 'zip', 'country',
- 'daytime', 'night', 'fax',
- 'stateid', 'stateid_state',
-
- 'same',
-
- 'ship_last', 'ship_first', 'ship_company',
- 'ship_address1', 'ship_address2', 'ship_city',
- 'ship_county', 'ship_state', 'ship_zip', 'ship_country',
- 'ship_daytime','ship_night', 'ship_fax',
-
- 'geocode',
-
- 'select' // XXX key
- );
-
- var layervars = new Array(
- 'payauto',
- 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
- 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
- 'paystart_month', 'paystart_year', 'payissue',
- 'payip',
- 'paid'
- );
-
- var billing_bottomvars = new Array(
- 'tax',
- 'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
- 'invoice_terms',
- 'spool_cdr',
- 'squelch_cdr'
- );
-
- for ( f=0; f < topvars.length; f++ ) {
- var field = topvars[f];
- copyelement( document.topform.elements[field],
- document.bottomform.elements[field]
- );
- }
-
- var layerform = document.topform.select.options[document.topform.select.selectedIndex].value;
- for ( f=0; f < layervars.length; f++ ) {
- var field = layervars[f];
- copyelement( document.forms[layerform].elements[field],
- document.bottomform.elements[field]
- );
- }
-
- for ( f=0; f < billing_bottomvars.length; f++ ) {
- var field = billing_bottomvars[f];
- copyelement( document.billing_bottomform.elements[field],
- document.bottomform.elements[field]
- );
- }
-
- //this part does USPS address correction
-
- // XXX should this be first and should we update the form fields that are
- // displayed???
-
- //var state_el = document.bottomform.elements['state'];
-
- //address_standardize(
- var cust_main = new Array(
- 'company', document.bottomform.elements['company'].value,
- 'address1', document.bottomform.elements['address1'].value,
- 'address2', document.bottomform.elements['address2'].value,
- 'city', document.bottomform.elements['city'].value,
- 'state', document.bottomform.elements['state'].value,
- //'state', state_el.options[ state_el.selectedIndex ].value,
- 'zip', document.bottomform.elements['zip'].value,
-
- 'ship_company', document.bottomform.elements['ship_company'].value,
- 'ship_address1', document.bottomform.elements['ship_address1'].value,
- 'ship_address2', document.bottomform.elements['ship_address2'].value,
- 'ship_city', document.bottomform.elements['ship_city'].value,
- 'ship_state', document.bottomform.elements['ship_state'].value,
- //'ship_state', state_el.options[ state_el.selectedIndex ].value,
- 'ship_zip', document.bottomform.elements['ship_zip'].value
- );
-
- address_standardize( cust_main, update_address );
-
-}
-
-var standardize_address;
-
-function update_address(arg) {
-
- var argsHash = eval('(' + arg + ')');
-
- var changed = argsHash['address_standardized'];
- var ship_changed = argsHash['ship_address_standardized'];
- var error = argsHash['error'];
- var ship_error = argsHash['ship_error'];
-
- //yay closures
- standardize_address = function () {
-
- if ( changed ) {
- document.bottomform.elements['company'].value = argsHash['new_company'];
- document.bottomform.elements['address1'].value = argsHash['new_address1'];
- document.bottomform.elements['address2'].value = argsHash['new_address2'];
- document.bottomform.elements['city'].value = argsHash['new_city'];
- document.bottomform.elements['state'].value = argsHash['new_state'];
- //'state', state_el.options[ state_el.selectedIndex ].value,
- document.bottomform.elements['zip'].value = argsHash['new_zip'];
- }
-
- if ( ship_changed ) {
- document.bottomform.elements['ship_company'].value = argsHash['new_ship_company'];
- document.bottomform.elements['ship_address1'].value = argsHash['new_ship_address1'];
- document.bottomform.elements['ship_address2'].value = argsHash['new_ship_address2'];
- document.bottomform.elements['ship_city'].value = argsHash['new_ship_city'];
- document.bottomform.elements['ship_state'].value = argsHash['new_ship_state'];
- //'state', state_el.options[ state_el.selectedIndex ].value,
- document.bottomform.elements['ship_zip'].value = argsHash['new_ship_zip'];
- }
-
- }
-
-% if ( $conf->exists('enable_taxproducts') ) {
-
- if ( <% $taxpre %>error ) {
-
- if ( document.bottomform.elements['country'].value == 'CA' ||
- document.bottomform.elements['country'].value == 'US'
- )
- {
-
- var url = "cust_main/choose_tax_location.html?data_vendor=cch-zip;city="+document.bottomform.elements['city'].value+";state="+document.bottomform.elements['state'].value+";zip="+document.bottomform.elements['zip'].value+";country="+document.bottomform.elements['country'].value+";";
- // popup a chooser
- OLgetAJAX( url, update_geocode, 300 );
-
- } else {
-
- document.bottomform.elements['geocode'].value = 'DEFAULT';
- document.bottomform.submit();
-
- }
+% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
+% if (!$ro_comments || $cust_main->comments) {
- } else
+ <BR>Comments
+ <% &ntable("#cccccc") %>
+ <TR>
+ <TD>
+ <TEXTAREA NAME = "comments"
+ COLS = 80
+ ROWS = 5
+ WRAP = "HARD"
+ <% $ro_comments %>
+ ><% $cust_main->comments %></TEXTAREA>
+ </TD>
+ </TR>
+ </TABLE>
% }
- if ( changed || ship_changed ) {
-
-% if ( $conf->exists('cust_main-auto_standardize_address') ) {
-
- standardize_address();
- document.bottomform.submit();
-
-% } else {
-
- // popup a confirmation popup
-
- var confirm_change =
- '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
- '<TABLE>';
-
- if ( changed ) {
-
- confirm_change = confirm_change +
- '<TR><TH>Entered billing address</TH>' +
- '<TH>Standardized billing address</TH></TR>';
- // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
- if ( argsHash['company'] || argsHash['new_company'] ) {
- confirm_change = confirm_change +
- '<TR><TD>' + argsHash['company'] +
- '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
- }
-
- confirm_change = confirm_change +
- '<TR><TD>' + argsHash['address1'] +
- '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
- '<TR><TD>' + argsHash['address2'] +
- '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
- '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + ' ' + argsHash['zip'] +
- '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + ' ' + argsHash['new_zip'] + '</TD></TR>' +
- '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
- }
-
- if ( ship_changed ) {
-
- confirm_change = confirm_change +
- '<TR><TH>Entered service address</TH>' +
- '<TH>Standardized service address</TH></TR>';
- // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
- if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
- confirm_change = confirm_change +
- '<TR><TD>' + argsHash['ship_company'] +
- '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
- }
-
- confirm_change = confirm_change +
- '<TR><TD>' + argsHash['ship_address1'] +
- '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
- '<TR><TD>' + argsHash['ship_address2'] +
- '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
- '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + ' ' + argsHash['ship_zip'] +
- '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + ' ' + argsHash['new_ship_zip'] + '</TD></TR>' +
- '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
- }
-
- var addresses = 'address';
- var height = 268;
- if ( changed && ship_changed ) {
- addresses = 'addresses';
- height = 396; // #what
- }
-
- confirm_change = confirm_change +
- '<TR><TD>' +
- '<BUTTON TYPE="button" onClick="document.bottomform.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' +
- '</TD><TD>' +
- '<BUTTON TYPE="button" onClick="standardize_address(); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' +
- '</TD></TR>' +
- '<TR><TD COLSPAN=2 ALIGN="center">' +
- '<BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
-
- '</TABLE></CENTER>';
-
- overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-% }
-
- } else {
-
- document.bottomform.submit();
+% unless ( $custnum ) {
- }
-
-}
-
-function update_geocode() {
-
- //yay closures
- set_geocode = function (what) {
-
- //alert(what.options[what.selectedIndex].value);
- var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
- document.bottomform.elements['city'].value = argsHash['city'];
- document.bottomform.elements['state'].value = argsHash['state'];
- document.bottomform.elements['zip'].value = argsHash['zip'];
- document.bottomform.elements['geocode'].value = argsHash['geocode'];
-
- }
-
- // popup a chooser
-
- overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-}
+ <% include('cust_main/first_pkg.html', $cust_main,
+ 'pkgpart_svcpart' => $pkgpart_svcpart,
+ #svc_acct
+ 'username' => $username,
+ 'password' => $password,
+ 'popnum' => $popnum,
+ 'saved_domsvc' => $saved_domsvc,
+ %svc_phone,
+ )
+ %>
-function copyelement(from, to) {
- if ( from == undefined ) {
- to.value = '';
- } else if ( from.type == 'select-one' ) {
- to.value = from.options[from.selectedIndex].value;
- //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
- } else if ( from.type == 'checkbox' ) {
- if ( from.checked ) {
- to.value = from.value;
- } else {
- to.value = '';
- }
- } else {
- if ( from.value == undefined ) {
- to.value = '';
- } else {
- to.value = from.value;
- }
- }
- //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
-}
+% }
-</SCRIPT>
+<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
-<FORM ACTION="<% popurl(1) %>process/cust_main.cgi" METHOD=POST NAME="bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+%# cust_main/bottomfixup.js
% foreach my $hidden (
-% 'birthdate',
-%
-% 'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
-% 'last', 'first', 'ss', 'company',
-% 'address1', 'address2', 'city',
-% 'county', 'state', 'zip', 'country',
-% 'daytime', 'night', 'fax',
-% 'stateid', 'stateid_state',
-%
-% 'same',
-%
-% 'ship_last', 'ship_first', 'ship_company',
-% 'ship_address1', 'ship_address2', 'ship_city',
-% 'ship_county', 'ship_state', 'ship_zip', 'ship_country',
-% 'ship_daytime','ship_night', 'ship_fax',
-%
-% 'geocode',
-%
-% 'select', #XXX key
-%
-% 'payauto',
-% 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
-% 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
-% 'paystart_month', 'paystart_year', 'payissue',
-% 'payip',
-% 'paid',
-%
-% 'tax',
-% 'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
-% 'invoice_terms',
-% 'spool_cdr',
-% 'squelch_cdr'
-% ) {
-%
-
- <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
-% }
-%
-% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
-% if (!$ro_comments || $cust_main->comments) {
-
-<BR>Comments
-<% &ntable("#cccccc") %>
- <TR>
- <TD>
- <TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments" <%$ro_comments%>><% $cust_main->comments %></TEXTAREA>
- </TD>
- </TR>
-</TABLE>
-%
-% }
-%
-%unless ( $custnum ) {
-% # pry the wrong place for this logic. also pretty expensive
-% #use FS::part_pkg;
-%
-% #false laziness, copied from FS::cust_pkg::order
-% my $pkgpart;
-% my $agentnum = '';
-% my @agents = $FS::CurrentUser::CurrentUser->agents;
-% if ( scalar(@agents) == 1 ) {
-% # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
-% $pkgpart = $agents[0]->pkgpart_hashref;
-% $agentnum = $agents[0]->agentnum;
-% } else {
-% #can't know (agent not chosen), so, allow all
-% $agentnum = 'all';
-% my %typenum;
-% foreach my $agent ( @agents ) {
-% next if $typenum{$agent->typenum}++;
-% $pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
-% }
-% }
-% #eslaf
-%
-% my @part_pkg = grep { $_->svcpart('svc_acct')
-% && ( $pkgpart->{ $_->pkgpart }
-% || $agentnum eq 'all'
-% || ( $agentnum ne 'all'
-% && $agentnum
-% && $_->agentnum
-% && $_->agentnum == $agentnum
-% )
-% )
-% }
-% qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
-%
-% if ( @part_pkg ) {
-%
-% # print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"),
-% #apiabuse & undesirable wrapping
-%
-%
-
- <BR>First package
- <% ntable("#cccccc") %>
-
- <TR>
- <TD COLSPAN=2>
- <% include('cust_main/select-domain.html',
- 'pkgparts' => \@part_pkg,
- 'saved_pkgpart' => $saved_pkgpart,
- 'saved_domsvc' => $saved_domsvc,
- )
- %>
- </TD>
- </TR>
-%
-% #false laziness: (mostly) copied from edit/svc_acct.cgi
-% #$ulen = $svc_acct->dbdef_table->column('username')->length;
-% my $ulen = dbdef->table('svc_acct')->column('username')->length;
-% my $ulen2 = $ulen+2;
-% my $passwordmax = $conf->config('passwordmax') || 8;
-% my $pmax2 = $passwordmax + 2;
-%
-
-
- <TR>
- <TD ALIGN="right">Username</TD>
- <TD>
- <INPUT TYPE="text" NAME="username" VALUE="<% $username %>" SIZE=<% $ulen2 %> MAXLENGTH=<% $ulen %>>
- </TD>
- </TR>
-
- <TR>
- <TD ALIGN="right">Domain</TD>
- <TD>
- <SELECT NAME="domsvc">
- <OPTION>(none)</OPTION>
- </SELECT>
- </TD>
- </TR>
-
- <TR>
- <TD ALIGN="right">Password</TD>
- <TD>
- <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $passwordmax %>>
- (blank to generate)
- </TD>
- </TR>
-
- <TR>
- <TD ALIGN="right">Access number</TD>
- <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
- </TR>
- </TABLE>
-% }
+% 'payauto',
+% 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+% 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+% 'paystart_month', 'paystart_year', 'payissue',
+% 'payip',
+% 'paid',
+% ) {
+ <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
% }
+<% include('cust_main/bottomfixup.html') %>
-<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
-<BR>
-<INPUT TYPE="button" NAME="submitButton" ID="submitButton" VALUE="<% $custnum ? "Apply Changes" : "Add Customer" %>" onClick="document.bottomform.submitButton.disabled=true; bottomfixup(this.form);">
<BR>
+<INPUT TYPE = "button"
+ NAME = "submitButton"
+ ID = "submitButton"
+ VALUE = "<% $custnum ? "Apply Changes" : "Add Customer" %>"
+ onClick = "this.disabled=true; bottomfixup(this.form);"
+>
</FORM>
<% include('/elements/footer.html') %>
<%init>
-die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
-
-#for misplaced logic below
-#use FS::part_pkg;
+my $curuser = $FS::CurrentUser::CurrentUser;
-#for false laziness below (now more properly lazy)
-#use FS::svc_acct_pop;
-
-#for (other) false laziness below
-#use FS::agent;
-#use FS::type_pkgs;
+#probably redundant given the checks below...
+die "access denied"
+ unless $curuser->access_right('New customer')
+ || $curuser->access_right('Edit customer');
my $conf = new FS::Conf;
-my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
#get record
-my($custnum, $username, $password, $popnum, $cust_main, $saved_pkgpart, $saved_domsvc);
-my(@invoicing_list);
-my ($ss,$stateid,$payinfo);
+my($custnum, $cust_main, $ss, $stateid, $payinfo, @invoicing_list);
my $same = '';
+my $pkgpart_svcpart = ''; #first_pkg
+my($username, $password, $popnum, $saved_domsvc) = ( '', '', 0, 0 ); #svc_acct
+my %svc_phone = ();
+
if ( $cgi->param('error') ) {
+
$cust_main = new FS::cust_main ( {
map { $_, scalar($cgi->param($_)) } fields('cust_main')
} );
+
$custnum = $cust_main->custnum;
- $saved_domsvc = $cgi->param('domsvc') || '';
- if ( $saved_domsvc =~ /^(\d+)$/ ) {
- $saved_domsvc = $1;
- } else {
- $saved_domsvc = '';
- }
- $saved_pkgpart = $cgi->param('pkgpart_svcpart') || '';
- if ( $saved_pkgpart =~ /^(\d+)_/ ) {
- $saved_pkgpart = $1;
- } else {
- $saved_pkgpart = '';
- }
- $username = $cgi->param('username');
- $password = $cgi->param('_password');
- $popnum = $cgi->param('popnum');
+
+ die "access denied"
+ unless $curuser->access_right($custnum ? 'Edit customer' : 'New customer');
+
@invoicing_list = split( /\s*,\s*/, $cgi->param('invoicing_list') );
$same = $cgi->param('same');
$cust_main->setfield('paid' => $cgi->param('paid')) if $cgi->param('paid');
$ss = $cust_main->ss; # don't mask an entered value on errors
$stateid = $cust_main->stateid; # don't mask an entered value on errors
$payinfo = $cust_main->payinfo; # don't mask an entered value on errors
+
+ $pkgpart_svcpart = $cgi->param('pkgpart_svcpart') || '';
+
+ #svc_acct
+ $username = $cgi->param('username');
+ $password = $cgi->param('_password');
+ $popnum = $cgi->param('popnum');
+ $saved_domsvc = $cgi->param('domsvc') || '';
+ if ( $saved_domsvc =~ /^(\d+)$/ ) {
+ $saved_domsvc = $1;
+ } else {
+ $saved_domsvc = '';
+ }
+
+ #svc_phone
+ $svc_phone{$_} = $cgi->param($_)
+ foreach qw( countrycode phonenum sip_password pin phone_name );
+
} elsif ( $cgi->keywords ) { #editing
+
+ die "access denied"
+ unless $curuser->access_right('Edit customer');
+
my( $query ) = $cgi->keywords;
$query =~ /^(\d+)$/;
$custnum=$1;
@@ -741,31 +276,27 @@ if ( $cgi->param('error') ) {
$paycvv =~ s/./*/g;
$cust_main->paycvv($paycvv);
}
- $saved_pkgpart = 0;
- $saved_domsvc = 0;
- $username = '';
- $password = '';
- $popnum = 0;
@invoicing_list = $cust_main->invoicing_list;
$ss = $cust_main->masked('ss');
$stateid = $cust_main->masked('stateid');
$payinfo = $cust_main->paymask;
-} else {
+
+} else { #new customer
+
+ die "access denied"
+ unless $curuser->access_right('New customer');
+
$custnum='';
$cust_main = new FS::cust_main ( {} );
$cust_main->otaker( &getotaker );
$cust_main->referral_custnum( $cgi->param('referral_custnum') );
- $saved_pkgpart = 0;
- $saved_domsvc = 0;
- $username = '';
- $password = '';
- $popnum = 0;
@invoicing_list = ();
push @invoicing_list, 'POST'
unless $conf->exists('disablepostalinvoicedefault');
$ss = '';
$stateid = '';
$payinfo = '';
+
}
my $error = $cgi->param('error');
diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html
index 8724db9..ad83778 100644
--- a/httemplate/edit/cust_main/billing.html
+++ b/httemplate/edit/cust_main/billing.html
@@ -1,18 +1,15 @@
%if ( $payby_default eq 'HIDE' ) {
%
% $cust_main->payby('BILL') unless $cust_main->payby;
+% my $payby = $cust_main->payby;
- <INPUT TYPE="hidden" NAME="select" VALUE="<% $cust_main->payby %>">
-
- </FORM>
-
- <FORM NAME="<% $cust_main->payby %>" STYLE="margin-top: 0; margin-bottom: 0">
+ <INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
- <INPUT TYPE="hidden" NAME="payinfo" VALUE="<% $cust_main->paymask %>">
+ <INPUT TYPE="hidden" NAME="<%$payby%>_payinfo" VALUE="<% $cust_main->paymask %>">
% foreach my $field (qw( payname paycvv paystart_month paystart_year payissue payip paytype paystate )) {
- <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $cust_main->getfield($field) %>">
+ <INPUT TYPE="hidden" NAME="<% $payby.'_'.$field %>" VALUE="<% $cust_main->get($field) %>">
% }
@@ -27,24 +24,18 @@
% die "unrecognized expiration date format: $date";
% }
- <INPUT TYPE="hidden" NAME="exp_month" VALUE="<% $mon %>">
- <INPUT TYPE="hidden" NAME="exp_year" VALUE="<% $year %>">
-
- </FORM>
-
- <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+ <INPUT TYPE="hidden" NAME="<%$payby%>_exp_month" VALUE="<% $mon %>">
+ <INPUT TYPE="hidden" NAME="<%$payby%>_exp_year" VALUE="<% $year %>">
<INPUT TYPE="hidden" NAME="tax" VALUE="<% $cust_main->tax %>">
<INPUT TYPE="hidden" NAME="invoicing_list" VALUE="<% join(', ', @invoicing_list) %>">
- </FORM>
-
% } else {
%
% my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
- <BR>Billing information
+ <BR><FONT SIZE="+1"><B>Billing information</B></FONT>
<% &ntable("#cccccc") %>
<TR>
@@ -128,13 +119,13 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Card number </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
% '<TD WIDTH="408">'.
%
% include('/elements/select-month_year.html',
-% 'prefix' => 'exp',
+% 'prefix' => 'CARD_exp',
% 'selected_date' =>
% ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->paydate : '' ),
% ).
@@ -145,14 +136,14 @@
%
% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
% qq!</TD>!.
-% '<TD WIDTH="408"><INPUT TYPE="text" NAME="paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
+% '<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
%
%
% qq!<TR><TD ALIGN="right" WIDTH="200"><SPAN ID="paystart_label" $text_disabled>Start date </SPAN></TD>!.
% '<TD WIDTH="408">'.
%
% include('/elements/select-month_year.html',
-% 'prefix' => 'paystart',
+% 'prefix' => 'CARD_paystart',
% 'disabled' => $disabled,
% 'empty_option' => 1,
% 'start_year' => 2000,
@@ -167,12 +158,12 @@
% ).
%
% qq!<SPAN ID="payissue_label" $text_disabled> or Issue number </SPAN>!.
-% '<INPUT TYPE="text" NAME="payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
+% '<INPUT TYPE="text" NAME="CARD_payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Exact name on card </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
%
-% qq!<TR><TD COLSPAN=2 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCRD' ? '' : 'CHECKED' ). '> Charge future payments to this card automatically</TD></TR>'.
+% qq!<TR><TD COLSPAN=2 WIDTH="608"><INPUT TYPE="checkbox" NAME="CARD_payauto" !. ( $payby eq 'DCRD' ? '' : 'CHECKED' ). '> Charge future payments to this card automatically</TD></TR>'.
%
% '</TABLE>',
%
@@ -181,21 +172,21 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Account number </TD>!.
-% qq!<TD><INPUT TYPE="text" SIZE=12 NAME="payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
-% qq!<TD ALIGN="right">Type</TD><TD><SELECT NAME="paytype">!.
+% qq!<TD><INPUT TYPE="text" SIZE=12 NAME="CHEK_payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
+% qq!<TD ALIGN="right">Type</TD><TD><SELECT NAME="CHEK_paytype">!.
% join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes).
% qq!</SELECT></TD></TR>!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}ABA/Routing number </TD>!.
-% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!" SIZE=10 MAXLENGTH=9> !.
+% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="CHEK_payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!" SIZE=10 MAXLENGTH=9> !.
% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
% qq!</TD></TR>!.
%
-% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+% qq!<INPUT TYPE="hidden" NAME="CHEK_exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="CHEK_exp_year" VALUE="2037">!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Bank name </TD>!.
-% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="CHEK_payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
% ( $conf->exists('show_bankstate') ?
% qq!<TR><TD ALIGN="right" WIDTH="200">$paystate_label</TD>!.
% qq!<TD COLSPAN="3" WIDTH="408">!.
@@ -203,14 +194,14 @@
% 'empty' => '(choose)',
% 'state' => $cust_main->paystate,
% 'country' => $cust_main->country,
-% 'prefix' => 'pay',
+% 'prefix' => 'CHEK_pay',
% ). "</TD></TR>"
-% : '<INPUT TYPE="hidden" NAME="paystate" VALUE="'.
+% : '<INPUT TYPE="hidden" NAME="CHEK_paystate" VALUE="'.
% $cust_main->paystate. '">'
% ).
%
%
-% qq!<TR><TD COLSPAN=4 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCHK' ? '' : 'CHECKED' ). '> Charge future payments to this electronic check automatically</TD></TR>'.
+% qq!<TR><TD COLSPAN=4 WIDTH="608"><INPUT TYPE="checkbox" NAME="CHEK_payauto" !. ( $payby eq 'DCHK' ? '' : 'CHECKED' ). '> Charge future payments to this electronic check automatically</TD></TR>'.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -223,11 +214,11 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Phone number </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="LECB_payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
%
-% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
-% qq!<INPUT TYPE="hidden" NAME="payname" VALUE="">!.
+% qq!<INPUT TYPE="hidden" NAME="LECB_exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="LECB_exp_year" VALUE="2037">!.
+% qq!<INPUT TYPE="hidden" NAME="LECB_payname" VALUE="">!.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -243,13 +234,13 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">P.O. </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
%
-% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+% qq!<INPUT TYPE="hidden" NAME="BILL_exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="BILL_exp_year" VALUE="2037">!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">Attention </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -264,13 +255,13 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Approved by </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE=""></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""></TD></TR>!.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
% '<TD WIDTH="408">'.
%
% include('/elements/select-month_year.html',
-% 'prefix' => 'exp',
+% 'prefix' => 'COMP_exp',
% 'selected_date' =>
% ( $payby eq 'COMP' ? $cust_main->paydate : '' ),
% ).
@@ -290,7 +281,7 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CASH_paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -306,7 +297,7 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="WEST_paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -322,7 +313,7 @@
% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
%
% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="MCRD_paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
%
% '<TR><TD>&nbsp;</TD></TR>'.
% '<TR><TD>&nbsp;</TD></TR>'.
@@ -336,57 +327,51 @@
% );
%
% #this should use FS::payby
-% my %allopt = (
-% 'CARD' => 'Credit card',
-% 'CHEK' => 'Electronic check',
-% 'LECB' => 'Phone bill billing',
-% 'BILL' => 'Billing',
-% 'CASH' => 'Cash', # initial payment, then billing',
-% 'WEST' => 'Western Union', # initial payment, then billing',
-% 'MCRD' => 'Manual credit card', # initial payment, then billing',
-% 'COMP' => 'Complimentary',
-% );
-% if ( $cust_main->custnum ) { #don't offer CASH/WEST/MCRD initial payment types
-% # when editing customer
+% my @allopt = qw( CARD CHEK LECB BILL CASH WEST MCRD COMP );
+%
+% my %allopt = map { $_ => FS::payby->shortname($_) } @allopt;
+%
+% if ( $cust_main->custnum ) {
+% #don't offer CASH/WEST/MCRD initial payment types when editing customer
% delete $allopt{$_} for qw(CASH WEST MCRD);
% }
%
-% tie my %options, 'Tie::IxHash',
-% map { $_ => $allopt{$_} }
-% grep { exists $allopt{$_} }
-% @payby;
+% my @options = grep exists( $allopt{$_} ), @payby;
%
% my %payby2option = (
-% ( map { $_ => $_ } keys %options ),
+% ( map { $_ => $_ } @options ),
% 'DCRD' => 'CARD',
% 'DCHK' => 'CHEK',
% );
-%
-% my $widget = new HTML::Widgets::SelectLayers(
-% 'options' => \%options,
-% #'form_name' => 'dummy',
-% #'form_action' => 'nothingyet',
-% #chops bottom of page in IE# 'under_position' => 'absolute',
-% 'html_between' => '</TD></TR></TABLE>',
-% 'selected_layer' => $payby2option{$payby || $payby_default || $payby[0] },
-% 'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
-% );
-%
-%
-
-
- <TD WIDTH="408"><% $widget->html %>
- <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+ <TD WIDTH="408">
+ <% include( '/elements/selectlayers.html',
+ 'field' => 'payby',
+ 'curr_value' => $payby2option{$payby || $payby_default || $payby[0] },
+ 'options' => \@options,
+ 'labels' => \%allopt,
+ 'html_between' => '</TD></TR></TABLE>',
+ 'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
+ )
+ %>
<% &ntable("#cccccc") %>
<TR><TD>&nbsp;</TD></TR>
+% my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
+
<TR>
- <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="tax" VALUE="Y" <% $cust_main->tax eq "Y" ? 'CHECKED' : '' %>> Tax Exempt</TD>
+ <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="tax" VALUE="Y" <% $cust_main->tax eq "Y" ? 'CHECKED' : '' %>> Tax Exempt<% @exempt_groups ? ' (all taxes)' : '' %></TD>
</TR>
+% foreach my $exempt_group ( @exempt_groups ) {
+% #escape $exempt_group for NAME
+ <TR>
+ <TD WIDTH="608" COLSPAN="2">&nbsp;&nbsp;<INPUT TYPE="checkbox" NAME="tax_<% $exempt_group %>" VALUE="Y" <% $cust_main->tax_exemption($exempt_group) ? 'CHECKED' : '' %>> Tax Exempt (<% $exempt_group %> taxes)<TD>
+ </TR>
+% }
+
% unless ( $conf->exists('emailinvoiceonly') ) {
<TR>
@@ -426,14 +411,10 @@
<TR>
<TD ALIGN="right" WIDTH="200">Invoice terms </TD>
<TD WIDTH="408">
- <SELECT NAME="invoice_terms">
- <OPTION VALUE="">Default (<% $conf->config('invoice_default_terms') || 'Payable upon receipt' %>)
-% foreach my $term ( 'Payable upon receipt',
-% ( map "Net $_", 0, 10, 15, 30, 45, 60 ),
-% ) {
- <OPTION VALUE="<% $term %>" <% $cust_main->invoice_terms eq $term ? ' SELECTED' : '' %>><% $term %>
-% }
- </SELECT>
+ <% include('/elements/select-terms.html',
+ 'curr_value' => $cust_main->invoice_terms,
+ )
+ %>
</TD>
</TR>
@@ -442,22 +423,40 @@
<TD COLSPAN="2"><INPUT TYPE="checkbox" NAME="spool_cdr" VALUE="Y" <% $cust_main->spool_cdr eq "Y" ? 'CHECKED' : '' %>> Spool CDRs</TD>
</TR>
% } else {
-
<INPUT TYPE="hidden" NAME="spool_cdr" VALUE="<% $cust_main->spool_cdr %>">
-% }
+% }
% if ( $conf->exists('voip-cust_cdr_squelch') ) {
<TR>
<TD COLSPAN="2"><INPUT TYPE="checkbox" NAME="squelch_cdr" VALUE="Y" <% $cust_main->squelch_cdr eq "Y" ? 'CHECKED' : '' %>> Omit CDRs from invoices</TD>
</TR>
% } else {
-
<INPUT TYPE="hidden" NAME="squelch_cdr" VALUE="<% $cust_main->squelch_cdr %>">
-% }
+% }
- </TABLE>
+% if ( $conf->exists('voip-cust_email_csv_cdr') ) {
+ <TR>
+ <TD COLSPAN="2"><INPUT TYPE="checkbox" NAME="email_csv_cdr" VALUE="Y" <% $cust_main->email_csv_cdr eq "Y" ? 'CHECKED' : '' %>> Attach CDRs as CSV to emailed invoices</TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="email_csv_cdr" VALUE="<% $cust_main->email_csv_cdr %>">
+% }
- </FORM>
+% if ( $show_term || $cust_main->cdr_termination_percentage ) {
+ <TR>
+ <TD ALIGN="right">CDR termination settlement</TD>
+ <TD><INPUT TYPE = "text"
+ NAME = "cdr_termination_percentage"
+ SIZE = 6
+ VALUE = "<% $cust_main->cdr_termination_percentage %>"
+ STYLE = "text-align:right;"
+ ><B>%</B></TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="cdr_termination_percentage" VALUE="<% $cust_main->cdr_termination_percentage %>">
+% }
+
+ </TABLE>
<% $r %> required fields
% }
@@ -481,4 +480,13 @@ my @payby = grep /\w/, $conf->config('payby');
@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
unless @payby;
+my $show_term = '';
+if ( $cust_main->custnum ) {
+ #false laziness w/view/cust_main/billing.html
+ my $term_sql = "SELECT COUNT(*) FROM cust_pkg LEFT JOIN part_pkg USING ( pkgpart ) WHERE custnum = ? AND plan = 'cdr_termination' LIMIT 1";
+ my $term_sth = dbh->prepare($term_sql) or die dbh->errstr;
+ $term_sth->execute($cust_main->custnum) or die $term_sth->errstr;
+ $show_term = $term_sth->fetchrow_arrayref->[0];
+}
+
</%init>
diff --git a/httemplate/edit/cust_main/birthdate.html b/httemplate/edit/cust_main/birthdate.html
new file mode 100644
index 0000000..415aba3
--- /dev/null
+++ b/httemplate/edit/cust_main/birthdate.html
@@ -0,0 +1,15 @@
+<% ntable("#cccccc", 2) %>
+ <% include ('/elements/tr-input-date-field.html',
+ 'birthdate',
+ $cust_main->birthdate,
+ 'Date of Birth',
+ $conf->config('date_format') || "%m/%d/%Y",
+ 1)
+ %>
+</TABLE>
+<%init>
+
+my( $cust_main, %opt ) = @_;
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/cust_main/bottomfixup.html b/httemplate/edit/cust_main/bottomfixup.html
new file mode 100644
index 0000000..1b29c67
--- /dev/null
+++ b/httemplate/edit/cust_main/bottomfixup.html
@@ -0,0 +1,19 @@
+<% include('/elements/init_overlib.html') %>
+
+<% include( '/elements/xmlhttp.html',
+ 'url' => $p.'misc/xmlhttp-cust_main-address_standardize.html',
+ 'subs' => [ 'address_standardize' ],
+ #'method' => 'POST', #could get too long?
+ )
+%>
+
+<% include( '/elements/xmlhttp.html',
+ 'url' => $p.'misc/xmlhttp-cust_main-censustract.html',
+ 'subs' => [ 'censustract' ],
+ #'method' => 'POST', #could get too long?
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+ <% include('bottomfixup.js') %>
+</SCRIPT>
diff --git a/httemplate/edit/cust_main/bottomfixup.js b/httemplate/edit/cust_main/bottomfixup.js
new file mode 100644
index 0000000..1a06d94
--- /dev/null
+++ b/httemplate/edit/cust_main/bottomfixup.js
@@ -0,0 +1,398 @@
+function bottomfixup(what) {
+
+%# ../cust_main.cgi
+ var layervars = new Array(
+ 'payauto',
+ 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+ 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+ 'paystart_month', 'paystart_year', 'payissue',
+ 'payip',
+ 'paid'
+ );
+
+ var cf = document.CustomerForm;
+ var payby = cf.payby.options[cf.payby.selectedIndex].value;
+ for ( f=0; f < layervars.length; f++ ) {
+ var field = layervars[f];
+ copyelement( cf.elements[payby + '_' + field],
+ cf.elements[field]
+ );
+ }
+
+ //this part does USPS address correction
+
+ // XXX should this be first and should we update the form fields that are
+ // displayed???
+
+ var cf = document.CustomerForm;
+
+ var state_el = cf.elements['state'];
+ var ship_state_el = cf.elements['ship_state'];
+
+ //address_standardize(
+ var cust_main = new Array(
+ 'company', cf.elements['company'].value,
+ 'address1', cf.elements['address1'].value,
+ 'address2', cf.elements['address2'].value,
+ 'city', cf.elements['city'].value,
+ 'state', state_el.options[ state_el.selectedIndex ].value,
+ 'zip', cf.elements['zip'].value,
+
+ 'ship_company', cf.elements['ship_company'].value,
+ 'ship_address1', cf.elements['ship_address1'].value,
+ 'ship_address2', cf.elements['ship_address2'].value,
+ 'ship_city', cf.elements['ship_city'].value,
+ 'ship_state', ship_state_el.options[ ship_state_el.selectedIndex ].value,
+ 'ship_zip', cf.elements['ship_zip'].value
+ );
+
+ address_standardize( cust_main, update_address );
+
+}
+
+var standardize_address;
+
+function update_address(arg) {
+
+ var argsHash = eval('(' + arg + ')');
+
+ var changed = argsHash['address_standardized'];
+ var ship_changed = argsHash['ship_address_standardized'];
+ var error = argsHash['error'];
+ var ship_error = argsHash['ship_error'];
+
+
+ //yay closures
+ standardize_address = function () {
+
+ var cf = document.CustomerForm;
+ var state_el = cf.elements['state'];
+ var ship_state_el = cf.elements['ship_state'];
+
+ if ( changed ) {
+ cf.elements['company'].value = argsHash['new_company'];
+ cf.elements['address1'].value = argsHash['new_address1'];
+ cf.elements['address2'].value = argsHash['new_address2'];
+ cf.elements['city'].value = argsHash['new_city'];
+ setselect(cf.elements['state'], argsHash['new_state']);
+ cf.elements['zip'].value = argsHash['new_zip'];
+ }
+
+ if ( ship_changed ) {
+ cf.elements['ship_company'].value = argsHash['new_ship_company'];
+ cf.elements['ship_address1'].value = argsHash['new_ship_address1'];
+ cf.elements['ship_address2'].value = argsHash['new_ship_address2'];
+ cf.elements['ship_city'].value = argsHash['new_ship_city'];
+ setselect(cf.elements['ship_state'], argsHash['new_ship_state']);
+ cf.elements['ship_zip'].value = argsHash['new_ship_zip'];
+ }
+
+ post_standardization();
+
+ }
+
+
+
+ if ( changed || ship_changed ) {
+
+% if ( $conf->exists('cust_main-auto_standardize_address') ) {
+
+ standardize_address();
+
+% } else {
+
+ // popup a confirmation popup
+
+ var confirm_change =
+ '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
+ '<TABLE>';
+
+ if ( changed ) {
+
+ confirm_change = confirm_change +
+ '<TR><TH>Entered billing address</TH>' +
+ '<TH>Standardized billing address</TH></TR>';
+ // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ if ( argsHash['company'] || argsHash['new_company'] ) {
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['company'] +
+ '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['address1'] +
+ '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['address2'] +
+ '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + ' ' + argsHash['zip'] +
+ '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + ' ' + argsHash['new_zip'] + '</TD></TR>' +
+ '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ }
+
+ if ( ship_changed ) {
+
+ confirm_change = confirm_change +
+ '<TR><TH>Entered service address</TH>' +
+ '<TH>Standardized service address</TH></TR>';
+ // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['ship_company'] +
+ '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['ship_address1'] +
+ '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['ship_address2'] +
+ '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + ' ' + argsHash['ship_zip'] +
+ '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + ' ' + argsHash['new_ship_zip'] + '</TD></TR>' +
+ '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ }
+
+ var addresses = 'address';
+ var height = 268;
+ if ( changed && ship_changed ) {
+ addresses = 'addresses';
+ height = 396; // #what
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' +
+ '<BUTTON TYPE="button" onClick="post_standardization();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' +
+ '</TD><TD>' +
+ '<BUTTON TYPE="button" onClick="standardize_address();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' +
+ '</TD></TR>' +
+ '<TR><TD COLSPAN=2 ALIGN="center">' +
+ '<BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+
+ '</TABLE></CENTER>';
+
+ overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+% }
+
+ } else {
+
+ post_standardization();
+
+ }
+
+
+}
+
+function post_standardization() {
+
+ var cf = document.CustomerForm;
+
+% if ( $conf->exists('enable_taxproducts') ) {
+
+ if ( new String(cf.elements['<% $taxpre %>zip'].value).length < 10 )
+ {
+
+ var country_el = cf.elements['<% $taxpre %>country'];
+ var country = country_el.options[ country_el.selectedIndex ].value;
+ var geocode = cf.elements['geocode'].value;
+
+ if ( country == 'CA' || country == 'US' ) {
+
+ var state_el = cf.elements['<% $taxpre %>state'];
+ var state = state_el.options[ state_el.selectedIndex ].value;
+
+ var url = "cust_main/choose_tax_location.html" +
+ "?data_vendor=cch-zip" +
+ ";city=" + cf.elements['<% $taxpre %>city'].value +
+ ";state=" + state +
+ ";zip=" + cf.elements['<% $taxpre %>zip'].value +
+ ";country=" + country +
+ ";geocode=" + geocode +
+ ";";
+
+ // popup a chooser
+ OLgetAJAX( url, update_geocode, 300 );
+
+ } else {
+
+ cf.elements['geocode'].value = 'DEFAULT';
+ post_geocode();
+
+ }
+
+ } else {
+
+ post_geocode();
+
+ }
+
+% } else {
+
+ post_geocode();
+
+% }
+
+}
+
+function post_geocode() {
+
+% if ( $conf->exists('cust_main-require_censustract') ) {
+
+ //alert('fetch census tract data');
+ var cf = document.CustomerForm;
+ var state_el = cf.elements['ship_state'];
+ var census_data = new Array(
+ 'year', <% $conf->config('census_year') || '2009' %>,
+ 'address', cf.elements['ship_address1'].value,
+ 'city', cf.elements['ship_city'].value,
+ 'state', state_el.options[ state_el.selectedIndex ].value,
+ 'zip', cf.elements['ship_zip'].value
+ );
+
+ censustract( census_data, update_censustract );
+
+% }else{
+
+ document.CustomerForm.submit();
+
+% }
+
+}
+
+function update_geocode() {
+
+ //yay closures
+ set_geocode = function (what) {
+
+ var cf = document.CustomerForm;
+
+ //alert(what.options[what.selectedIndex].value);
+ var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
+ cf.elements['<% $taxpre %>city'].value = argsHash['city'];
+ setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
+ cf.elements['<% $taxpre %>zip'].value = argsHash['zip'];
+ cf.elements['geocode'].value = argsHash['geocode'];
+ post_geocode();
+
+ }
+
+ // popup a chooser
+
+ overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+}
+
+var set_censustract;
+
+function update_censustract(arg) {
+
+ var argsHash = eval('(' + arg + ')');
+
+ var cf = document.CustomerForm;
+
+ var msacode = argsHash['msacode'];
+ var statecode = argsHash['statecode'];
+ var countycode = argsHash['countycode'];
+ var tractcode = argsHash['tractcode'];
+ var error = argsHash['error'];
+
+ var newcensus =
+ new String(statecode) +
+ new String(countycode) +
+ new String(tractcode).replace(/\s$/, ''); // JSON 1 workaround
+
+ set_censustract = function () {
+
+ cf.elements['censustract'].value = newcensus
+ cf.submit();
+
+ }
+
+ if (error || cf.elements['censustract'].value != newcensus) {
+ // popup an entry dialog
+
+ if (error) { newcensus = error; }
+ newcensus.replace(/.*ndefined.*/, 'Not found');
+
+ var choose_censustract =
+ '<CENTER><BR><B>Confirm censustract</B><BR>' +
+ '<A href="http://maps.ffiec.gov/FFIECMapper/TGMapSrv.aspx?' +
+ 'census_year=<% $conf->config('census_year') || '2008' %>' +
+ '&latitude=' + cf.elements['latitude'].value +
+ '&longitude=' + cf.elements['longitude'].value +
+ '" target="_blank">Map service module location</A><BR>' +
+ '<A href="http://maps.ffiec.gov/FFIECMapper/TGMapSrv.aspx?' +
+ 'census_year=<% $conf->config('census_year') || '2008' %>' +
+ '&zip_code=' + cf.elements['ship_zip'].value +
+ '" target="_blank">Map zip code center</A><BR><BR>' +
+ '<TABLE>';
+
+ choose_censustract = choose_censustract +
+ '<TR><TH style="width:50%">Entered census tract</TH>' +
+ '<TH style="width:50%">Calculated census tract</TH></TR>' +
+ '<TR><TD>' + cf.elements['censustract'].value +
+ '</TD><TD>' + newcensus + '</TD></TR>' +
+ '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ choose_censustract = choose_censustract +
+ '<TR><TD ALIGN="center">' +
+ '<BUTTON TYPE="button" onClick="document.CustomerForm.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered census tract </BUTTON>' +
+ '</TD><TD ALIGN="center">' +
+ '<BUTTON TYPE="button" onClick="set_censustract();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use calculated census tract </BUTTON>' +
+ '</TD></TR>' +
+ '<TR><TD COLSPAN=2 ALIGN="center">' +
+ '<BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+
+ '</TABLE></CENTER>';
+
+ overlib( choose_censustract, CAPTION, 'Confirm censustract', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+ } else {
+
+ cf.submit();
+
+ }
+
+}
+
+function copyelement(from, to) {
+ if ( from == undefined ) {
+ to.value = '';
+ } else if ( from.type == 'select-one' ) {
+ to.value = from.options[from.selectedIndex].value;
+ //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
+ } else if ( from.type == 'checkbox' ) {
+ if ( from.checked ) {
+ to.value = from.value;
+ } else {
+ to.value = '';
+ }
+ } else {
+ if ( from.value == undefined ) {
+ to.value = '';
+ } else {
+ to.value = from.value;
+ }
+ }
+ //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
+}
+
+function setselect(el, value) {
+
+ for ( var s = 0; s < el.options.length; s++ ) {
+ if ( el.options[s].value == value ) {
+ el.selectedIndex = s;
+ }
+ }
+
+}
+<%init>
+
+my $conf = new FS::Conf;
+
+my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
+
+</%init>
diff --git a/httemplate/edit/cust_main/choose_tax_location.html b/httemplate/edit/cust_main/choose_tax_location.html
index bd8b95c..ac475c5 100644
--- a/httemplate/edit/cust_main/choose_tax_location.html
+++ b/httemplate/edit/cust_main/choose_tax_location.html
@@ -1,5 +1,6 @@
<FORM NAME="choosegeocodeform">
<CENTER><BR><B>Choose tax location</B><BR><BR>
+<P>the geocode is:<% $header %></P>
<P STYLE="<% $style %>"><% $header %></P>
<SELECT NAME='geocodes' ID='geocodes' STYLE="<% $style %>">
@@ -18,7 +19,7 @@
% foreach qw( city county state );
% $content .= $location->cityflag eq 'I' ? 'Y' : 'N' ;
% my $selected = '' ;
-% if (!$have_selected && lc($location->city) eq lc($location{city})) {
+% if ($geocode && $location->geocode eq $geocode) {
% $selected = 'SELECTED';
% }
<OPTION VALUE="<% $value %>" STYLE="<% $style %>" <% $selected %>><% $content %>
@@ -26,8 +27,8 @@
</SELECT><BR><BR>
<TABLE><TR>
- <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes')); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
- <TD><BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
+ <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes'));"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
+ <TD><BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
</TR>
</TABLE>
@@ -36,7 +37,6 @@
<%init>
my $conf = new FS::Conf;
-my $have_selected = 0;
my %location = ();
@@ -46,6 +46,8 @@ my %location = ();
($location{zip}) = $cgi->param('zip') =~ /^([-\w ]+)$/;
($location{country}) = $cgi->param('country') =~ /^([\w ]+)$/;
+my($geocode) = $cgi->param('geocode') =~ /^([\w]+)$/;
+
my($zip5, $zip4) = split('-', $location{zip});
#only support US & CA
diff --git a/httemplate/edit/cust_main/contact.html b/httemplate/edit/cust_main/contact.html
index 27dd385..3ccee62 100644
--- a/httemplate/edit/cust_main/contact.html
+++ b/httemplate/edit/cust_main/contact.html
@@ -32,6 +32,7 @@
'disabled' => $disabled,
'same_checked' => $opt{'same_checked'},
'geocode' => $opt{'geocode'},
+ 'censustract' => $opt{'censustract'},
)
%>
@@ -110,6 +111,12 @@ $cust_main->set($pre.'state', $statedefault )
$cust_main->set('stateid_state', $cust_main->state )
unless $pre || $cust_main->get('stateid_state');
+$opt{geocode} ||= $cust_main->get('geocode');
+
+if ( $conf->exists('cust_main-require_censustract') ) {
+ $opt{censustract} ||= $cust_main->censustract;
+}
+
#my($county_html, $state_html, $country_html) =
# FS::cust_main_county::regionselector( $cust_main->get($pre.'county'),
# $cust_main->get($pre.'state'),
diff --git a/httemplate/edit/cust_main/first_pkg.html b/httemplate/edit/cust_main/first_pkg.html
new file mode 100644
index 0000000..0de33c0
--- /dev/null
+++ b/httemplate/edit/cust_main/first_pkg.html
@@ -0,0 +1,55 @@
+% if ( @part_pkg ) {
+
+ <BR><BR>
+ <FONT SIZE="+1"><B>First package</B></FONT>
+ <% ntable("#cccccc") %>
+
+ <TR>
+ <TD COLSPAN=2>
+ <% include('first_pkg/select-part_pkg.html',
+ 'part_pkg' => \@part_pkg,
+ %opt,
+ # map { $_ => $opt{$_} } qw( pkgpart_svcpart saved_domsvc )
+ )
+ %>
+
+% }
+<%init>
+
+my( $cust_main, %opt ) = @_;
+
+# pry the wrong place for this logic. also pretty expensive
+
+#false laziness, copied from FS::cust_pkg::order
+my $pkgpart;
+my $agentnum = '';
+my @agents = $FS::CurrentUser::CurrentUser->agents;
+if ( scalar(@agents) == 1 ) {
+ # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
+ $pkgpart = $agents[0]->pkgpart_hashref;
+ $agentnum = $agents[0]->agentnum;
+} else {
+ #can't know (agent not chosen), so, allow all
+ $agentnum = 'all';
+ my %typenum;
+ foreach my $agent ( @agents ) {
+ next if $typenum{$agent->typenum}++;
+ $pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
+ }
+}
+#eslaf
+
+my @first_svc = ( 'svc_acct', 'svc_phone' );
+
+my @part_pkg =
+ grep { $_->svcpart(\@first_svc)
+ && ( $pkgpart->{ $_->pkgpart }
+ || $agentnum eq 'all'
+ || ( $agentnum ne 'all' && $agentnum && $_->agentnum
+ && $_->agentnum == $agentnum
+ )
+ )
+ }
+ qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/select-part_pkg.html b/httemplate/edit/cust_main/first_pkg/select-part_pkg.html
new file mode 100644
index 0000000..871e1cd
--- /dev/null
+++ b/httemplate/edit/cust_main/first_pkg/select-part_pkg.html
@@ -0,0 +1,170 @@
+<% include('/elements/xmlhttp.html',
+ 'url' => $url_prefix.'misc/svc_acct-domains.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_domains' ],
+ )
+%>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $url_prefix.'misc/part_svc-columns.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_part_svc' ],
+ )
+%>
+
+<INPUT TYPE="hidden" NAME="svcdb" VALUE="">
+
+<SCRIPT TYPE="text/javascript">
+
+ function selopt(what,value,text,selected) {
+ var optionName = new Option(text, value, false, selected);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ var pkgpart_svcpart2svcdb = {
+% foreach my $pkgpart ( map $_->pkgpart, @part_pkg ) {
+ "<% $pkgpart_svcpart{$pkgpart} %>":"<% $svcdb{$pkgpart} %>",
+% }
+ '':''
+ };
+
+ function <% $opt{'prefix'} %>pkgpart_svcpart_changed_too(what,selected) {
+
+ <% $opt{'onchange'} %>;
+
+ pkgpart_svcpart = what.options[what.selectedIndex].value;
+
+ var svcdb = pkgpart_svcpart2svcdb[pkgpart_svcpart];
+
+ what.form.svcdb.value = svcdb;
+
+ if ( svcdb == 'svc_acct' ) {
+
+ // go get the new domains
+ function <% $opt{'prefix'} %>update_domains(domains) {
+
+ // blank the current domain list
+ for ( var i = what.form.<% $opt{'prefix'} %>domsvc.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>domsvc.options[i] = null;
+
+ // add the new domains
+ var domainArray = eval('(' + domains + ')' );
+ for ( var s = 0; s < domainArray.length; s=s+2 ) {
+ var domainLabel = domainArray[s+1];
+ if ( domainLabel == "" )
+ domainLabel = '(n/a)';
+ selopt( what.form.<% $opt{'prefix'} %>domsvc,
+ domainArray[s],
+ domainLabel,
+ (domainArray[s] == selected) ? true : false
+ );
+ }
+
+ }
+
+ <% $opt{'prefix'} %>get_domains( pkgpart_svcpart,
+ <% $opt{'prefix'} %>update_domains
+ );
+
+ } else if ( svcdb == 'svc_phone' ) {
+
+ function <% $opt{'prefix'} %>update_svc_phone(part_svc_column) {
+ var colArray = eval('(' + part_svc_column + ')' );
+ for ( var s = 0; s < colArray.length; s=s+3 ) {
+ var name = colArray[s];
+ var flag = colArray[s+1];
+ var value = colArray[s+2];
+ var td_label = document.getElementById(name+'_label_td');
+ var td = document.getElementById(name+'_td');
+ var input = document.getElementById(name);
+ if ( flag == 'D' ) {
+ if ( ! input.value ) { input.value = value; }
+ td_label.style.display = ''
+ td.style.display = ''
+ } else if ( flag == 'F' ) {
+ input.value = value;
+ td_label.style.display = 'none'
+ td.style.display = 'none'
+ } else {
+ td_label.style.display = ''
+ td.style.display = ''
+ }
+ }
+ }
+
+ <% $opt{'prefix'} %>get_part_svc( pkgpart_svcpart,
+ <% $opt{'prefix'} %>update_svc_phone
+ );
+
+ }
+
+ }
+
+</SCRIPT>
+
+<% include( '/elements/selectlayers.html',
+ 'field' => $opt{'prefix'}. 'pkgpart_svcpart',
+ 'curr_value' => $opt{pkgpart_svcpart},
+ 'options' => \@options,
+ 'labels' => \%labels,
+ 'html_between' => '</TD></TR></TABLE>',
+ #'onchange' => $opt{'prefix'}. 'pkgpart_svcpart_changed(this,0);',
+ 'onchange' => $opt{'prefix'}. 'pkgpart_svcpart_changed_too(what,0)',
+
+ 'layer_callback' => $layer_callback,
+ 'layermap' => \%layermap,
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+ pkgpart_svcpart_changed_too( document.CustomerForm.pkgpart_svcpart,
+ <% $opt{saved_domsvc} %>
+ );
+</SCRIPT>
+
+<%init>
+
+my %opt = @_;
+
+foreach my $opt (qw( svc_part pkgparts saved_pkgpart saved_domsvc prefix)) {
+ $opt{$_} = '' unless exists($opt{$_}) && defined($opt{$_});
+}
+$opt{saved_domsvc} = 0 unless $opt{saved_domsvc};
+
+my $url_prefix = $opt{'relurls'} ? '' : $p;
+
+my @part_pkg = @{$opt{'part_pkg'}};
+
+my @first_svc = ( 'svc_acct', 'svc_phone' );
+
+my %pkgpart_svcpart = ();
+my %svcdb = ();
+my %layermap = ();
+foreach my $part_pkg ( @part_pkg ) {
+ my $pkgpart = $part_pkg->pkgpart;
+ my $pkgpart_svcpart = $pkgpart. "_". $part_pkg->svcpart(\@first_svc);
+ $pkgpart_svcpart{$pkgpart} = $pkgpart_svcpart;
+ $svcdb{$pkgpart} = $part_pkg->part_svc(\@first_svc)->svcdb;
+ $layermap{$pkgpart_svcpart} = $svcdb{$pkgpart};
+}
+
+my @options = ( '', map $pkgpart_svcpart{ $_->pkgpart }, @part_pkg );
+my %labels = ( '' => ( $opt{'empty_label'} || '(none)' ),
+ map { $pkgpart_svcpart{ $_->pkgpart } => $_->pkg_comment }
+ @part_pkg
+ );
+
+my $layer_callback = sub {
+ my $layer = shift;
+ #$layer_fields, $layer_values, $layer_prefix
+
+# my( $pkgpart, $svcpart ) = split('_', $layer);
+# my $svcdb = $svcdb{$pkgpart};
+ my $svcdb = $layer;
+
+ return '' unless $svcdb; #'<BR><BR><BR><BR><BR>'
+
+ #full path cause we're being slung around as a coderef (mason closures?)
+ include("/edit/cust_main/first_pkg/$svcdb.html", %opt, );
+};
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/svc_acct.html b/httemplate/edit/cust_main/first_pkg/svc_acct.html
new file mode 100644
index 0000000..150d4c0
--- /dev/null
+++ b/httemplate/edit/cust_main/first_pkg/svc_acct.html
@@ -0,0 +1,88 @@
+<% ntable("#cccccc") %>
+
+ <TR>
+ <TD ALIGN="right">Username</TD>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "username"
+ VALUE = "<% $opt{'username'} %>"
+ SIZE = <% $ulen2 %>
+ MAXLENGTH = <% $ulen %>
+ >
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Domain</TD>
+ <TD>
+ <SELECT NAME="domsvc">
+ <OPTION>(none)</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Password</TD>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "_password"
+ VALUE = "<% $opt{'password'} %>"
+ SIZE = <% $pmax2 %>
+ MAXLENGTH = <% $passwordmax %>>
+% unless ( $opt{'password_verify'} ) {
+ (blank to generate)
+% }
+ </TD>
+ </TR>
+
+% if ( $opt{'password_verify'} ) {
+ <TR>
+ <TD ALIGN="right">Re-enter Password</TD>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "_password2"
+ VALUE = "<% $opt{'password2'} %>"
+ SIZE = <% $pmax2 %>
+ MAXLENGTH = <% $passwordmax %>>
+ </TD>
+ </TR>
+% }
+
+% if ( $conf->exists('security_phrase') ) {
+ <TR>
+ <TD ALIGN="right">Security Phrase</TD>
+ <TD><INPUT TYPE="text" NAME="sec_phrase" VALUE="<% $opt{'sec_phrase'} %>">
+ </TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="sec_phrase" VALUE="">
+% }
+
+% if ( $conf->exists('svc_acct-disable_access_number') ) {
+ <INPUT TYPE="hidden" NAME="popnum" VALUE="">
+% } else {
+ <TR>
+ <TD ALIGN="right">Access number</TD>
+%# XXX should gain "area code" selection and labels on the dropdowns
+ <TD><% FS::svc_acct_pop::popselector($opt{'popnum'}) %></TD>
+ </TR>
+% }
+
+</TABLE>
+
+<%init>
+
+#use FS::svc_acct_pop;
+
+my( %opt ) = @_;
+
+my $conf = new FS::Conf;
+
+#false laziness: (mostly) copied from edit/svc_acct.cgi
+#$ulen = $svc_acct->dbdef_table->column('username')->length;
+my $ulen = dbdef->table('svc_acct')->column('username')->length;
+my $ulen2 = $ulen+2;
+my $passwordmax = $conf->config('passwordmax') || 8;
+my $pmax2 = $passwordmax + 2;
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/svc_phone.html b/httemplate/edit/cust_main/first_pkg/svc_phone.html
new file mode 100644
index 0000000..70e013e
--- /dev/null
+++ b/httemplate/edit/cust_main/first_pkg/svc_phone.html
@@ -0,0 +1,82 @@
+<% ntable("#cccccc") %>
+
+%#XXX this should be hidden or something in most/all cases
+ <TR>
+ <TD ALIGN="right" ID="countrycode_label_td">Country code</TD>
+ <TD ID="countrycode_td">
+ <INPUT TYPE = "text"
+ NAME = "countrycode"
+ ID = "countrycode"
+ VALUE = "<% $opt{'countrycode'} %>"
+ SIZE = 4
+ MAXLENGTH = 3
+ >
+ </TD>
+ </TR>
+
+%#we don't know the svcpart until the dropdown is changed :/
+%#<% include('/elements/tr-select-did.html',
+%# 'label' => 'Phone number',
+%# 'curr_value' => $opt{'phonenum'},
+%# )
+%#%>
+ <TR>
+ <TD ALIGN="right" ID="phonenum_label_td">Phone Number</TD>
+ <TD ID="phonenum_td">
+ <INPUT TYPE = "text"
+ NAME = "phonenum"
+ ID = "phonenum"
+ VALUE = "<% $opt{'phonenum'} %>"
+ SIZE = 21
+ MAXLENGTH = 20
+ >
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right" ID="sip_password_label_td">SIP password</TD>
+ <TD ID="sip_password_td">
+ <INPUT TYPE = "text"
+ NAME = "sip_password"
+ ID = "sip_password"
+ VALUE = "<% $opt{'sip_password'} %>"
+ MAXLENGTH = 80
+ >
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right" ID="pin_label_td">Voicemail PIN</TD>
+ <TD ID="pin_td">
+ <INPUT TYPE = "text"
+ NAME = "pin"
+ ID = "pin"
+ VALUE = "<% $opt{'pin'} %>"
+ SIZE = 5
+ MAXLENGTH = 4
+ >
+ </TD>
+ </TR>
+
+%#XXX this should be hidden or something in most/all cases
+ <TR>
+ <TD ALIGN="right" ID="phone_name_label_td">Name</TD>
+ <TD ID="phone_name_td">
+ <INPUT TYPE = "text"
+ NAME = "phone_name"
+ ID = "phone_name"
+ VALUE = "<% $opt{'phone_name'} %>"
+ MAXLENGTH = 80
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+<%init>
+
+my( %opt ) = @_;
+
+#my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/cust_main/select-domain.html b/httemplate/edit/cust_main/select-domain.html
deleted file mode 100644
index bec1e83..0000000
--- a/httemplate/edit/cust_main/select-domain.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-<% include('/elements/xmlhttp.html',
- 'url' => $p.'misc/svc_acct-domains.cgi',
- 'subs' => [ $opt{'prefix'}. 'get_domains' ],
- )
-%>
-
-<SCRIPT TYPE="text/javascript">
-
- function selopt(what,value,text,selected) {
- var optionName = new Option(text, value, false, selected);
- var length = what.length;
- what.options[length] = optionName;
- }
-
- function <% $opt{'prefix'} %>pkgpart_svcpart_changed(what,selected) {
-
- pkgpart_svcpart = what.options[what.selectedIndex].value;
-
- function <% $opt{'prefix'} %>update_domains(domains) {
-
- // blank the current domain list
- for ( var i = what.form.<% $opt{'prefix'} %>domsvc.length; i >= 0; i-- )
- what.form.<% $opt{'prefix'} %>domsvc.options[i] = null;
-
- // add the new domains
- var domainArray = eval('(' + domains + ')' );
- for ( var s = 0; s < domainArray.length; s=s+2 ) {
- var domainLabel = domainArray[s+1];
- if ( domainLabel == "" )
- domainLabel = '(n/a)';
- selopt(what.form.<% $opt{'prefix'} %>domsvc, domainArray[s], domainLabel, (domainArray[s] == selected) ? true : false);
- }
-
- }
-
- // go get the new domains
- <% $opt{'prefix'} %>get_domains( pkgpart_svcpart, <% $opt{'prefix'} %>update_domains );
-
- }
-
-</SCRIPT>
-
-<SELECT NAME="<% $opt{'prefix'} %>pkgpart_svcpart" onchange="<% $opt{'prefix'} %>pkgpart_svcpart_changed(this,0);" >
- <OPTION VALUE="">(none)
-
-% foreach my $part_pkg ( @part_pkg ) {
-
- <OPTION VALUE="<% $part_pkg->pkgpart. "_". $part_pkg->svcpart('svc_acct') %>"<% ( $opt{saved_pkgpart} && $part_pkg->pkgpart == $opt{saved_pkgpart} ) ? ' SELECTED' : '' %>><% $part_pkg->pkg. " - ". $part_pkg->comment %>
-
-% }
-
-</SELECT>
-<SCRIPT>
- pkgpart_svcpart_changed(document.bottomform.pkgpart_svcpart, <% $opt{saved_domsvc} %>);
-</SCRIPT>
-
-<%init>
-my %opt = @_;
-foreach my $opt (qw( svc_part pkgparts saved_pkgpart saved_domsvc prefix)) {
- $opt{$_} = '' unless exists($opt{$_}) && defined($opt{$_});
-}
-$opt{saved_domsvc} = 0 unless $opt{saved_domsvc};
-my @part_pkg = @{$opt{'pkgparts'}};
-
-</%init>
-
diff --git a/httemplate/edit/cust_main/top_misc.html b/httemplate/edit/cust_main/top_misc.html
new file mode 100644
index 0000000..0410506
--- /dev/null
+++ b/httemplate/edit/cust_main/top_misc.html
@@ -0,0 +1,97 @@
+<% &ntable("#cccccc") %>
+
+%# agent
+<% include('/elements/tr-select-agent.html',
+ 'curr_value' => $cust_main->agentnum,
+ 'label' => "<B>${r}Agent</B>",
+ 'empty_label' => 'Select agent',
+ 'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
+ )
+%>
+
+%# agent_custid
+% if ( $conf->exists('cust_main-edit_agent_custid') ) {
+
+ <TR>
+ <TD ALIGN="right">Customer identifier</TD>
+ <TD><INPUT TYPE="text" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>"></TD>
+ </TR>
+
+% } else {
+
+ <INPUT TYPE="hidden" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>">
+
+% }
+
+%# referral (advertising source)
+%my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
+%if ( $custnum && ! $conf->exists('editreferrals') ) {
+
+ <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
+
+% } else {
+
+ <% include('/elements/tr-select-part_referral.html',
+ 'curr_value' => $refnum
+ )
+ %>
+% }
+
+
+%# referring customer
+%my $referring_cust_main = '';
+%if ( $cust_main->referral_custnum
+% and $referring_cust_main =
+% qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
+%) {
+
+ <TR>
+ <TD ALIGN="right">Referring customer</TD>
+ <TD>
+ <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
+ </TD>
+ </TR>
+ <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
+% } elsif ( ! $conf->exists('disable_customer_referrals') ) {
+
+
+ <TR>
+ <TD ALIGN="right">Referring customer</TD>
+ <TD>
+ <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
+ <% include('/elements/search-cust_main.html',
+ 'field_name' => 'referral_custnum',
+ )
+ %>
+ </TD>
+ </TR>
+% } else {
+
+
+ <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
+% }
+
+%# signup date
+% if ( $conf->exists('cust_main-edit_signupdate') ) {
+ <% include('/elements/tr-input-date-field.html', {
+ 'name' => 'signupdate',
+ 'value' => $cust_main->signupdate,
+ 'label' => 'Signup date',
+ 'format' => $conf->config('date_format') || "%m/%d/%Y",
+ })
+ %>
+% }
+
+</TABLE>
+
+<%init>
+
+my( $cust_main, %opt ) = @_;
+
+my $custnum = $opt{'custnum'};
+
+my $conf = new FS::Conf;
+
+my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+</%init>
diff --git a/httemplate/edit/cust_main_attach.cgi b/httemplate/edit/cust_main_attach.cgi
new file mode 100755
index 0000000..43d2e29
--- /dev/null
+++ b/httemplate/edit/cust_main_attach.cgi
@@ -0,0 +1,59 @@
+<% include('/elements/header-popup.html', "$action File Attachment") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/cust_main_attach.cgi" METHOD=POST ENCTYPE="multipart/form-data">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+<INPUT TYPE="hidden" NAME="attachnum" VALUE="<% $attachnum %>">
+
+<BR><BR>
+
+% if(defined $attach) {
+Filename <INPUT TYPE="text" NAME="filename" VALUE="<% $attach->filename %>"><BR>
+MIME type <INPUT TYPE="text" NAME="mime_type" VALUE="<% $attach->mime_type %>"<BR>
+Size: <% $attach->size %><BR>
+
+% }
+% else { # !defined $attach
+
+Filename <INPUT TYPE="file" NAME="file"><BR>
+
+% }
+
+<BR>
+<INPUT TYPE="submit" NAME="submit"
+ VALUE="<% $attachnum ? "Apply Changes" : "Upload File" %>">
+
+% if(defined $attach and $curuser->access_right('Delete attachment')) {
+<BR>
+<INPUT TYPE="submit" NAME="delete" value="Delete File">
+% }
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $attachnum = '';
+my $attach;
+if ( $cgi->param('error') ) {
+ #$comment = $cgi->param('comment');
+} elsif ( $cgi->param('attachnum') =~ /^(\d+)$/ ) {
+ $attachnum = $1;
+ die "illegal query ". $cgi->keywords unless $attachnum;
+ $attach = qsearchs('cust_attachment', { 'attachnum' => $attachnum });
+ die "no such attachment: ". $attachnum unless $attach;
+}
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die "illegal custnum";
+my $custnum = $1;
+
+my $action = $attachnum ? 'Edit' : 'Add';
+
+die "access denied"
+ unless $curuser->access_right("$action attachment");
+
+</%init>
+
diff --git a/httemplate/edit/cust_pay.cgi b/httemplate/edit/cust_pay.cgi
index 3c28774..07e5198 100755
--- a/httemplate/edit/cust_pay.cgi
+++ b/httemplate/edit/cust_pay.cgi
@@ -72,6 +72,16 @@ Payment
% }
</TR>
+% if ( $conf->exists('pkg-balances') ) {
+ <% include('/elements/tr-select-cust_pkg-balances.html',
+ 'custnum' => $custnum,
+ 'cgi' => $cgi
+ )
+ %>
+% } else {
+ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="">
+% }
+
</TABLE>
<BR>
@@ -95,7 +105,7 @@ my $money_char = $conf->config('money_char') || '$';
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Post payment');
-my($link, $linknum, $paid, $payby, $payinfo, $_date);
+my($link, $linknum, $paid, $payby, $payinfo, $_date);
if ( $cgi->param('error') ) {
$link = $cgi->param('link');
$linknum = $cgi->param('linknum');
@@ -131,7 +141,7 @@ if ( $link eq 'invnum' ) {
my $cust_bill = qsearchs('cust_bill', { 'invnum' => $linknum } )
or die "unknown invnum $linknum";
$custnum = $cust_bill->custnum;
-} elsif ( $link eq 'custnum' ) {
+} elsif ( $link eq 'custnum' || $link eq 'popup' ) {
$custnum = $linknum;
}
diff --git a/httemplate/edit/cust_pkg.cgi b/httemplate/edit/cust_pkg.cgi
index f927e10..dd1ed33 100755
--- a/httemplate/edit/cust_pkg.cgi
+++ b/httemplate/edit/cust_pkg.cgi
@@ -128,10 +128,10 @@ my %all_comment = ();
#}
foreach (qsearch('part_pkg', {} )) {
$all_pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
- $all_comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+ $all_comment{ $_ -> getfield('pkgpart') } = $_->custom_comment;
next if $_->disabled;
$pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
- $comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+ $comment{ $_ -> getfield('pkgpart') } = $_->custom_comment;
}
my($custnum, %remove_pkg);
diff --git a/httemplate/edit/cust_tax_adjustment.html b/httemplate/edit/cust_tax_adjustment.html
new file mode 100644
index 0000000..9d4afbc
--- /dev/null
+++ b/httemplate/edit/cust_tax_adjustment.html
@@ -0,0 +1,102 @@
+<% include('/elements/header-popup.html', 'Tax adjustment' ) %>
+
+<% include('/elements/error.html') %>
+
+<SCRIPT TYPE="text/javascript">
+
+function enable_tax_adjustment () {
+ if ( document.TaxAdjustmentForm.amount.value
+ && document.TaxAdjustmentForm.taxname.selectedIndex > 0 ) {
+ document.TaxAdjustmentForm.submit.disabled = false;
+ } else {
+ document.TaxAdjustmentForm.submit.disabled = true;
+ }
+}
+
+function validate_tax_adjustment () {
+ var comment = document.TaxAdjustmentForm.comment.value;
+ var comment_regex = /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/ ;
+ var amount = document.TaxAdjustmentForm.amount.value;
+ var amount_regex = /^\s*\$?\s*(\d*(\.?\d{1,2}))\s*$/ ;
+ var rval = true;
+
+ if ( ! amount_regex.test(amount) ) {
+ alert('Illegal amount - enter the amount of the tax adjustment, for example, "5" or "43" or "21.46".');
+ return false;
+ }
+ if ( ! comment_regex.test(comment) ) {
+ alert('Illegal comment - spaces, letters, numbers, and the following punctuation characters are allowed: . , ! ? @ # $ % & ( ) - + ; : ' + "'" + ' " = [ ]' );
+ return false;
+ }
+
+ return true;
+}
+
+</SCRIPT>
+
+<FORM ACTION="process/cust_tax_adjustment.html" NAME="TaxAdjustmentForm" ID="TaxAdjustmentForm" METHOD="POST" onsubmit="document.TaxAdjustmentForm.submit.disabled=true;return validate_tax_adjustment();">
+
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+
+<TABLE ID="TaxAdjustmentTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 STYLE="background-color: #cccccc">
+
+<TR>
+ <TD ALIGN="right">Tax </TD>
+ <TD>
+ <SELECT NAME="taxname" ID="taxname" onChange="enable_tax_adjustment()" onKeyPress="enable_tax_adjustment()">
+ <OPTION VALUE=""></OPTION>
+% foreach my $taxname (@taxname) {
+ <OPTION VALUE="<% $taxname %>"><% $taxname %></OPTION>
+% }
+ </SELECT>
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount </TD>
+ <TD>
+ $<INPUT TYPE="text" NAME="amount" SIZE=6 VALUE="<% $amount %>" onChange="enable_tax_adjustment()" onKeyPress="enable_tax_adjustment()">
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Comment </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="comment" SIZE="50" MAXLENGTH="50" VALUE="<% $comment %>" onChange="enable_tax_adjustment()" onKeyPress="enable_tax_adjustment()">
+ </TD>
+</TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" ID="submit" NAME="submit" VALUE="Add tax adjustment" <% $cgi->param('error') ? '' :' DISABLED' %>>
+
+</FORM>
+
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Add customer tax adjustment');
+
+my $sql = 'SELECT DISTINCT(taxname) FROM cust_main_county';
+my $sth = dbh->prepare($sql) or die dbh->errstr;
+$sth->execute() or die $sth->errstr;
+my @taxname = map { $_->[0] || 'Tax' } @{ $sth->fetchall_arrayref([]) };
+
+my $conf = new FS::Conf;
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
+my $custnum = $1;
+
+my $amount = '';
+if ( $cgi->param('amount') =~ /^\s*\$?\s*(\d+(\.\d{1,2})?)\s*$/ ) {
+ $amount = $1;
+}
+
+$cgi->param('comment') =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/
+ or die 'illegal description';
+my $comment = $1;
+
+</%init>
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index d18a37d..fd73e03 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -132,37 +132,39 @@ Example:
# initialization callbacks
###
- ###global callbacks
+ ###global callbacks, always run if provided
- #always run if provided, after decoding long CGI "redirect=" responses but
+ #after decoding long CGI "redirect=" responses but
# before object creation/search
# (useful if you have a long form that might trigger redirect= and you need
# to do things with $cgi params - they're not decoded in the calling
# <%init> block yet)
'begin_callback' = sub { my( $cgi, $fields_listref, $opt_hashref ) = @_; },
- #always run, after the mode-specific object creation/search
+ #after the mode-specific object creation/search
'end_callback' = sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
- ###mode-specific callbacks
+ ###mode-specific callbacks. one (and only one) of these four is called
+ #run when adding
+ 'new_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
+ #run when editing
+ 'edit_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
#run when re-displaying with an error
'error_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
- #run when editing
- 'edit_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; },
-
+ #run when cloning
+ 'clone_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
+ ###callbacks called in new mode only
+
# returns a hashref for the new object
'new_hashref_callback'
# returns the new object iself (otherwise, ->new is called)
'new_object_callback'
-
- #run when adding
- 'new_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; },
-
- #run when cloning
- 'clone_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
###display callbacks
@@ -287,7 +289,8 @@ Example:
% foreach grep exists($f->{$_}), qw( hashref agent_virt agent_null_right );
%
% if ( $type eq 'tablebreak-tr-title' ) {
-% $include_common{'table_id'} = 'TableNumber'. $tablenum++
+% $include_common{'table_id'} = 'TableNumber'. $tablenum++;
+% $include_common{'colspan'} = $f->{colspan} if $f->{colspan};
% }
%
% my $layer_prefix_on = '';
@@ -315,6 +318,27 @@ Example:
% @include;
% };
%
+% my $column_sub = sub {
+% my %opt = @_;
+%
+% my $column = delete($opt{field});
+% my $fieldnum = delete($opt{fieldnum});
+% my $include = delete($opt{type}) || 'text';
+% $include = "input-$include" if $include =~ /^(text|money|percentage)$/;
+%
+% ( "/elements/$include.html",
+% 'field' => $field.'__'.$column.$fieldnum,
+% 'id' => $field.'__'.$column.$fieldnum,
+% 'layer_prefix' => $field.'__'.$column.$fieldnum.".",
+% ( $fieldnum
+% ? ('cell_style' => 'border-top:1px solid black')
+% : ()
+% ),
+% 'cgi' => $cgi,
+% %opt,
+% );
+% };
+%
% unless ( $type =~ /^column/ ) {
% $g_row = 1 if $type eq 'tablebreak-tr-title';
% $g_row++;
@@ -380,8 +404,35 @@ Example:
% 'layer_values' => $layer_values,
% 'cell_style' => ( $fieldnum ? 'border-top:1px solid black' : '' ),
% );
+% $existing[0] =~ s(^/elements/tr-)(/elements/);
+% my @label = @existing;
+% $label[0] = '/elements/tr-td-label.html';
+ <% include( @label ) %>
+ <TD>
<% include( @existing ) %>
+ </TD>
+
+% if ( $f->{'m2_fields'} ) {
+% foreach my $c ( @{ $f->{'m2_fields'} } ) {
+% my $column = $c->{field};
+% my @column = &{ $column_sub }( %$c,
+% 'fieldnum' => $fieldnum,
+% 'curr_value' => $name_obj->$column()
+% );
+
+ <TD id='<% $field %>__<% $column %>_label<% $fieldnum %>'
+ style='text-align:right;vertical-align:top;
+ border-top:1px solid black;padding-top:5px;'>
+ <% $c->{'label'} || '' %>
+ </TD>
+ <TD style='border-top:1px solid black;padding-top:3px;'>
+ <% include( @column ) %>
+ </TD>
+% }
+% }
+
+ </TR>
% $fieldnum++;
% $g_row++;
@@ -407,9 +458,40 @@ Example:
% 'onchange' => $onchange,
% ( $fieldnum ? ('cell_style' => 'border-top:1px solid black') : () ),
% );
+%
+% if ( $f->{'m2name_table'} || $f->{'m2m_method'} ) {
+% $include[0] =~ s(^/elements/tr-)(/elements/);
+% my @label = @include;
+% $label[0] = '/elements/tr-td-label.html';
+
+ <% include( @label ) %>
+ <TD>
+ <% include( @include ) %>
+ </TD>
+
+% if ( $f->{'m2_fields'} ) {
+% foreach my $c ( @{ $f->{'m2_fields'} } ) {
+% my $column = $c->{field};
+% my @column = &{ $column_sub }( %$c, 'fieldnum' => $fieldnum );
+
+ <TD id='<% $field %>__<% $column %>_label<% $fieldnum %>'
+ style='text-align:right;vertical-align:top;
+ border-top:1px solid black;padding-top:5px;'>
+ <% $c->{'label'} || '' %>
+ </TD>
+ <TD style='border-top:1px solid black;padding-top:3px;'>
+ <% include( @column ) %>
+ </TD>
+% }
+% }
+
+ </TR>
+
+% } else {
- <% include( @include ) %>
+ <% include( @include ) %>
+% }
% if ( $f->{'m2name_table'} || $f->{'m2m_method'} ) {
<SCRIPT TYPE="text/javascript">
@@ -497,6 +579,39 @@ Example:
row.appendChild(widget_cell);
+% if ( $f->{'m2_fields'} ) {
+% foreach my $c ( @{ $f->{'m2_fields'} } ) {
+% my $column = $c->{field};
+% my @column = &{ $column_sub }(%$c, 'fieldnum' => 'MAGIC_NUMBER');
+
+ var column = <% include(@column, html_only=>1) |js_string %>;
+ column = column.replace( magic_regex, <%$field%>_fieldnum );
+
+ var column_label = document.createElement('TD');
+ column_label.id =
+ '<% $field %>__<% $column %>_label' + <%$field%>_fieldnum;
+
+ column_label.style.textAlign = "right";
+ column_label.style.verticalAlign = "top";
+ column_label.style.borderTop = "1px solid black";
+ column_label.style.paddingTop = "5px";
+
+ column_label.innerHTML = '<% $c->{'label'} || '' %>';
+
+ row.appendChild(column_label);
+
+ var column_widget = document.createElement('TD');
+
+ column_widget.style.borderTop = "1px solid black";
+ column_widget.style.paddingTop = "3px";
+
+ column_widget.innerHTML = column;
+
+ row.appendChild(column_widget);
+
+% }
+% }
+
% if ( $f->{'m2_new_js'} ) {
// take out items selected in previous dropdowns
var new_element = document.getElementById("<%$field%>" + <%$field%>_fieldnum );
@@ -562,7 +677,7 @@ Example:
<BR>
-<INPUT TYPE="submit" ID="submit" VALUE="<% ( !$clone && $object->$pkey() ) ? "Apply changes" : "Add $opt{'name'}" %>">
+<INPUT TYPE="submit" ID="submit" VALUE="<% ( !$clone && $object->$pkey() ) ? "Apply changes" : "Add ". ( $opt{'name'} || $opt{'name_singular'} ) %>">
</FORM>
@@ -618,7 +733,7 @@ if ( $cgi->param('error') ) {
map { $_ => scalar($cgi->param($_)) } fields($table)
});
- &{$opt{'error_callback'}}($cgi, $object, $fields, \%opt )
+ &{$opt{'error_callback'}}( $cgi, $object, $fields, \%opt )
if $opt{'error_callback'};
} elsif ( $cgi->param('clone') =~ /^(\d+)$/ ) {
@@ -630,9 +745,10 @@ if ( $cgi->param('error') ) {
$qsearch{'extra_sql'} = ' AND '. $opt{'agent_clone_extra_sql'}
if $opt{'agent_clone_extra_sql'};
- $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } });
+ $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } })
+ or die "$pkey $clone not found in $table";
- &{$opt{'clone_callback'}}($cgi, $object, $fields, \%opt )
+ &{$opt{'clone_callback'}}( $cgi, $object, $fields, \%opt )
if $opt{'clone_callback'};
#$object->$pkey('');
@@ -657,7 +773,7 @@ if ( $cgi->param('error') ) {
warn "$table $pkey => $1"
if $opt{'debug'};
- &{$opt{'edit_callback'}}($cgi, $object, $fields)
+ &{$opt{'edit_callback'}}( $cgi, $object, $fields, \%opt )
if $opt{'edit_callback'};
} else { #adding
@@ -672,7 +788,7 @@ if ( $cgi->param('error') ) {
? &{$opt{'new_object_callback'}}( $cgi, $hashref, $fields, \%opt )
: $class->new( $hashref );
- &{$opt{'new_callback'}}($cgi, $object, $fields)
+ &{$opt{'new_callback'}}( $cgi, $object, $fields, \%opt )
if $opt{'new_callback'};
}
@@ -682,7 +798,7 @@ if ( $cgi->param('error') ) {
$opt{action} ||= $object->$pkey() ? 'Edit' : 'Add';
-my $title = $opt{action}. ' '. $opt{name};
+my $title = $opt{action}. ' '. ( $opt{name} || $opt{'name_singular'} );
my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html";
$viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'};
diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html
index 0b64120..ef04bd0 100644
--- a/httemplate/edit/elements/svc_Common.html
+++ b/httemplate/edit/elements/svc_Common.html
@@ -3,7 +3,7 @@
'menubar' => [],
'error_callback' => sub {
- my( $cgi, $svc_x ) = @_;
+ my( $cgi, $svc_x, $fields, $opt ) = @_;
#$svcnum = $svc_x->svcnum;
$pkgnum = $cgi->param('pkgnum');
$svcpart = $cgi->param('svcpart');
@@ -11,11 +11,13 @@
$part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart });
die "No part_svc entry!" unless $part_svc;
+ label_fixup($part_svc, $opt);
+
$svc_x->setfield('svcpart', $svcpart);
},
'edit_callback' => sub {
- my( $cgi, $svc_x ) = @_;
+ my( $cgi, $svc_x, $fields, $opt ) = @_;
#$svcnum = $svc_x->svcnum;
my $cust_svc = $svc_x->cust_svc
or die "Unknown (cust_svc) svcnum!";
@@ -25,6 +27,8 @@
$part_svc = qsearchs ('part_svc', { svcpart=>$svcpart });
die "No part_svc entry!" unless $part_svc;
+
+ label_fixup($part_svc, $opt);
},
'new_hashref_callback' => sub {
@@ -35,11 +39,13 @@
},
'new_callback' => sub {
- my( $cgi, $svc_x ) = @_;;
+ my( $cgi, $svc_x, $fields, $opt ) = @_;;
$part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart });
die "No part_svc entry!" unless $part_svc;
+ label_fixup($part_svc, $opt);
+
#$svcnum='';
$svc_x->set_default_and_fixed;
@@ -100,6 +106,22 @@
%opt #pass through/override params
)
%>
+<%once>
+
+sub label_fixup {
+ my( $part_svc, $opt ) = @_;
+
+ #false laziness w/view/svc_Common.html
+ #override default labels with service-definition labels if applicable
+ my $labels = $opt->{labels}; # with -> here
+ foreach my $field ( keys %$labels ) {
+ my $col = $part_svc->part_svc_column($field);
+ $labels->{$field} = $col->columnlabel if $col->columnlabel !~ /^\S*$/;
+ }
+
+}
+
+</%once>
<%init>
my %opt = @_;
diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi
index 3b51141..c0ff386 100755
--- a/httemplate/edit/part_bill_event.cgi
+++ b/httemplate/edit/part_bill_event.cgi
@@ -78,7 +78,7 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
% join("\n", map {
% '<OPTION VALUE="'. $_->pkgpart. '"'.
% ( $selected{$_->pkgpart} ? ' SELECTED' : '' ).
-% '>'. $_->pkg. ' - '. $_->comment
+% '>'. $_->pkg_comment
% } qsearch('part_pkg', { 'disabled' => '' } ) ).
% '</SELECT>';
%}
@@ -178,7 +178,7 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
% 'cancel' => {
% 'name' => 'Cancel',
% 'code' => '$cust_main->cancel(reason => %%%creason%%%);',
-% 'weight' => 10,
+% 'weight' => 80, #10,
% 'reason' => 'C',
% },
%
@@ -191,7 +191,7 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
% 'comp' => {
% 'name' => 'Pay invoice with a complimentary "payment"',
% 'code' => '$cust_bill->comp();',
-% 'weight' => 30,
+% 'weight' => 90, #30,
% },
%
% 'credit' => {
diff --git a/httemplate/edit/part_device.html b/httemplate/edit/part_device.html
new file mode 100644
index 0000000..4f2fe93
--- /dev/null
+++ b/httemplate/edit/part_device.html
@@ -0,0 +1,16 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Phone device type',
+ 'table' => 'part_device',
+ 'labels' => {
+ 'devicepart' => 'Part number',
+ 'devicename' => 'Device name',
+ },
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi
index d579797..8b697e1 100644
--- a/httemplate/edit/part_export.cgi
+++ b/httemplate/edit/part_export.cgi
@@ -79,13 +79,28 @@ my $widget = new HTML::Widgets::SelectLayers(
);
$html .= qq!<TR><TD ALIGN="right">$label</TD><TD>!;
if ( $type eq 'select' ) {
- $html .= qq!<SELECT NAME="$option">!;
- foreach my $select_option ( @{$optinfo->{options}} ) {
+ my $size = defined($optinfo->{size}) ? " SIZE=" . $optinfo->{size} : '';
+ my $multi = defined($optinfo->{multi}) ? ' MULTIPLE' : '';
+ $html .= qq!<SELECT NAME="$option"$multi$size>!;
+ my @values = split '\s+', $value if $multi;
+ my @options;
+ if (defined($optinfo->{option_values})) {
+ my $valsub = $optinfo->{option_values};
+ @options = &$valsub();
+ } elsif (defined($optinfo->{options})) {
+ @options = @{$optinfo->{options}};
+ }
+ foreach my $select_option ( @options ) {
#if ( ref($select_option) ) {
#} else {
- my $selected = $select_option eq $value ? ' SELECTED' : '';
+ my $selected = ($multi ? grep {$_ eq $select_option} @values : $select_option eq $value ) ? ' SELECTED' : '';
+ my $label = $select_option;
+ if (defined($optinfo->{option_label})) {
+ my $labelsub = $optinfo->{option_label};
+ $label = &$labelsub($select_option);
+ }
$html .= qq!<OPTION VALUE="$select_option"$selected>!.
- qq!$select_option</OPTION>!;
+ qq!$label</OPTION>!;
#}
}
$html .= '</SELECT>';
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index f404699..690e884 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -37,6 +37,8 @@
'taxproduct_select'=> 'Tax products',
'plan' => 'Price plan',
'disabled' => 'Disable new orders',
+ 'setup_cost' => 'Setup cost',
+ 'recur_cost' => 'Recur cost',
'pay_weight' => 'Payment weight',
'credit_weight' => 'Credit weight',
'agentnum' => 'Agent',
@@ -44,6 +46,7 @@
'recur_fee' => 'Recurring fee',
'bill_dst_pkgpart' => 'Include line item(s) from package',
'svc_dst_pkgpart' => 'Include services of package',
+ 'report_option' => 'Report classes',
},
'fields' => [
@@ -56,6 +59,8 @@
sub { shift->param('pkgnum') },
},
+ { field=>'custom', type=>'hidden' },
+
{ type => 'columnstart' },
{ field => 'pkg',
@@ -131,10 +136,10 @@
{ field=>'promo_code', type=>'text', size=>15 },
{ type => 'tablebreak-tr-title',
- value => 'Line-item revenue recogition', #better name?
+ value => 'Cost tracking', #better name?
},
- { field=>'pay_weight', type=>'text', size=>6 },
- { field=>'credit_weight', type=>'text', size=>6 },
+ { field=>'setup_cost', type=>'money', },
+ { field=>'recur_cost', type=>'money', },
{ type => 'columnnext' },
@@ -148,10 +153,31 @@
},
},
+ { type => 'tablebreak-tr-title',
+ value => 'Line-item revenue recogition', #better name?
+ },
+ { field=>'pay_weight', type=>'text', size=>6 },
+ { field=>'credit_weight', type=>'text', size=>6 },
+
+
{ type => 'columnend' },
- { 'type' => 'tablebreak-tr-title',
- 'value' => 'Pricing add-ons',
+ { 'type' => $census ? 'tablebreak-tr-title'
+ : 'hidden',
+ 'value' => 'Optional report classes',
+ 'field' => 'census_title',
+ },
+ { 'field' => 'report_option',
+ 'type' => $census ? 'select-table' : 'hidden',
+ 'table' => 'part_pkg_report_option',
+ 'name_col' => 'name',
+ 'multiple' => 1,
+ },
+
+
+ { 'type' => 'tablebreak-tr-title',
+ 'value' => 'Pricing add-ons',
+ 'colspan' => 4,
},
{ 'field' => 'bill_dst_pkgpart',
'type' => 'select-part_pkg',
@@ -160,6 +186,13 @@
'm2m_dstcol' => 'dst_pkgpart',
'm2_error_callback' =>
&{$m2_error_callback_maker}('bill'),
+ 'm2_fields' => [ { 'field' => 'hidden',
+ 'type' => 'checkbox',
+ 'value' => 'Y',
+ 'curr_value' => '',
+ 'label' => 'Bundle',
+ },
+ ],
},
{ type => 'tablebreak-tr-title',
@@ -208,12 +241,12 @@ my $disabled_type = $acl_edit_either ? 'checkbox' : 'hidden';
my $agent_clone_extra_sql =
' ( '. FS::part_pkg->curuser_pkgs_sql.
- #kludge to clone custom customer packages you otherwise couldn't see
- " OR ( part_pkg.disabled = 'Y' AND part_pkg.comment LIKE '(CUSTOM)%' ) ".
+ " OR ( part_pkg.custom = 'Y' ) ".
' ) ';
my $conf = new FS::Conf;
my $taxproducts = $conf->exists('enable_taxproducts');
+my $census = scalar( qsearch( 'part_pkg_report_option', {} ) );
#XXX
# - tr-part_pkg_freq: month_increments_only (from price plans)
@@ -291,14 +324,27 @@ my $edit_callback = sub {
(@agent_type) = map {$_->typenum} qsearch('type_pkgs',{'pkgpart'=>$1});
+ my @report_option = ();
foreach ($object->options) {
/^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
+ /^report_option_(\d+)$/ && (push @report_option, $1);
}
foreach ($object->part_pkg_taxoverride) {
$taxproductnums{$_->usage_class} = 1
if $_->usage_class;
}
+ $cgi->param('report_option', join(',', @report_option));
+ foreach my $field ( @$fields ) {
+ next unless (
+ ref($field) eq 'HASH' &&
+ $field->{field} &&
+ $field->{field} eq 'report_option'
+ );
+ #$field->{curr_value} = join(',', @report_option);
+ $field->{value} = join(',', @report_option);
+ }
+
%options = $object->options;
$object->set($_ => $object->option($_))
@@ -328,9 +374,8 @@ my $clone_callback = sub {
$opt->{action} = 'Custom';
#my $part_pkg = $clone_part_pkg->clone;
- #this is all clone did anyway
- $object->comment( '(CUSTOM) '. $object->comment )
- unless $object->comment =~ /^\(CUSTOM\) /;
+ #this is all clone does anyway
+ $object->custom('Y');
$object->disabled('Y');
@@ -348,16 +393,26 @@ my $m2_error_callback_maker = sub {
my $link_type = shift; #yay closures
return sub {
my( $cgi, $object ) = @_;
- map {
- new FS::part_pkg_link {
- 'link_type' => $link_type,
- 'src_pkgpart' => $object->pkgpart,
- 'dst_pkgpart' => $_,
- };
- }
- grep $_,
- map $cgi->param($_),
- grep /^${link_type}_dst_pkgpart(\d+)$/, $cgi->param;
+ my $num;
+ map {
+
+ if ( /^${link_type}_dst_pkgpart(\d+)$/ &&
+ ( my $dst = $cgi->param("${link_type}_dst_pkgpart$1") ) )
+ {
+
+ my $hidden = $cgi->param("${link_type}_dst_pkgpart__hidden$1")
+ || '';
+ new FS::part_pkg_link {
+ 'link_type' => $link_type,
+ 'src_pkgpart' => $object->pkgpart,
+ 'dst_pkgpart' => $dst,
+ 'hidden' => $hidden,
+ };
+ } else {
+ ();
+ }
+ }
+ $cgi->param;
};
};
diff --git a/httemplate/edit/part_pkg_report_option.html b/httemplate/edit/part_pkg_report_option.html
new file mode 100644
index 0000000..a6f8e57
--- /dev/null
+++ b/httemplate/edit/part_pkg_report_option.html
@@ -0,0 +1,23 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Package optional report class',
+ 'table' => 'part_pkg_report_option',
+ 'fields' => [
+ 'name',
+ { field=>'num', type=>'hidden' },
+ { field=>'disabled', type=>'checkbox', value=>'Y', },
+ ],
+ 'labels' => {
+ 'num' => 'Class number',
+ 'name' => 'Class name',
+ 'disabled' => 'Disable class',
+ },
+ 'viewall_dir' => 'browse',
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/part_pkg_taxclass.html b/httemplate/edit/part_pkg_taxclass.html
index e767057..ad03044 100644
--- a/httemplate/edit/part_pkg_taxclass.html
+++ b/httemplate/edit/part_pkg_taxclass.html
@@ -1,32 +1,23 @@
-<% include('/elements/header.html', "$action taxclass") %>
-
-<% include('/elements/error.html') %>
-
-<FORM ACTION="<% $p1 %>process/part_pkg_taxclass.html" METHOD=POST>
-
-<INPUT TYPE="hidden" NAME="taxclassnum" VALUE="">
-
-Tax class <INPUT TYPE="text" NAME="taxclass" VALUE="<% $taxclass |h %>">
-
-<BR><BR>
-<INPUT TYPE="submit" VALUE="<% $action %> taxclass">
-
-</FORM>
-
-<% include('/elements/footer.html') %>
-
+<% include('elements/edit.html',
+ 'name_singular' => 'tax class',
+ 'table' => 'part_pkg_taxclass',
+ 'labels' => {
+ 'taxclassnum' => 'Tax class',
+ 'taxclass' => 'Tax class',
+ 'disabled' => 'Disabled',
+ },
+ 'fields' => [ 'taxclass',
+ { 'field' => 'disabled',
+ 'type' => 'checkbox',
+ 'value' => 'Y',
+ },
+ ],
+ 'viewall_dir' => 'browse',
+ )
+%>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-my $taxclass = '';
-if ( $cgi->param('error') ) {
- $taxclass = $cgi->param('taxclass');
-}
-
-my $action = 'Add';
-
-my $p1 = popurl(1);
-
</%init>
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index e0fb615..7970343 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -122,6 +122,7 @@ that field.
% $html .= include('/elements/table-grid.html', 'cellpadding' => 4 ).
% '<TR>'.
% '<TH CLASS="grid" BGCOLOR="#cccccc">Field</TH>'.
+% '<TH CLASS="grid" BGCOLOR="#cccccc">Label</TH>'.
% '<TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>'.
% '</TR>';
%
@@ -131,7 +132,14 @@ that field.
%
% #yucky kludge
% my @fields = defined( dbdef->table($layer) )
-% ? grep { $_ ne 'svcnum' } fields($layer)
+% ? grep {
+% $_ ne 'svcnum' &&
+% ( !FS::part_svc->svc_table_fields($layer)
+% ->{$_}->{disable_part_svc_column} ||
+% $part_svc->part_svc_column($_)->columnflag
+% )
+% }
+% fields($layer)
% : ();
% push @fields, 'usergroup' if $layer eq 'svc_acct'; #kludge
% $part_svc->svcpart($clone) if $clone; #haha, undone below
@@ -139,13 +147,15 @@ that field.
%
% foreach my $field (@fields) {
%
-% #my $def = $defs{$layer}{$field};
+% #a few lines of false laziness w/browse/part_svc.cgi
% my $def = FS::part_svc->svc_table_fields($layer)->{$field};
-% my $label = $def->{'def_label'} || $def->{'label'};
+% my $def_info = $def->{'def_info'};
% my $formatter = $def->{'format'} || sub { shift };
+%
% my $part_svc_column = $part_svc->part_svc_column($field);
+% my $label = $part_svc_column->columnlabel || $def->{'label'};
% my $value = &$formatter($part_svc_column->columnvalue);
-% my $flag = $part_svc_column->columnflag;
+% my $flag = $part_svc_column->columnflag;
%
% if ( $bgcolor eq $bgcolor1 ) {
% $bgcolor = $bgcolor2;
@@ -153,9 +163,12 @@ that field.
% $bgcolor = $bgcolor1;
% }
%
-% $html .= qq!<TR><TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">!.
-% ( $label || $field ).
+% $html .= qq!<TR><TD ROWSPAN=2 CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">!.
+% ( $def->{'label'} || $field ).
% "</TD>";
+%
+% $html .= qq!<TD ROWSPAN=2 CLASS="grid" BGCOLOR="$bgcolor"><INPUT NAME="${layer}__${field}_label" VALUE="!. encode_entities($label). '" STYLE="text-align:right"></TD>';
+%
% $flag = '' if $def->{type} eq 'disabled';
%
% $html .= qq!<TD CLASS="grid" BGCOLOR="$bgcolor">!;
@@ -295,6 +308,15 @@ that field.
% }
%
% $html .= "</TD></TR>\n";
+
+% $def_info = "($def_info)" if $def_info;
+% $html .=
+% qq!<TR>!.
+% qq! <TD COLSPAN=2 BGCOLOR="$bgcolor" ALIGN="center" !.
+% qq! STYLE="padding:0; border-top: none">!.
+% qq! <FONT SIZE="-1"><I>$def_info</I></FONT>!.
+% qq! </TD>!.
+% qq!</TR>\n!;
%
% } #foreach my $field (@fields) {
%
diff --git a/httemplate/edit/payment_gateway.html b/httemplate/edit/payment_gateway.html
index e3893cf..4c7bae1 100644
--- a/httemplate/edit/payment_gateway.html
+++ b/httemplate/edit/payment_gateway.html
@@ -1,132 +1,134 @@
-<% include("/elements/header.html","$action Payment gateway", menubar(
- 'View all payment gateways' => $p. 'browse/payment_gateway.html',
-)) %>
-
-<% include('/elements/error.html') %>
-
-<FORM ACTION="<%popurl(1)%>process/payment_gateway.html" METHOD=POST>
-<INPUT TYPE="hidden" NAME="gatewaynum" VALUE="<% $payment_gateway->gatewaynum %>">
-Gateway #<% $payment_gateway->gatewaynum || "(NEW)" %>
-
-<% ntable('#cccccc', 2, '') %>
-
-<TR>
- <TH ALIGN="right">Gateway: </TH>
- <TD>
-% if ( $payment_gateway->gatewaynum ) {
-
-
- <% $payment_gateway->gateway_module %>
- <INPUT TYPE="hidden" NAME="gateway_module" VALUE="<% $payment_gateway->gateway_module %>">
-% } else {
-
-
- <SELECT NAME="gateway_module" SIZE=1>
-% foreach my $module ( qw(
-% 2CheckOut
-% AuthorizeNet
-% BankOfAmerica
-% Beanstream
-% Capstone
-% Cardstream
-% CashCow
-% CyberSource
-% eSec
-% eSelectPlus
-% Exact
-% iAuthorizer
-% IPaymentTPG
-% Jettis
-% LinkPoint
-% MerchantCommerce
-% Network1Financial
-% OCV
-% OpenECHO
-% PayConnect
-% PayflowPro
-% PaymentsGateway
-% PXPost
-% SecureHostingUPG
-% Skipjack
-% StGeorge
-% SurePay
-% TCLink
-% TransactionCentral
-% TransFirsteLink
-% VirtualNet
-% ) ) {
-%
-
- <OPTION VALUE="<% $module %>"><% $module %>
-% }
-
- </SELECT>
+<% include( 'elements/edit.html',
+ 'table' => 'payment_gateway',
+ 'name_singular' => 'Payment gateway',
+ 'viewall_dir' => 'browse',
+ 'fields' => $fields,
+ 'field_callback' => $field_callback,
+ 'labels' => {
+ 'gatewaynum' => 'Gateway #',
+ 'gateway_module' => 'Gateway',
+ 'gateway_username' => 'Username',
+ 'gateway_password' => 'Password',
+ 'gateway_action' => 'Action',
+ 'gateway_options' => 'Options: (Name/Value pairs, one element per line)',
+ 'gateway_callback_url' => 'Callback URL',
+ },
+ )
+%>
+
+
+<SCRIPT TYPE="text/javascript">
+ var gatewayNamespace = new Array;
+
+% foreach my $module ( sort { lc($a) cmp lc ($b) } keys %modules ) {
+ gatewayNamespace.push('<% $modules{$module} %>')
% }
+ // document.getElementById('gateway_namespace').value = gatewayNamespace[0];
+ function setNamespace(what) {
+ document.getElementById('gateway_namespace').value =
+ gatewayNamespace[what.selectedIndex];
+ }
- </TD>
-</TR>
-
-<TR>
- <TH ALIGN="right">Username: </TH>
- <TD><INPUT TYPE="text" NAME="gateway_username" VALUE="<% $payment_gateway->gateway_username %>"></TD>
-</TR>
-
-<TR>
- <TH ALIGN="right">Password: </TH>
- <TD><INPUT TYPE="text" NAME="gateway_password" VALUE="<% $payment_gateway->gateway_password %>"></TD>
-</TR>
-
-<TR>
- <TH ALIGN="right">Action: </TH>
- <TD>
- <SELECT NAME="gateway_action" SIZE=1>
-% foreach my $action (
-% 'Normal Authorization',
-% 'Authorization Only',
-% 'Authorization Only, Post Authorization',
-% ) {
-%
-
- <OPTION VALUE="<% $action %>"<% $action eq $payment_gateway->gateway_action ? ' SELECTED' : '' %>><% $action %>
-% }
-
- </SELECT>
- </TD>
-</TR>
-
-<TR>
- <TH ALIGN="right">Options: (Name/Value pairs, one element per line)</TH>
- <TD>
- <TEXTAREA ROWS="5" NAME="gateway_options"><% join("\r", $payment_gateway->options ) %></TEXTAREA>
- </TD>
-</TR>
-
-</TABLE>
-
-<BR><INPUT TYPE="submit" VALUE="<% $payment_gateway->gatewaynum ? "Apply changes" : "Add gateway" %>">
- </FORM>
-
-<% include('/elements/footer.html') %>
+</SCRIPT>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-my $payment_gateway;
-if ( $cgi->param('error') ) {
- $payment_gateway = new FS::payment_gateway ( {
- map { $_, scalar($cgi->param($_)) } fields('payment_gateway')
- } );
-} elsif ( $cgi->keywords ) {
- my($query) = $cgi->keywords;
- $query =~ /^(\d+)$/;
- $payment_gateway = qsearchs( 'payment_gateway', { 'gatewaynum' => $1 } );
-} else { #adding
- $payment_gateway = new FS::payment_gateway {};
-}
-my $action = $payment_gateway->gatewaynum ? 'Edit' : 'Add';
-#my $hashref = $payment_gateway->hashref;
+my %modules = (
+ '2CheckOut' => 'Business::OnlinePayment',
+ 'AuthorizeNet' => 'Business::OnlinePayment',
+ 'BankOfAmerica' => 'Business::OnlinePayment', #deprecated?
+ 'Beanstream' => 'Business::OnlinePayment',
+ 'Capstone' => 'Business::OnlinePayment',
+ 'Cardstream' => 'Business::OnlinePayment',
+ 'CashCow' => 'Business::OnlinePayment',
+ 'CyberSource' => 'Business::OnlinePayment',
+ 'eSec' => 'Business::OnlinePayment',
+ 'eSelectPlus' => 'Business::OnlinePayment',
+ 'Exact' => 'Business::OnlinePayment',
+ 'iAuthorizer' => 'Business::OnlinePayment',
+ 'Ingotz' => 'Business::OnlinePayment',
+ 'InternetSecure' => 'Business::OnlinePayment',
+ 'Interswitchng' => 'Business::OnlineThirdPartyPayment',
+ 'IPaymentTPG' => 'Business::OnlinePayment',
+ 'IPPay' => 'Business::OnlinePayment',
+ 'Iridium' => 'Business::OnlinePayment',
+ 'Jettis' => 'Business::OnlinePayment',
+ 'LinkPoint' => 'Business::OnlinePayment',
+ 'MerchantCommerce' => 'Business::OnlinePayment',
+ 'Network1Financial' => 'Business::OnlinePayment',
+ 'OCV' => 'Business::OnlinePayment',
+ 'OpenECHO' => 'Business::OnlinePayment',
+ 'PayConnect' => 'Business::OnlinePayment',
+ 'PayflowPro' => 'Business::OnlinePayment',
+ 'PaymenTech' => 'Business::OnlinePayment',
+ 'PaymentsGateway' => 'Business::OnlinePayment',
+ 'PayPal' => 'Business::OnlinePayment',
+ 'PlugnPay ' => 'Business::OnlinePayment',
+ 'PPIPayMover ' => 'Business::OnlinePayment',
+ 'Protx ' => 'Business::OnlinePayment',
+ 'PXPost' => 'Business::OnlinePayment',
+ 'SecureHostingUPG' => 'Business::OnlinePayment',
+ 'Skipjack' => 'Business::OnlinePayment',
+ 'StGeorge' => 'Business::OnlinePayment',
+ 'SurePay' => 'Business::OnlinePayment',
+ 'TCLink' => 'Business::OnlinePayment',
+ 'TransactionCentral' => 'Business::OnlinePayment',
+ 'TransFirsteLink' => 'Business::OnlinePayment',
+ 'Vanco' => 'Business::OnlinePayment',
+ 'viaKLIX' => 'Business::OnlinePayment',
+ 'VirtualNet' => 'Business::OnlinePayment',
+ 'WesternACH' => 'Business::OnlinePayment',
+);
+
+my @actions = (
+ 'Normal Authorization',
+ 'Authorization Only',
+ 'Authorization Only, Post Authorization',
+ );
+
+my $fields = [
+ {
+ field => 'gateway_namespace',
+ type => 'hidden',
+ curr_value_callback => sub { my($cgi, $object, $fref) = @_;
+ $modules{$object->gateway_module}
+ || 'Business::OnlinePayment'
+ },
+ },
+ {
+ field => 'gateway_module',
+ type => 'select',
+ options => [ sort { lc($a) cmp lc ($b) } keys %modules ],
+ onchange => 'setNamespace',
+ },
+ 'gateway_username',
+ 'gateway_password',
+ {
+ field => 'gateway_action',
+ type => 'select',
+ options => \@actions,
+ },
+ 'gateway_callback_url',
+ {
+ field => 'gateway_options',
+ type => 'textarea',
+ curr_value_callback => sub { my($cgi, $object, $fref) = @_;
+ join("\r", $object->options );
+ },
+ },
+ ];
+
+my $field_callback = sub {
+ my ($cgi, $object, $field_hashref ) = @_;
+ if ($object->gatewaynum) {
+ if ( $field_hashref->{field} eq 'gateway_module' ) {
+ $field_hashref->{type} = 'fixed';
+ }
+ }
+};
</%init>
diff --git a/httemplate/edit/phone_device.html b/httemplate/edit/phone_device.html
new file mode 100644
index 0000000..a1aa166
--- /dev/null
+++ b/httemplate/edit/phone_device.html
@@ -0,0 +1,37 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Phone device',
+ 'table' => 'phone_device',
+ 'labels' => {
+ 'devicenum' => 'Device',
+ 'devicepart' => 'Device type',
+ 'mac_addr' => 'MAC address',
+ },
+ 'fields' => [ { 'field' => 'devicepart',
+ 'type' => 'select-table',
+ 'table' => 'part_device',
+ 'name_col' => 'devicename',
+ 'empty_label' =>'Select device type',
+ #'hashref' =>{ disabled => '' },
+ },
+ 'mac_addr',
+ { 'field' => 'svcnum',
+ 'type' => 'hidden',
+ },
+ ],
+ 'menubar' => [], #disable viewall
+ #'viewall_dir' => 'browse',
+ 'new_callback' => sub {
+ my( $cgi, $object ) = @_;
+ $object->svcnum( $cgi->param('svcnum') );
+ },
+ )
+%>
+<%init>
+
+# :/ needs agent-virt so you can't futz with arbitrary devices
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+
+</%init>
diff --git a/httemplate/edit/pkg_category.html b/httemplate/edit/pkg_category.html
index fdc8da6..a07dc58 100644
--- a/httemplate/edit/pkg_category.html
+++ b/httemplate/edit/pkg_category.html
@@ -3,11 +3,13 @@
'table' => 'pkg_category',
'fields' => [
'categoryname',
+ 'weight',
{ field=>'disabled', type=>'checkbox', value=>'Y', },
],
'labels' => {
'categorynum' => 'Category number',
'categoryname' => 'Category name',
+ 'weight' => 'Weight',
'disabled' => 'Disable category',
},
'viewall_dir' => 'browse',
diff --git a/httemplate/edit/prepay_credit.cgi b/httemplate/edit/prepay_credit.cgi
index 9e1c30b..ed404b7 100644
--- a/httemplate/edit/prepay_credit.cgi
+++ b/httemplate/edit/prepay_credit.cgi
@@ -97,14 +97,14 @@ tie my %multiplier, 'Tie::IxHash',
tie my %bytemultiplier, 'Tie::IxHash',
1 => 'bytes',
- 1000 => 'Kbytes',
- 1000000 => 'Mbytes',
- 1000000000 => 'Gbytes',
+ 1024 => 'Kbytes',
+ 1048576 => 'Mbytes',
+ 1073741824 => 'Gbytes',
;
$cgi->param('multiplier', '60') unless $cgi->param('multiplier');
-$cgi->param('upmultiplier', '1000000') unless $cgi->param('upmultiplier');
-$cgi->param('downmultiplier', '1000000') unless $cgi->param('downmultiplier');
-$cgi->param('totalmultiplier','1000000') unless $cgi->param('totalmultiplier');
+$cgi->param('upmultiplier', '1048576') unless $cgi->param('upmultiplier');
+$cgi->param('downmultiplier', '1048576') unless $cgi->param('downmultiplier');
+$cgi->param('totalmultiplier','1048576') unless $cgi->param('totalmultiplier');
</%init>
diff --git a/httemplate/edit/process/REAL_cust_pkg.cgi b/httemplate/edit/process/REAL_cust_pkg.cgi
index ebcb7e4..d4ba976 100755
--- a/httemplate/edit/process/REAL_cust_pkg.cgi
+++ b/httemplate/edit/process/REAL_cust_pkg.cgi
@@ -3,16 +3,23 @@
<% $cgi->redirect(popurl(2). "REAL_cust_pkg.cgi?". $cgi->query_string ) %>
%} else {
% my $custnum = $new->custnum;
-<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum#cust_pkg$pkgnum" ) %>
+% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+% ? ''
+% : ';show=packages';
+% my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag" ) %>
%}
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Edit customer package dates');
+ unless $curuser->access_right('Edit customer package dates');
my $pkgnum = $cgi->param('pkgnum') or die;
my $old = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
my %hash = $old->hash;
+$hash{'start_date'} = $cgi->param('start_date') ? str2time($cgi->param('start_date')) : '';
$hash{'setup'} = $cgi->param('setup') ? str2time($cgi->param('setup')) : '';
$hash{'bill'} = $cgi->param('bill') ? str2time($cgi->param('bill')) : '';
$hash{'last_bill'} =
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
index 097d382..f72ca0a 100755
--- a/httemplate/edit/process/cust_main.cgi
+++ b/httemplate/edit/process/cust_main.cgi
@@ -19,6 +19,8 @@ my $DEBUG = 0;
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+my $conf = new FS::Conf;
+
my $error = '';
#unmunge stuff
@@ -27,8 +29,7 @@ $cgi->param('tax','') unless defined $cgi->param('tax');
$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] );
-#my $payby = $cgi->param('payby');
-my $payby = $cgi->param('select'); # XXX key
+my $payby = $cgi->param('payby');
my %noauto = (
'CARD' => 'DCRD',
@@ -72,55 +73,83 @@ if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) {
);
}
-if ( $cgi->param('birthdate') && $cgi->param('birthdate') =~ /^([ 0-9\-\/]{0,10})$/) {
- my $conf = new FS::Conf;
- my $format = $conf->config('date_format') || "%m/%d/%Y";
- my $parser = DateTime::Format::Strptime->new(pattern => $format,
- time_zone => 'floating',
- );
- my $dt = $parser->parse_datetime($1);
- if ($dt) {
- $new->setfield('birthdate', $dt->epoch);
- $cgi->param('birthdate', $dt->epoch);
- } else {
-# $error ||= $cgi->param('birthdate') . " is an invalid birthdate:" . $parser->errmsg;
- $error ||= "Invalid birthdate: " . $cgi->param('birthdate') . ".";
- $cgi->param('birthdate', '');
+my %usedatetime = ( 'birthdate' => 1 );
+
+foreach my $dfield (qw( birthdate signupdate )) {
+
+ if ( $cgi->param($dfield) && $cgi->param($dfield) =~ /^([ 0-9\-\/]{0,10})$/) {
+
+ my $value = $1;
+ my $parsed = '';
+
+ if ( exists $usedatetime{$dfield} && $usedatetime{$dfield} ) {
+
+ my $format = $conf->config('date_format') || "%m/%d/%Y";
+ my $parser = DateTime::Format::Strptime->new( pattern => $format,
+ time_zone => 'floating',
+ );
+ my $dt = $parser->parse_datetime($value);
+ if ( $dt ) {
+ $parsed = $dt->epoch;
+ } else {
+ # $error ||= $cgi->param('birthdate') . " is an invalid birthdate:" . $parser->errmsg;
+ $error ||= "Invalid $dfield: $value";
+ }
+
+ } else {
+
+ $parsed = str2time($value)
+ or $error ||= "Invalid $dfield: $value";
+
+ }
+
+ $new->setfield( $dfield, $parsed );
+ $cgi->param( $dfield, $parsed );
+
}
+
}
$new->setfield('paid', $cgi->param('paid') )
if $cgi->param('paid');
+my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
+my @tax_exempt = grep { $cgi->param("tax_$_") eq 'Y' } @exempt_groups;
+
#perhaps this stuff should go to cust_main.pm
-my $cust_pkg = '';
-my $svc_acct = '';
if ( $new->custnum eq '' ) {
+ my $cust_pkg = '';
+ my $svc;
+
if ( $cgi->param('pkgpart_svcpart') ) {
+
my $x = $cgi->param('pkgpart_svcpart');
$x =~ /^(\d+)_(\d+)$/ or die "illegal pkgpart_svcpart $x\n";
my($pkgpart, $svcpart) = ($1, $2);
+ my $part_pkg = qsearchs('part_pkg', { 'pkgpart' => $pkgpart } );
#false laziness: copied from FS::cust_pkg::order (which should become a
#FS::cust_main method)
my(%part_pkg);
# generate %part_pkg
# $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart
my $agent = qsearchs('agent',{'agentnum'=> $new->agentnum });
- #my($type_pkgs);
- #foreach $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {
- # my($pkgpart)=$type_pkgs->pkgpart;
- # $part_pkg{$pkgpart}++;
- #}
- # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart
- my $pkgpart_href = $agent->pkgpart_hashref;
- #eslaf
-
- # this should wind up in FS::cust_pkg!
- $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum. ") can't ".
- "purchase pkgpart ". $pkgpart
- #unless $part_pkg{ $pkgpart };
- unless $pkgpart_href->{ $pkgpart };
+
+ if ( $agent ) {
+ # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart
+ my $pkgpart_href = $agent->pkgpart_hashref
+ if $agent;
+ #eslaf
+
+ # this should wind up in FS::cust_pkg!
+ $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum.
+ ") can't purchase pkgpart ". $pkgpart
+ #unless $part_pkg{ $pkgpart };
+ unless $pkgpart_href->{ $pkgpart }
+ || $agent->agentnum == $part_pkg->agentnum;
+ } else {
+ $error = 'Select agent';
+ }
$cust_pkg = new FS::cust_pkg ( {
#later 'custnum' => $custnum,
@@ -132,33 +161,52 @@ if ( $new->custnum eq '' ) {
#$error ||= $cust_svc->check;
- my %svc_acct = (
- 'svcpart' => $svcpart,
- 'username' => $cgi->param('username'),
- '_password' => $cgi->param('_password'),
- 'popnum' => $cgi->param('popnum'),
- );
- $svc_acct{'domsvc'} = $cgi->param('domsvc')
- if $cgi->param('domsvc');
+ my $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
+ my $svcdb = $part_svc->svcdb;
+
+ if ( $svcdb eq 'svc_acct' ) {
+
+ my %svc_acct = (
+ 'svcpart' => $svcpart,
+ 'username' => scalar($cgi->param('username')),
+ '_password' => scalar($cgi->param('_password')),
+ 'popnum' => scalar($cgi->param('popnum')),
+ );
+ $svc_acct{'domsvc'} = $cgi->param('domsvc')
+ if $cgi->param('domsvc');
+
+ $svc = new FS::svc_acct \%svc_acct;
+
+ #and just in case you were silly
+ $svc->svcpart($svcpart);
+ $svc->username($cgi->param('username'));
+ $svc->_password($cgi->param('_password'));
+ $svc->popnum($cgi->param('popnum'));
+
+ } elsif ( $svcdb eq 'svc_phone' ) {
+
+ my %svc_phone = (
+ 'svcpart' => $svcpart,
+ map { $_ => scalar($cgi->param($_)) }
+ qw( countrycode phonenum sip_password pin phone_name )
+ );
- $svc_acct = new FS::svc_acct \%svc_acct;
+ $svc = new FS::svc_phone \%svc_phone;
- #and just in case you were silly
- $svc_acct->svcpart($svcpart);
- $svc_acct->username($cgi->param('username'));
- $svc_acct->_password($cgi->param('_password'));
- $svc_acct->popnum($cgi->param('popnum'));
+ } else {
+ die "$svcdb not handled on new customer yet";
+ }
#$error ||= $svc_acct->check;
- } elsif ( $cgi->param('username') ) { #good thing to catch
- $error = "Can't assign username without a package!";
}
use Tie::RefHash;
tie my %hash, 'Tie::RefHash';
- %hash = ( $cust_pkg => [ $svc_acct ] ) if $cust_pkg;
- $error ||= $new->insert( \%hash, \@invoicing_list );
+ %hash = ( $cust_pkg => [ $svc ] ) if $cust_pkg;
+ $error ||= $new->insert( \%hash, \@invoicing_list,
+ 'tax_exemption' => \@tax_exempt,
+ );
my $conf = new FS::Conf;
if ( $conf->exists('backend-realtime') && ! $error ) {
@@ -201,7 +249,9 @@ if ( $new->custnum eq '' ) {
local($FS::cust_main::DEBUG) = $DEBUG if $DEBUG;
local($FS::Record::DEBUG) = $DEBUG if $DEBUG;
- $error ||= $new->replace($old, \@invoicing_list);
+ $error ||= $new->replace( $old, \@invoicing_list,
+ 'tax_exemption' => \@tax_exempt,
+ );
warn "$me returned from replace" if $DEBUG;
diff --git a/httemplate/edit/process/cust_main_attach.cgi b/httemplate/edit/process/cust_main_attach.cgi
new file mode 100644
index 0000000..98f4d09
--- /dev/null
+++ b/httemplate/edit/process/cust_main_attach.cgi
@@ -0,0 +1,99 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). 'cust_main_attach.cgi?'. $cgi->query_string ) %>
+%} else {
+% my $act = 'added';
+% $act = 'updated' if ($attachnum);
+% $act = 'purged' if($attachnum and $purge);
+% $act = 'undeleted' if($attachnum and $undelete);
+% $act = 'deleted' if($attachnum and $delete);
+<% header('Attachment ' . $act ) %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+my $error;
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die "Illegal custnum: ". $cgi->param('custnum');
+my $custnum = $1;
+
+$cgi->param('attachnum') =~ /^(\d*)$/
+ or die "Illegal attachnum: ". $cgi->param('attachnum');
+my $attachnum = $1;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $otaker = $curuser->name;
+$otaker = $curuser->username if ($otaker eq "User, Legacy");
+
+my $delete = $cgi->param('delete');
+my $undelete = $cgi->param('undelete');
+my $purge = $cgi->param('purge');
+
+my $new = new FS::cust_attachment ( {
+ attachnum => $attachnum,
+ custnum => $custnum,
+ _date => time,
+ otaker => $otaker,
+ disabled => '',
+});
+my $old;
+
+if($attachnum) {
+ $old = qsearchs('cust_attachment', { attachnum => $attachnum });
+ if(!$old) {
+ $error = "Attachnum '$attachnum' not found";
+ }
+ elsif($purge) { # do nothing
+ }
+ else {
+ map { $new->$_($old->$_) }
+ ('_date', 'otaker', 'body', 'disabled');
+ $new->filename($cgi->param('filename') || $old->filename);
+ $new->mime_type($cgi->param('mime_type') || $old->mime_type);
+ if($delete and not $old->disabled) {
+ $new->disabled(time);
+ }
+ if($undelete and $old->disabled) {
+ $new->disabled('');
+ }
+ }
+}
+else { # This is a new attachment, so require a file.
+
+ my $filename = $cgi->param('file');
+ if($filename) {
+ $new->filename($filename);
+ $new->mime_type($cgi->uploadInfo($filename)->{'Content-Type'});
+
+ local $/;
+ my $fh = $cgi->upload('file');
+ $new->body(<$fh>);
+ }
+ else {
+ $error = 'No file uploaded';
+ }
+}
+my $action = 'Add';
+$action = 'Edit' if $attachnum;
+$action = 'Delete' if $attachnum and $delete;
+$action = 'Undelete' if $attachnum and $undelete;
+$action = 'Purge' if $attachnum and $purge;
+
+$error = 'access denied' unless $curuser->access_right($action . ' attachment');
+
+if(!$error) {
+ if($old and $old->disabled and $purge) {
+ $error = $old->delete;
+ }
+ elsif($old) {
+ $error = $new->replace($old);
+ }
+ else {
+ $error = $new->insert;
+ }
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_main_county-collapse.cgi b/httemplate/edit/process/cust_main_county-collapse.cgi
index a917825..18bd1fd 100755
--- a/httemplate/edit/process/cust_main_county-collapse.cgi
+++ b/httemplate/edit/process/cust_main_county-collapse.cgi
@@ -1,44 +1,37 @@
-%
-%
-%my($query) = $cgi->keywords;
-%$query =~ /^(\d+)$/ or die "Illegal taxnum!";
-%my $taxnum = $1;
-%my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } )
-% or die "Unknown taxnum $taxnum";
-%
-%#really should do this in a .pm & start transaction
-%
-%foreach my $delete ( qsearch('cust_main_county', {
-% 'country' => $cust_main_county->country,
-% 'state' => $cust_main_county->state
-% } ) ) {
-%# unless ( qsearch('cust_main',{
-%# 'state' => $cust_main_county->getfield('state'),
-%# 'county' => $cust_main_county->getfield('county'),
-%# 'country' => $cust_main_county->getfield('country'),
-%# } ) ) {
-% my $error = $delete->delete;
-% die $error if $error;
-%# } else {
-% #should really fix the $cust_main record
-%# }
-%
-%}
-%
-%$cust_main_county->taxnum('');
-%$cust_main_county->county('');
-%my $error = $cust_main_county->insert;
-%die $error if $error;
-%
-%print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi");
-%
-%
+<% $cgi->redirect(popurl(3). "browse/cust_main_county.cgi") %>
<%init>
-#this isn't actually linked from anywhere just now, but it will be again soon
-
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ or die "Illegal taxnum!";
+my $taxnum = $1;
+my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } )
+ or die "Unknown taxnum $taxnum";
+
+#really should do this in a .pm & start transaction
+
+foreach my $delete ( qsearch('cust_main_county', {
+ 'country' => $cust_main_county->country,
+ 'state' => $cust_main_county->state
+ } ) ) {
+# unless ( qsearch('cust_main',{
+# 'state' => $cust_main_county->getfield('state'),
+# 'county' => $cust_main_county->getfield('county'),
+# 'country' => $cust_main_county->getfield('country'),
+# } ) ) {
+ my $error = $delete->delete;
+ die $error if $error;
+# } else {
+ #should really fix the $cust_main record
+# }
+
+}
+
+$cust_main_county->taxnum('');
+$cust_main_county->county('');
+my $error = $cust_main_county->insert;
+die $error if $error;
</%init>
diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi
index 647f6fc..a310c53 100755
--- a/httemplate/edit/process/cust_pay.cgi
+++ b/httemplate/edit/process/cust_pay.cgi
@@ -7,7 +7,7 @@
% if ( $cgi->param('apply') eq 'yes' ) {
% my $cust_main = qsearchs('cust_main', { 'custnum' => $linknum })
% or die "unknown custnum $linknum";
-% $cust_main->apply_payments;
+% $cust_main->apply_payments( 'manual' => 1 );
% }
% if ( $link eq 'popup' ) {
%
@@ -46,7 +46,9 @@ my $new = new FS::cust_pay ( {
_date => $_date,
map {
$_, scalar($cgi->param($_));
- } qw(paid payby payinfo paybatch)
+ } qw( paid payby payinfo paybatch
+ pkgnum
+ )
#} fields('cust_pay')
} );
diff --git a/httemplate/edit/process/cust_tax_adjustment.html b/httemplate/edit/process/cust_tax_adjustment.html
new file mode 100644
index 0000000..204b5b9
--- /dev/null
+++ b/httemplate/edit/process/cust_tax_adjustment.html
@@ -0,0 +1,41 @@
+% if ( $error ) {
+% $cgi->param('error', $error );
+<% $cgi->redirect($p.'cust_tax_adjustment.html?'. $cgi->query_string) %>
+% } else {
+<% header("Tax adjustment added") %>
+ <SCRIPT TYPE="text/javascript">
+ //window.top.location.reload();
+ parent.cClick();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Add customer tax adjustment');
+
+my $error = '';
+my $conf = new FS::conf;
+my $param = $cgi->Vars;
+
+$param->{"custnum"} =~ /^(\d+)$/
+ or $error .= "Illegal customer number " . $param->{"custnum"} . " ";
+my $custnum = $1;
+
+$param->{"amount"} =~ /^\s*(\d*(?:\.?\d{1,2}))\s*$/
+ or $error .= "Illegal amount " . $param->{"amount"} . " ";
+my $amount = $1;
+
+unless ( $error ) {
+
+ my $cust_tax_adjustment = new FS::cust_tax_adjustment {
+ 'custnum' => $custnum,
+ 'taxname' => $param->{'taxname'},
+ 'amount' => $amount,
+ 'comment' => $param->{'comment'},
+ };
+ $error = $cust_tax_adjustment->insert;
+
+}
+
+</%init>
diff --git a/httemplate/edit/process/domreg.cgi b/httemplate/edit/process/domreg.cgi
new file mode 100755
index 0000000..a95474e
--- /dev/null
+++ b/httemplate/edit/process/domreg.cgi
@@ -0,0 +1,62 @@
+%if ($error) {
+% $cgi->param('error', $error);
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('op') =~ /^(register|transfer|revoke|renew)$/ or die "Illegal operation";
+my $operation = $1;
+#my($query) = $cgi->keywords;
+#$query =~ /^(\d+)$/;
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum = $1;
+my $svc_domain = qsearchs({
+ 'select' => 'svc_domain.*',
+ 'table' => 'svc_domain',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => {'svcnum'=>$svcnum},
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Unknown svcnum" unless $svc_domain;
+
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } );
+die "Unknown svcpart" unless $part_svc;
+
+my $error = '';
+
+my @exports = $part_svc->part_export();
+
+my $registrar;
+my $export;
+
+# Find the first export that does domain registration
+foreach (@exports) {
+ $export = $_ if $_->can('registrar');
+}
+
+my $period = 1; # Current OpenSRS export can only handle 1 year registrations
+
+# If we have a domain registration export, get the registrar object
+if ($export) {
+ if ($operation eq 'register') {
+ $error = $export->register( $svc_domain, $period );
+ } elsif ($operation eq 'transfer') {
+ $error = $export->transfer( $svc_domain );
+ } elsif ($operation eq 'revoke') {
+ $error = $export->revoke( $svc_domain );
+ } elsif ($operation eq 'renew') {
+ $cgi->param('period') =~ /^(\d+)$/ or die "Illegal renewal period!";
+ $period = $1;
+ $error = $export->renew( $svc_domain, $period );
+ }
+}
+
+</%init>
diff --git a/httemplate/edit/process/elements/ApplicationCommon.html b/httemplate/edit/process/elements/ApplicationCommon.html
index 2782dc2..e0c5bd7 100644
--- a/httemplate/edit/process/elements/ApplicationCommon.html
+++ b/httemplate/edit/process/elements/ApplicationCommon.html
@@ -72,6 +72,6 @@ my $new;
#}
-my $error = $new->insert;
+my $error = $new->insert( 'manual' => 1 );
</%init>
diff --git a/httemplate/edit/process/part_device.html b/httemplate/edit/process/part_device.html
new file mode 100644
index 0000000..2b7e1da
--- /dev/null
+++ b/httemplate/edit/process/part_device.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'part_device',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/part_export.cgi b/httemplate/edit/process/part_export.cgi
index b5f82e8..209419f 100644
--- a/httemplate/edit/process/part_export.cgi
+++ b/httemplate/edit/process/part_export.cgi
@@ -16,7 +16,8 @@ my $old = qsearchs('part_export', { 'exportnum'=>$exportnum } ) if $exportnum;
#fixup options
#warn join('-', split(',',$cgi->param('options')));
my %options = map {
- my $value = $cgi->param($_);
+ my @values = $cgi->param($_);
+ my $value = scalar(@values) > 1 ? join (' ', @values) : $values[0];
$value =~ s/\r\n/\n/g; #browsers? (textarea)
$_ => $value;
} split(',', $cgi->param('options'));
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
index 96c5b36..019224c 100755
--- a/httemplate/edit/process/part_pkg.cgi
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -93,6 +93,7 @@ my $args_callback = sub {
}
( $optionname => $value );
}
+ grep { $_ !~ /^report_option_/ }
@options;
foreach ( split(',', $cgi->param('taxproductnums') ) ) {
@@ -102,6 +103,11 @@ my $args_callback = sub {
$options{"usage_taxproductnum_$_"} = $value;
}
+ foreach ( $cgi->param('report_option') ) {
+ $error ||= "Illegal optional report class: $_" unless ( $_ =~ /^\d*$/ );
+ $options{"report_option_$_"} = 1;
+ }
+
$options{$_} = scalar( $cgi->param($_) )
for (qw( setup_fee recur_fee ));
@@ -134,7 +140,13 @@ my $args_callback = sub {
my $redirect_callback = sub {
#my( $cgi, $new ) = @_;
return '' unless $custnum;
- popurl(3). "view/cust_main.cgi?keywords=$custnum;dummy=";
+ my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+ ? ''
+ : ';show=packages';
+ #my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment
+
+ #can we link back to the specific customized package? it would be nice...
+ popurl(3). "view/cust_main.cgi?custnum=$custnum$show;dummy=";
};
#these should probably move to @args above and be processed by part_pkg.pm...
@@ -152,16 +164,28 @@ my @process_m2m = (
'target_table' => 'part_pkg',
'base_field' => 'src_pkgpart',
'target_field' => 'dst_pkgpart',
- 'hashref' => { 'link_type' => 'bill' },
- 'params' => [ map $cgi->param($_), grep /^bill_dst_pkgpart/, $cgi->param ],
- },
- { 'link_table' => 'part_pkg_link',
- 'target_table' => 'part_pkg',
- 'base_field' => 'src_pkgpart',
- 'target_field' => 'dst_pkgpart',
- 'hashref' => { 'link_type' => 'svc' },
- 'params' => [ map $cgi->param($_), grep /^svc_dst_pkgpart/, $cgi->param ],
+ 'hashref' => { 'link_type' => 'svc', 'hidden' => '' },
+ 'params' => [ map $cgi->param($_),
+ grep /^svc_dst_pkgpart/, $cgi->param
+ ],
},
+ map {
+ my $hidden = $_;
+ { 'link_table' => 'part_pkg_link',
+ 'target_table' => 'part_pkg',
+ 'base_field' => 'src_pkgpart',
+ 'target_field' => 'dst_pkgpart',
+ 'hashref' => { 'link_type' => 'bill', 'hidden' => $hidden },
+ 'params' => [ map { $cgi->param($_) }
+ grep { my $param = "bill_dst_pkgpart__hidden";
+ my $digit = '';
+ (($digit) = /^bill_dst_pkgpart(\d+)/ ) &&
+ $cgi->param("$param$digit") eq $hidden;
+ }
+ $cgi->param
+ ],
+ },
+ } ( '', 'Y' ),
);
foreach my $override_class ($cgi->param) {
diff --git a/httemplate/edit/process/part_pkg_report_option.html b/httemplate/edit/process/part_pkg_report_option.html
new file mode 100644
index 0000000..052aabd
--- /dev/null
+++ b/httemplate/edit/process/part_pkg_report_option.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'part_pkg_report_option',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/part_pkg_taxclass.html b/httemplate/edit/process/part_pkg_taxclass.html
index 8f149bb..b37279f 100644
--- a/httemplate/edit/process/part_pkg_taxclass.html
+++ b/httemplate/edit/process/part_pkg_taxclass.html
@@ -1,53 +1,17 @@
-% if ( $error ) {
-% $cgi->param('error', $error);
-<% $cgi->redirect(popurl(2). "part_pkg_taxclass.html?". $cgi->query_string ) %>
-%} else {
-<% $cgi->redirect(popurl(3). "browse/cust_main_county.cgi?taxclass=". uri_escape($part_pkg_taxclass->taxclass) ) %>
-%}
+<% include( 'elements/process.html',
+ 'table' => 'part_pkg_taxclass',
+ 'redirect' => sub {
+ my( $cgi, $part_pkg_taxclass ) = @_;
+
+ popurl(3). 'browse/cust_main_county.cgi?'.
+ 'taxclass='. uri_escape($part_pkg_taxclass->taxclass).
+ ';dummy=';
+ },
+ )
+%>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-my $part_pkg_taxclass = new FS::part_pkg_taxclass {
- 'taxclass' => $cgi->param('taxclass'),
-};
-
-#maybe this whole thing should be in a transaction. at some point, no biggie
-#none of the follow-up stuff will fail unless there's a more serious problem
-#than a hanging record in part_pkg_taxclass...
-
-my $error = $part_pkg_taxclass->insert;
-
-unless ( $error ) {
- #auto-add the new taxclass to any regions that have taxclasses already
-
- my $sth = dbh->prepare("
- SELECT country, state, county FROM cust_main_county
- WHERE taxclass IS NOT NULL AND taxclass != ''
- GROUP BY country, state, county
- ") or die dbh->errstr;
- $sth->execute or die $sth->errstr;
-
- while ( my $row = $sth->fetchrow_hashref ) {
- warn "inserting for $row";
- my $cust_main_county = new FS::cust_main_county {
- 'country' => $row->{country},
- 'state' => $row->{state},
- 'county' => $row->{county},
- 'tax' => 0,
- 'taxclass' => $part_pkg_taxclass->taxclass,
- #exempt_amount
- #taxname
- #setuptax
- #recurtax
- };
- $error = $cust_main_county->insert;
- #last if $error;
- die $error if $error;
- }
-
-
-}
-
</%init>
diff --git a/httemplate/edit/process/payment_gateway.html b/httemplate/edit/process/payment_gateway.html
index b16bc3d..812c988 100644
--- a/httemplate/edit/process/payment_gateway.html
+++ b/httemplate/edit/process/payment_gateway.html
@@ -1,35 +1,22 @@
-%if ( $error ) {
-% $cgi->param('error', $error);
-<% $cgi->redirect(popurl(2). "payment_gateway.html?". $cgi->query_string ) %>
-%} else {
-<% $cgi->redirect(popurl(3). "browse/payment_gateway.html") %>
-%}
+<% include( 'elements/process.html',
+ 'table' => 'payment_gateway',
+ 'viewall_dir' => 'browse',
+ 'args_callback' => $args_callback,
+ )
+%>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-my $gatewaynum = $cgi->param('gatewaynum');
+my $args_callback = sub {
+ my ( $cgi, $new ) = @_;
-my $old = qsearchs('payment_gateway',{'gatewaynum'=>$gatewaynum}) if $gatewaynum;
+ my @options = split(/\r?\n/, $cgi->param('gateway_options') );
+ pop @options
+ if scalar(@options) % 2 && $options[-1] =~ /^\s*$/;
+ (@options)
+};
-my $new = new FS::payment_gateway ( {
- map {
- $_, scalar($cgi->param($_));
- } fields('payment_gateway')
-} );
-
-my @options = split(/\r?\n/, $cgi->param('gateway_options') );
-pop @options
- if scalar(@options) % 2 && $options[-1] =~ /^\s*$/;
-my %options = @options;
-
-my $error;
-if ( $gatewaynum ) {
- $error=$new->replace($old, \%options);
-} else {
- $error=$new->insert(\%options);
- $gatewaynum=$new->getfield('gatewaynum');
-}
</%init>
diff --git a/httemplate/edit/process/phone_device.html b/httemplate/edit/process/phone_device.html
new file mode 100644
index 0000000..df9d5e7
--- /dev/null
+++ b/httemplate/edit/process/phone_device.html
@@ -0,0 +1,18 @@
+<% include( 'elements/process.html',
+ 'table' => 'phone_device',
+ 'redirect' => sub {
+ my( $cgi, $phone_device ) = @_;
+ popurl(3).'view/svc_phone.cgi?'.
+ 'svcnum='. $phone_device->svcnum.
+ ';devicenum=';
+ },
+ )
+%>
+<%init>
+
+# :/ needs agent-virt so you can't futz with arbitrary devices
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/process/quick-charge.cgi b/httemplate/edit/process/quick-charge.cgi
index 8fa57dd..827530e 100644
--- a/httemplate/edit/process/quick-charge.cgi
+++ b/httemplate/edit/process/quick-charge.cgi
@@ -27,7 +27,7 @@ $param->{"custnum"} =~ /^(\d+)$/
or $error .= "Illegal customer number " . $param->{"custnum"} . " ";
my $custnum = $1;
-$param->{"amount"} =~ /^\s*(\d+(\.\d{1,2})?)\s*$/
+$param->{"amount"} =~ /^\s*(\d*(?:\.?\d{1,2}))\s*$/
or $error .= "Illegal amount " . $param->{"amount"} . " ";
my $amount = $1;
@@ -55,6 +55,12 @@ unless ( $error ) {
$error ||= $cust_main->charge( {
'amount' => $amount,
'quantity' => $quantity,
+ 'bill_now' => scalar($cgi->param('bill_now')),
+ 'invoice_terms' => scalar($cgi->param('invoice_terms')),
+ 'start_date' => ( scalar($cgi->param('start_date'))
+ ? str2time($cgi->param('start_date'))
+ : ''
+ ),
'pkg' => scalar($cgi->param('pkg')),
'setuptax' => scalar($cgi->param('setuptax')),
'taxclass' => scalar($cgi->param('taxclass')),
diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi
index 9c24743..7a0f082 100644
--- a/httemplate/edit/process/quick-cust_pkg.cgi
+++ b/httemplate/edit/process/quick-cust_pkg.cgi
@@ -3,12 +3,15 @@
<% $cgi->redirect(popurl(3). 'misc/order_pkg.html?'. $cgi->query_string ) %>
%} else {
% my $frag = "cust_pkg". $cust_pkg->pkgnum;
+% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+% ? ''
+% : ';show=packages';
<% header('Package ordered') %>
<SCRIPT TYPE="text/javascript">
// XXX fancy ajax rebuild table at some point, but a page reload will do for now
// XXX chop off trailing #target and replace... ?
- window.top.location = '<% popurl(3). "view/cust_main.cgi?keywords=$custnum;fragment=$frag#$frag" %>';
+ window.top.location = '<% popurl(3). "view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag" %>';
</SCRIPT>
@@ -16,8 +19,10 @@
%}
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Order customer package');
+ unless $curuser->access_right('Order customer package');
#untaint custnum (probably not necessary, searching for it is escape enough)
$cgi->param('custnum') =~ /^(\d+)$/
@@ -44,6 +49,10 @@ my $locationnum = $1;
my $cust_pkg = new FS::cust_pkg {
'custnum' => $custnum,
'pkgpart' => $pkgpart,
+ 'start_date' => ( scalar($cgi->param('start_date'))
+ ? str2time($cgi->param('start_date'))
+ : ''
+ ),
'refnum' => $refnum,
'locationnum' => $locationnum,
};
diff --git a/httemplate/edit/process/svc_domain.cgi b/httemplate/edit/process/svc_domain.cgi
index 9993a87..59b5180 100755
--- a/httemplate/edit/process/svc_domain.cgi
+++ b/httemplate/edit/process/svc_domain.cgi
@@ -18,8 +18,8 @@ my $svcnum = $1;
my $new = new FS::svc_domain ( {
map {
$_, scalar($cgi->param($_));
- #} qw(svcnum pkgnum svcpart domain action purpose)
- } ( fields('svc_domain'), qw( pkgnum svcpart action purpose ) )
+ #} qw(svcnum pkgnum svcpart domain action)
+ } ( fields('svc_domain'), qw( pkgnum svcpart action ) )
} );
my $error = '';
diff --git a/httemplate/edit/quick-charge.html b/httemplate/edit/quick-charge.html
index c18b2bc..c96fa6c 100644
--- a/httemplate/edit/quick-charge.html
+++ b/httemplate/edit/quick-charge.html
@@ -3,6 +3,11 @@
)
%>
+<LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
+
<% include('/elements/error.html') %>
<SCRIPT TYPE="text/javascript">
@@ -20,7 +25,7 @@ function validate_quick_charge () {
var pkg = document.QuickChargeForm.pkg.value;
var pkg_regex = /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/ ;
var amount = document.QuickChargeForm.amount.value;
- var amount_regex = /^\s*\$?\s*(\d+(\.\d{1,2})?)\s*$/ ;
+ var amount_regex = /^\s*\$?\s*(\d*(\.?\d{1,2}))\s*$/ ;
var rval = true;
if ( ! amount_regex.test(amount) ) {
@@ -53,6 +58,23 @@ function validate_quick_charge () {
return false;
}
+function bill_now_changed (what) {
+ var form = what.form;
+ if ( what.checked ) {
+ form.start_date_text.disabled = true;
+ form.start_date.style.backgroundColor = '#dddddd';
+ form.start_date_button.style.display = 'none';
+ form.start_date_button_disabled.style.display = '';
+ form.invoice_terms.disabled = false;
+ } else {
+ form.start_date_text.disabled = false;
+ form.start_date.style.backgroundColor = '#ffffff';
+ form.start_date_button.style.display = '';
+ form.start_date_button_disabled.style.display = 'none';
+ form.invoice_terms.disabled = true;
+ }
+}
+
</SCRIPT>
<FORM ACTION="process/quick-charge.cgi" NAME="QuickChargeForm" ID="QuickChargeForm" METHOD="POST" onsubmit="document.QuickChargeForm.submit.disabled=true;return validate_quick_charge();">
@@ -79,6 +101,58 @@ function validate_quick_charge () {
<% include('/elements/tr-select-pkg_class.html', 'curr_value' => $cgi->param('classnum') ) %>
+<TR>
+ <TD ALIGN="right">Invoice now</TD>
+ <TD>
+ <INPUT TYPE = "checkbox"
+ NAME = "bill_now"
+ VALUE = "1"
+ <% $cgi->param('bill_now') ? 'CHECKED' : '' %>
+ onChange = "bill_now_changed(this);"
+ >
+ with terms
+ <% include('/elements/select-terms.html',
+ 'curr_value' => scalar($cgi->param('invoice_terms')),
+ 'empty_value' => $default_terms,
+ 'disabled' => ( $cgi->param('bill_now') ? 0 : 1 ),
+ )
+ %>
+ </TD>
+</TR>
+
+%# false laziness w/misc/order_pkg.html
+<TR>
+ <TD ALIGN="right">Charge date </TD>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "start_date"
+ SIZE = 32
+ ID = "start_date_text"
+ VALUE = "<% $start_date %>"
+ <% $cgi->param('bill_now') ? 'STYLE = "background-color:#dddddd" DISABLED' : '' %>
+ >
+ <IMG SRC = "<%$fsurl%>images/calendar.png"
+ ID = "start_date_button"
+ TITLE = "Select date"
+ STYLE = "cursor:pointer<% $cgi->param('bill_now') ? ';display:none' : '' %>"
+ >
+ <IMG SRC = "<%$fsurl%>images/calendar-disabled.png"
+ ID = "start_date_button_disabled"
+ <% $cgi->param('bill_now') ? '' : 'STYLE="display:none"' %>
+ >
+ <FONT SIZE=-1>(leave blank to charge immediately)</FONT>
+ </TD>
+</TR>
+
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "start_date_text",
+ ifFormat: "%m/%d/%Y",
+ button: "start_date_button",
+ align: "BR"
+ });
+</SCRIPT>
+
<TR>
<TD ALIGN="right">Tax exempt </TD>
@@ -179,6 +253,11 @@ my $conf = new FS::Conf;
$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
my $custnum = $1;
+my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); #XXX agent-virt
+
+my $format = "%m/%d/%Y %T %z (%Z)"; #false laziness w/REAL_cust_pkg.cgi?
+my $start_date = $cust_main->next_bill_date;
+$start_date = $start_date ? time2str($format, $start_date) : '';
my $amount = '';
if ( $cgi->param('amount') =~ /^\s*\$?\s*(\d+(\.\d{1,2})?)\s*$/ ) {
@@ -194,4 +273,14 @@ $cgi->param('pkg') =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/
or die 'illegal description';
my $pkg = $1;
+my $default_terms;
+if ( $cust_main->invoice_terms ) {
+ $default_terms = 'Customer default ('. $cust_main->invoice_terms. ')';
+} else {
+ $default_terms =
+ 'Default ('.
+ ($conf->config('invoice_default_terms') || 'Payable upon receipt').
+ ')';
+}
+
</%init>
diff --git a/httemplate/edit/reg_code.cgi b/httemplate/edit/reg_code.cgi
index e57ac09..76790ab 100644
--- a/httemplate/edit/reg_code.cgi
+++ b/httemplate/edit/reg_code.cgi
@@ -18,7 +18,7 @@ registration codes for <B><% $agent->agent %></B> allowing the following package
% my $pkgpart = $part_pkg->pkgpart;
<INPUT TYPE="checkbox" NAME="pkgpart<% $pkgpart %>" <% $cgi->param("pkgpart$pkgpart") ? 'CHECKED' : '' %>>
- <% $part_pkg->pkg %> - <% $part_pkg->comment %>
+ <% $part_pkg->pkg_comment %>
<BR>
% }
diff --git a/httemplate/edit/router.cgi b/httemplate/edit/router.cgi
index 19e63b3..70eaa45 100755
--- a/httemplate/edit/router.cgi
+++ b/httemplate/edit/router.cgi
@@ -10,10 +10,12 @@
'fields' => [
{ 'field'=>'routername', 'type'=>'text', 'size'=>32 },
{ 'field'=>'agentnum', 'type'=>'select-agent' },
+ { 'field'=>'svcnum', 'type'=>'hidden' },
],
'error_callback' => $callback,
'edit_callback' => $callback,
'new_callback' => $callback,
+ 'html_table_bottom' => $html_table_bottom,
)
%>
<%init>
@@ -41,4 +43,12 @@ my $callback = sub {
}
};
+my $html_table_bottom = sub {
+ my $router = shift;
+ my $html = '';
+ foreach my $field ($router->virtual_fields) {
+ $html .= $router->pvf($field)->widget('HTML', 'edit', $router->get($field));
+ }
+ $html;
+};
</%init>
diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi
index 58283ef..b9a587d 100755
--- a/httemplate/edit/svc_acct.cgi
+++ b/httemplate/edit/svc_acct.cgi
@@ -168,7 +168,7 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
<TR>
- <TD ALIGN="right">GECOS</TD>
+ <TD ALIGN="right">Real Name</TD>
<TD>
<INPUT TYPE="text" NAME="finger" VALUE="<% $svc_acct->finger %>">
</TD>
diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi
index e60c76c..8a108f8 100644
--- a/httemplate/edit/svc_broadband.cgi
+++ b/httemplate/edit/svc_broadband.cgi
@@ -2,7 +2,7 @@
'post_url' => popurl(1). 'process/svc_broadband.cgi',
'name' => 'broadband service',
'table' => 'svc_broadband',
- 'labels' => { 'svcnum' => 'Service #',
+ 'labels' => { 'svcnum' => 'Service',
'description' => 'Description',
'ip_addr' => 'IP address',
'speed_down' => 'Download speed',
@@ -14,6 +14,7 @@
'longitude' => 'Longitude',
'altitude' => 'Altitude',
'vlan_profile' => 'VLAN profile',
+ 'performance_profile' => 'Performance profile',
'authkey' => 'Authentication key',
},
'fields' => \@fields,
@@ -34,7 +35,7 @@ my $conf = new FS::Conf;
my @fields = (
qw( description ip_addr speed_down speed_up blocknum ),
{ field=>'block_label', type=>'fixed' },
- qw( mac_addr latitude longitude altitude vlan_profile authkey )
+ qw( mac_addr latitude longitude altitude vlan_profile performance_profile authkey )
);
my $fixedblock = '';
diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi
index 56ba604..10079ce 100755
--- a/httemplate/edit/svc_domain.cgi
+++ b/httemplate/edit/svc_domain.cgi
@@ -7,17 +7,31 @@
<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
-<INPUT TYPE="radio" NAME="action" VALUE="N"<% $kludge_action eq 'N' ? ' CHECKED' : '' %>>New
+<% ntable("#cccccc",2) %>
+<TR>
+<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="<% $domain %>" SIZE=28 MAXLENGTH=63>
<BR>
+% if ($export) {
+Available top-level domains: <% $export->option('tlds') %>
+</TR>
-<INPUT TYPE="radio" NAME="action" VALUE="M"<% $kludge_action eq 'M' ? ' CHECKED' : '' %>>Transfer
+<TR>
+<INPUT TYPE="radio" NAME="action" VALUE="N"<% $kludge_action eq 'N' ? ' CHECKED' : '' %>>Register at <% $registrar->{'name'} %>
+<BR>
-<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="<% $domain %>" SIZE=28 MAXLENGTH=63>
+<INPUT TYPE="radio" NAME="action" VALUE="M"<% $kludge_action eq 'M' ? ' CHECKED' : '' %>>Transfer to <% $registrar->{'name'} %>
+<BR>
-<BR>Purpose/Description: <INPUT TYPE="text" NAME="purpose" VALUE="<% $purpose %>" SIZE=64>
+<INPUT TYPE="radio" NAME="action" VALUE="I"<% $kludge_action eq 'I' ? ' CHECKED' : '' %>>Registered elsewhere
-<P><INPUT TYPE="submit" VALUE="Submit">
+</TR>
+
+% }
+<TR>
+<P><INPUT TYPE="submit" VALUE="Submit">
+</TR>
+</TABLE>
</FORM>
<% include('/elements/footer.html') %>
@@ -27,7 +41,7 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
-my($svcnum, $pkgnum, $svcpart, $kludge_action, $purpose, $part_svc,
+my($svcnum, $pkgnum, $svcpart, $kludge_action, $part_svc,
$svc_domain);
if ( $cgi->param('error') ) {
@@ -38,7 +52,6 @@ if ( $cgi->param('error') ) {
$pkgnum = $cgi->param('pkgnum');
$svcpart = $cgi->param('svcpart');
$kludge_action = $cgi->param('action');
- $purpose = $cgi->param('purpose');
$part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
die "No part_svc entry!" unless $part_svc;
@@ -61,7 +74,6 @@ if ( $cgi->param('error') ) {
} else { #editing
$kludge_action = '';
- $purpose = '';
my($query) = $cgi->keywords;
$query =~ /^(\d+)$/ or die "unparsable svcnum";
$svcnum=$1;
@@ -82,6 +94,20 @@ my $action = $svcnum ? 'Edit' : 'Add';
my $svc = $part_svc->getfield('svc');
+my @exports = $part_svc->part_export();
+
+my $registrar;
+my $export;
+
+# Find the first export that does domain registration
+foreach (@exports) {
+ $export = $_ if $_->can('registrar');
+}
+# If we have a domain registration export, get the registrar object
+if ($export) {
+ $registrar = $export->registrar;
+}
+
my $otaker = getotaker;
my $domain = $svc_domain->domain;
diff --git a/httemplate/edit/svc_www.cgi b/httemplate/edit/svc_www.cgi
index eeb6f67..cd4db75 100644
--- a/httemplate/edit/svc_www.cgi
+++ b/httemplate/edit/svc_www.cgi
@@ -38,7 +38,7 @@ Service #<B><% $svcnum ? $svcnum : "(NEW)" %></B>
% foreach $_ (keys %svc_acct) {
<OPTION<% ($_ eq $usersvc) ? " SELECTED" : "" %> VALUE="<%$_%>"><% $svc_acct{$_} %>
% }
- <SELECT>
+ </SELECT>
</TD>
</TR>
% }
diff --git a/httemplate/elements/about_freeside.html b/httemplate/elements/about_freeside.html
new file mode 100644
index 0000000..8084583
--- /dev/null
+++ b/httemplate/elements/about_freeside.html
@@ -0,0 +1,19 @@
+<FONT SIZE="-2" STYLE="color:#999999">
+ <% include('/elements/popup_link.html',
+ 'action' => $fsurl.'docs/about.html',
+ 'label' => 'Freeside',
+ 'style' => 'color:#999999',
+ 'actionlabel' => 'About',
+ 'width' => 300,
+ 'height' => 360,
+ 'color' => '#7e0079',
+ 'scrolling' => 'no',
+ ) |n
+ %>&nbsp;v<% $FS::VERSION %><BR>
+ <A HREF="<% $conf->config('support-key') ? "http://www.freeside.biz/mediawiki/index.php/Supported:Documentation" : "http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation" %>" TARGET="_blank" STYLE="color:#999999">Documentation</A>
+</FONT>
+<%init>
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/elements/about_rt.html b/httemplate/elements/about_rt.html
new file mode 100644
index 0000000..e3ee140
--- /dev/null
+++ b/httemplate/elements/about_rt.html
@@ -0,0 +1,13 @@
+% if ( $conf->config('ticket_system') eq 'RT_Internal' ) {
+% eval "use RT;";
+
+<FONT SIZE="-2" STYLE="color:#999999">
+ <A HREF="http://www.bestpractical.com/rt" TARGET="_blank" STYLE="color:#999999">RT<A>&nbsp;v<% $RT::VERSION %><BR>
+ <A HREF="http://wiki.bestpractical.com/" TARGET="_blank" STYLE="color:#999999">Documentation</A>
+</FONT>
+% }
+<%init>
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/elements/checkbox.html b/httemplate/elements/checkbox.html
new file mode 100644
index 0000000..5176070
--- /dev/null
+++ b/httemplate/elements/checkbox.html
@@ -0,0 +1,19 @@
+<% $opt{'prefix'} %><INPUT TYPE = "checkbox"
+ NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id} %>"
+ VALUE = "<% $opt{value} %>"
+ <% $opt{curr_value} eq $opt{value}
+ ? ' CHECKED'
+ : ''
+ %>
+ <% $onchange %>
+ ><% $opt{'postfix'} %>
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+</%init>
diff --git a/httemplate/elements/checkboxes.html b/httemplate/elements/checkboxes.html
index 1262245..b120ada 100644
--- a/httemplate/elements/checkboxes.html
+++ b/httemplate/elements/checkboxes.html
@@ -10,8 +10,9 @@ Example:
'names_list' => [ 'value',
'other value',
- [ 'complex value' => { 'desc' => "Add'l description",
- 'note' => '&nbsp;*',
+ [ 'complex value' => { 'label' => 'Display value',
+ 'desc' => "Add'l description",
+ 'note' => '&nbsp;*',
}
],
],
@@ -40,7 +41,10 @@ Example:
% foreach my $item ( @{ $opt{'names_list'} } ) {
%
% my $name = ref($item) ? $item->[0] : $item;
-% ( my $display = $name ) =~ s/ /&nbsp;/g;
+% my $display = ( ref($item) && $item->[1]{label} )
+% ? $item->[1]{label}
+% : $name;
+% $display =~ s/ /&nbsp;/g;
% $display .= $item->[1]{note} if ref($item) && $item->[1]{note};
% my $desc = ref($item) && $item->[1]{desc} ? $item->[1]{desc} : '';
%
diff --git a/httemplate/elements/file-upload.html b/httemplate/elements/file-upload.html
index c8b026d..7e2eeef 100644
--- a/httemplate/elements/file-upload.html
+++ b/httemplate/elements/file-upload.html
@@ -55,7 +55,7 @@
% foreach (@field) {
<TR>
- <TH ALIGN="right"><% shift @label %></TH>
+ <TH ALIGN="<% $param{'label_align'} || 'right' %>"><% shift @label %></TH>
<TD><INPUT TYPE="file" NAME="<% $_ %>" /></TD>
</TR>
% }
diff --git a/httemplate/elements/header-popup.html b/httemplate/elements/header-popup.html
index 68be108..d74581b 100644
--- a/httemplate/elements/header-popup.html
+++ b/httemplate/elements/header-popup.html
@@ -1,10 +1,3 @@
-%
-% my($title, $menubar) = ( shift, shift ); #$menubar is unused here though
-% my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
-% my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section
-% my $conf = new FS::Conf;
-%
-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
@@ -21,4 +14,30 @@
<FONT SIZE=6>
<CENTER><% $title %></CENTER>
</FONT>
+
+% unless ( $nobr ) {
<BR><!--<BR>-->
+% }
+
+<%init>
+
+my( $title, $menubar, $etc, $head ) = ( '', '', '', '' );
+#my( $nobr, $nocss ) = ( 0, 0 );
+my $nobr = 0;
+if ( ref($_[0]) ) {
+ my $opt = shift;
+ $title = $opt->{title};
+ $menubar = $opt->{menubar};
+ $etc = $opt->{etc};
+ $head = $opt->{head};
+ $nobr = $opt->{nobr};
+# $nocss = $opt->{nocss};
+} else {
+ ($title, $menubar) = ( shift, shift );
+ $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
+ $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section
+}
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html
index 8e902f0..b9ddc73 100644
--- a/httemplate/elements/header.html
+++ b/httemplate/elements/header.html
@@ -1,4 +1,26 @@
+<%doc>
+
+Example:
+
+ include( '/elements/header.html',
+ {
+ 'title' => 'Title',
+ 'menubar' => \@menubar,
+ 'etc' => '', #included in <BODY> tag, for things like onLoad=
+ 'head' => '', #included before closing </HEAD> tag
+ 'nobr' => 0, #1 for no <BR><BR> after the title
+ }
+ );
+
+ #old-style
+ include( '/elements/header.html', 'Title', $menubar, $etc, $head);
+
+
+</%doc>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+%#<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+%# above is what RT declares, should we switch now? hopefully no glitches result
+%# or just fuck it, XHTML died anyway, HTML 5 or bust?
<HTML>
<HEAD>
<TITLE>
@@ -10,6 +32,7 @@
<% include('menu.html', 'freeside_baseurl' => $fsurl,
'position' => $menu_position,
+ 'nocss' => $nocss,
) |n
%>
@@ -17,7 +40,7 @@
<SCRIPT TYPE="text/javascript">
function clearhint_search_cust (what) {
- if ( what.value == '(cust #, name, company or phone)' )
+ if ( what.value == '(cust #, name, company or contact phone)' )
what.value = '';
}
@@ -32,7 +55,7 @@
}
function clearhint_search_svc (what) {
- if ( what.value == '(user, email, ip, mac, or domain)' )
+ if ( what.value == '(user, email, ip, mac, domain or service phone)' )
what.value = '';
}
@@ -48,49 +71,16 @@
<BODY <% $menu_position eq 'left' ? qq( BACKGROUND="${fsurl}images/background-cheat.png" ) : ' BGCOLOR="#e8e8e8" ' %> <% $etc |n %> STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0">
<table width="100%" CELLPADDING=0 CELLSPACING=0 STYLE="padding-left:0; padding-right:4">
<tr>
- <td rowspan=2 BGCOLOR="#ffffff"><IMG BORDER=0 ALT="freeside" SRC="<%$fsurl%>view/REAL_logo.cgi"></td>
- <td align=left rowspan=2 BGCOLOR="#ffffff"> <!-- valign="top" -->
+ <td BGCOLOR="#ffffff"><IMG BORDER=0 ALT="freeside" HEIGHT="36" SRC="<%$fsurl%>view/REAL_logo.cgi"></td>
+ <td align=left BGCOLOR="#ffffff"> <!-- valign="top" -->
<font size=6><% $company_name || 'ExampleCo' %></font>
</td>
- <td align=right valign=top BGCOLOR="#ffffff"><FONT SIZE="-1">Logged in as <b><% getotaker %>&nbsp;</b><br></FONT><FONT SIZE="-2"><a href="<%$fsurl%>pref/pref.html">Preferences</a>&nbsp;<BR></FONT>
- </td>
- </tr>
- <tr>
- <td align=right valign=bottom BGCOLOR="#ffffff">
-
- <table>
- <tr>
- <td align=right BGCOLOR="#ffffff">
- <FONT SIZE="-2">
- <% include('/elements/popup_link.html',
- 'action' => $fsurl.'docs/about.html',
- 'label' => 'Freeside',
- 'actionlabel' => 'About',
- 'width' => 300,
- 'height' => 360,
- 'color' => '#7e0079',
- 'scrolling' => 'no',
- ) |n
- %>&nbsp;v<% $FS::VERSION %><BR>
- <A HREF="<% $conf->config('support-key') ? "http://www.freeside.biz/mediawiki/index.php/Supported:Documentation" : "http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation" %>" TARGET="_blank">Documentation</A><BR>
- </FONT>
- </td>
-% if ( $conf->config('ticket_system') eq 'RT_Internal' ) {
-% eval "use RT;";
-
- <td bgcolor=#000000></td>
- <td align=left>
- <FONT SIZE="-2">
- <A HREF="http://www.bestpractical.com/rt" TARGET="_blank">RT<A>&nbsp;v<% $RT::VERSION %><BR>
- <A HREF="http://wiki.bestpractical.com/" TARGET="_blank">Documentation</A><BR>
- </FONT>
- </td>
-% }
-
-
- </tr>
- </table>
-
+ <td align=right valign=top BGCOLOR="#ffffff"><FONT SIZE="-1">Logged in as <b><% getotaker %>&nbsp;</b><br></FONT><FONT SIZE="-2"><a href="<%$fsurl%>pref/pref.html" STYLE="color: #000000">Preferences</a>
+% if ( $conf->config("ticket_system")
+% && FS::TicketSystem->access_right(\%session, 'ModifySelf') ) {
+ | <a href="<%$fsurl%>rt/User/Prefs.html" STYLE="color: #000000">Ticketing preferences</a>
+% }
+ <BR></FONT>
</td>
</tr>
</table>
@@ -104,9 +94,16 @@ input.fsblackbutton {
border-left-color:#cccccc;
border-right-color:#aaaaaa;
border-bottom-color:#aaaaaa;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
font-weight:bold;
padding-left:12px;
padding-right:12px;
+ padding-top:0px;
+ padding-bottom:0px;
+ margin-left:0px;
+ margin-right:0px;
+ margin-top:2px;
+ margin-bottom:0px;
overflow:visible;
filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
}
@@ -119,12 +116,40 @@ input.fsblackbuttonselected {
border-left-color:#cccccc;
border-right-color:#aaaaaa;
border-bottom-color:#aaaaaa;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
font-weight:bold;
padding-left:12px;
padding-right:12px;
+ padding-top:0px;
+ padding-bottom:0px;
+ margin-left:0px;
+ margin-right:0px;
+ margin-top:2px;
+ margin-bottom:0px;
overflow:visible;
filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
}
+
+input.fstext {
+ border: 2px inset #eee;
+ /*border-top-color:#aaaaaa;
+ border-left-color:#aaaaaa;
+ border-right-color:#cccccc;
+ border-bottom-color:#cccccc;
+ */
+ vertical-align:bottom;
+ text-align:right;
+ font-family: Arial,Verdana,Helvetica,sans-serif;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ margin-left:0px;
+ margin-right:0px;
+ margin-top:0px;
+ margin-bottom:1px;
+}
+
</style>
<TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=0>
@@ -136,12 +161,22 @@ input.fsblackbuttonselected {
<TR>
- <TD COLSPAN="6" WIDTH="100%" STYLE="padding:0">
+ <TD COLSPAN="4" WIDTH="100%" STYLE="padding:0" BGCOLOR="#000000">
<SCRIPT TYPE="text/javascript">
document.write(myBar);
</SCRIPT>
</TD>
+
+ <TD COLSPAN="2" ALIGN="right" STYLE="padding:0px 8px 0px 0px" BGCOLOR="#000000">
+ <TABLE CELLSPACING=0 CELLPADDING=0 BGCOLOR="#000000" BORDER=0>
+ <TR>
+ <TD ALIGN="right" STYLE="padding-right:3px;padding-bottom:1px;border-right:1px solid #999999"><% include('/elements/about_freeside.html') |n %></TD>
+ <TD ALIGN="left" STYLE="padding-left:3px;padding-bottom:1px"><% include('/elements/about_rt.html') |n %></TD>
+ </TR>
+ </TABLE>
+ </TD>
+
</TR>
<TR>
@@ -159,17 +194,11 @@ input.fsblackbuttonselected {
<TR>
<TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
- <FORM ACTION="<%$fsurl%>edit/cust_main.cgi" METHOD="GET" STYLE="margin:0">
- <INPUT TYPE="submit" VALUE="New customer" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="vertical-align:bottom; font-size:100%">
- </FORM>
- </TD>
-
- <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
% if ( $curuser->access_right('List customers') ) {
<FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0">
- <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name, company or phone)" SIZE="28" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
- <A HREF="<%$fsurl%>search/report_cust_main.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
- <INPUT TYPE="submit" VALUE="Search customers" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name, company or contact phone)" SIZE="37" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" CLASS="fstext"><BR>
+ <A HREF="<%$fsurl%>search/report_cust_main.html" STYLE="color: #ffffff; font-size: 11px">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search customers" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px">
</FORM>
% }
</TD>
@@ -178,9 +207,9 @@ input.fsblackbuttonselected {
% if ( $conf->exists('address2-search') ) {
<FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0;display:inline">
<INPUT TYPE="hidden" NAME="address2_on" VALUE="1">
- <INPUT NAME="address2_text" TYPE="text" VALUE="(Unit #)" SIZE="4" onFocus="clearhint_search_address2(this);" onClick="clearhint_search_address2(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
+ <INPUT NAME="address2_text" TYPE="text" VALUE="(Unit #)" SIZE="4" onFocus="clearhint_search_address2(this);" onClick="clearhint_search_address2(this);" CLASS="fstext">
<BR>
- <INPUT TYPE="submit" VALUE="Search units" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
+ <INPUT TYPE="submit" VALUE="Search units" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px;padding-left:2px;padding-right:2px">
</FORM>
% }
</TD>
@@ -189,32 +218,32 @@ input.fsblackbuttonselected {
% if ( $curuser->access_right('View invoices') ) {
<FORM ACTION="<%$fsurl%>search/cust_bill.html" METHOD="GET" STYLE="margin:0;display:inline">
- <INPUT NAME="invnum" TYPE="text" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
+ <INPUT NAME="invnum" TYPE="text" VALUE="(inv #)" SIZE="5" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" CLASS="fstext">
% if ( $curuser->access_right('List invoices') ) {
-
- <A HREF="<%$fsurl%>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
+ <A HREF="<%$fsurl%>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 11px">Adv</A>
% }
-
<BR>
- <INPUT TYPE="submit" VALUE="Search invoices" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ <INPUT TYPE="submit" VALUE="Search invoices" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px;padding-left:1px;padding-right:1px">
</FORM>
% }
</TD>
<TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
+% if ( $curuser->access_right('View customer services') ) {
<FORM ACTION="<%$fsurl%>search/cust_svc.html" METHOD="GET" STYLE="margin:0">
- <INPUT NAME="search_svc" TYPE="text" VALUE="(user, email, ip, mac, or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
- <A NOTYET="<%$fsurl%>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%">Advanced</A>
- <INPUT TYPE="submit" VALUE="Search services" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ <INPUT NAME="search_svc" TYPE="text" VALUE="(user, email, ip, mac, domain or service phone)" SIZE="41" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" CLASS="fstext"><BR>
+ <A NOTYET="<%$fsurl%>search/svc_Smarter.html" STYLE="color: #000000; font-size:11px">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search services" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px">
</FORM>
+% }
</TD>
- <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right" STYLE="padding-right:4px">
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right" STYLE="padding-left:4px;padding-right:4px">
% if ( $conf->config("ticket_system") ) {
<FORM ACTION="<% FS::TicketSystem->baseurl %>index.html" METHOD="GET" STYLE="margin:0">
- <INPUT NAME="q" TYPE="text" VALUE="(ticket #, subject, email or fulltext:text)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
- <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
- <INPUT TYPE="submit" VALUE="Search tickets" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
+ <INPUT NAME="q" TYPE="text" VALUE="(ticket #, subject, email or fulltext:text)" SIZE=33 onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" CLASS="fstext"><BR>
+ <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html" STYLE="color: #ffffff; font-size:11px">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search tickets" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px">
</FORM>
% }
</TD>
@@ -248,6 +277,15 @@ input.fsblackbuttonselected {
<BR>
<IMG SRC="<%$fsurl%>images/32clear.gif" HEIGHT="1" WIDTH="154">
+ <TABLE CELLSPACING=0 CELLPADDING=0 BGCOLOR="#000000" WIDTH="100%">
+ <TR>
+ <TD ALIGN="left" STYLE="padding-bottom:1px;border-bottom:1px solid #999999"><% include('/elements/about_freeside.html') |n %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right" STYLE="padding-bottom:1px"><% include('/elements/about_rt.html') |n %></TD>
+ </TR>
+ </TABLE>
+
</TD>
<TD STYLE="padding:0" HEIGHT="100%" WIDTH=13 VALIGN="top"><IMG WIDTH="13" HEIGHT="100%" BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gray-side.png"></TD>
@@ -267,7 +305,7 @@ input.fsblackbuttonselected {
<%init>
my( $title, $menubar, $etc, $head ) = ( '', '', '', '' );
-my( $nobr ) = ( 0 );
+my( $nobr, $nocss ) = ( 0, 0 );
if ( ref($_[0]) ) {
my $opt = shift;
$title = $opt->{title};
@@ -275,6 +313,7 @@ if ( ref($_[0]) ) {
$etc = $opt->{etc};
$head = $opt->{head};
$nobr = $opt->{nobr};
+ $nocss = $opt->{nocss};
} else {
($title, $menubar) = ( shift, shift );
$etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html
index d7b73a2..07aaa69 100644
--- a/httemplate/elements/location.html
+++ b/httemplate/elements/location.html
@@ -3,26 +3,28 @@
Example:
include( '/elements/location.html',
- 'object' => $cust_main, # or $cust_location
- 'prefix' => $pre, #only for cust_main objects
- 'onchange' => $javascript,
- 'disabled' => $disabled,
- 'same_checked' => $same_checked,
- 'geocode' => $geocode, #passed through
- 'no_asterisks' => 0, #set true to disable the red asterisks next
- #to required fields
+ 'object' => $cust_main, # or $cust_location
+ 'prefix' => $pre, #only for cust_main objects
+ 'onchange' => $javascript,
+ 'disabled' => $disabled,
+ 'same_checked' => $same_checked,
+ 'geocode' => $geocode, #passed through
+ 'censustract' => $censustract, #passed through
+ 'no_asterisks' => 0, #set true to disable the red asterisks next
+ #to required fields
+ 'address1_label' => 'Address', #label for address
)
</%doc>
<TR>
- <TH ALIGN="right"><%$r%>Address</TH>
+ <TH ALIGN="right"><%$r%><% $opt{'address1_label'} || 'Address' %></TH>
<TD COLSPAN=7>
<INPUT TYPE = "text"
NAME = "<%$pre%>address1"
ID = "<%$pre%>address1"
VALUE = "<% $object->get($pre.'address1') |h %>"
- SIZE = 58
+ SIZE = 54
onChange = "<% $onchange %>"
<% $disabled %>
<% $style %>
@@ -37,7 +39,7 @@ Example:
NAME = "<%$pre%>address2"
ID = "<%$pre%>address2"
VALUE = "<% $object->get($pre.'address2') |h %>"
- SIZE = 58
+ SIZE = 54
onChange = "<% $onchange %>"
<% $disabled %>
<% $style %>
@@ -47,7 +49,7 @@ Example:
<TR>
<TH ALIGN="right"><%$r%>City</TH>
- <TD>
+ <TD WIDTH="1">
<INPUT TYPE = "text"
NAME = "<%$pre%>city"
ID = "<%$pre%>city"
@@ -56,13 +58,11 @@ Example:
<% $disabled %>
<% $style %>
>
- </TD>
- <TH ALIGN="right" ID="<%$pre%>countylabel" <%$county_style%>><%$r%>County</TH>
- <TD>
- <% include('/elements/select-county.html', %select_hash ) %>
</TD>
- <TH ALIGN="right"><%$r%>State</TH>
- <TD>
+ <TH ALIGN="right" ID="<%$pre%>countylabel" <%$county_style%>><%$r%>County</TH>
+ <TD><% include('/elements/select-county.html', %select_hash ) %></TD>
+ <TH ALIGN="right" WIDTH="1"><%$r%>State</TH>
+ <TD WIDTH="1">
<% include('/elements/select-state.html', %select_hash ) %>
</TD>
<TH><%$r%>Zip</TH>
@@ -81,11 +81,21 @@ Example:
<TR>
<TH ALIGN="right"><%$r%>Country</TH>
- <TD COLSPAN=5><% include('/elements/select-country.html', %select_hash ) %></TD>
+ <TD COLSPAN=6><% include('/elements/select-country.html', %select_hash ) %></TD>
</TR>
% if ( !$pre ) {
<INPUT TYPE="hidden" NAME="geocode" VALUE="<% $opt{geocode} %>">
+% } else {
+% if ( $pre eq 'ship_' && $conf->exists('cust_main-require_censustract') ) {
+ <TR><TH ALIGN="right">Census tract<BR>(automatic)</TH>
+ <TD>
+ <INPUT TYPE="text" NAME="censustract" VALUE="<% $opt{censustract} %>">
+ </TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="censustract" VALUE="<% $opt{censustract} %>">
+% }
% }
<%init>
@@ -125,7 +135,7 @@ my @counties = counties( $object->get($pre.'state'),
$object->get($pre.'country'),
);
my @county_style = ();
-push @county_style, 'visibility:hidden'
+push @county_style, 'display:none' # 'visibility:hidden'
unless scalar(@counties) > 1;
my $style =
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index 627f9c8..c54ed07 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -12,7 +12,9 @@
% }
-<link href="<%$fsurl%>elements/freeside.css" type="text/css" rel="stylesheet">
+% unless ( $opt{'nocss'} ) {
+ <link href="<%$fsurl%>elements/freeside.css" type="text/css" rel="stylesheet">
+% }
<SCRIPT TYPE="text/javascript">
@@ -33,8 +35,8 @@
%
% my( $subhtml, $submenuname ) = submenu($url_or_submenu, $item);
- <% $subhtml %>
- myBar.add(new WebFXMenuButton("<% $item %>", null, "<% $tooltip %>", <% $submenuname %> ));
+ <% $subhtml |n %>
+ myBar.add(new WebFXMenuButton("<% $item %>", null, "<% $tooltip %>", <% $submenuname |n %> ));
% } else {
@@ -56,7 +58,7 @@ my $fsurl = $opt{'freeside_baseurl'};
my $curuser = $FS::CurrentUser::CurrentUser;
-#Active tickets not assigned to a customer
+#XXX Active tickets not assigned to a customer
tie my %report_customers_lists, 'Tie::IxHash',
'by customer number' => [ $fsurl. 'search/cust_main.cgi?browse=custnum', '' ],
@@ -133,10 +135,19 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
}
if ( $svcdb eq 'svc_acct' ) {
+
$report_svc{"All $lcname never logged in"} =
[ svc_url( %svc_url, 'query' => "magic=nologin;sortby=svcnum" ),
'',
];
+
+ } elsif ( $svcdb eq 'svc_phone' ) {
+
+ $report_svc{"${name}' total usage by time period"} =
+ [ $fsurl. 'search/report_svc_phone.html',
+ 'Total usage (minutes, and amount billed) for the specified time period, per phone number.',
+ ];
+
}
if ( $curuser->access_right('View/link unlinked services') ) {
@@ -170,6 +181,8 @@ if ( $curuser->access_right('Financial reports') ) {
$report_packages{'All customer packages'} = [ $fsurl.'search/cust_pkg.cgi?pkgnum', 'List all customer packages', ];
$report_packages{'Suspended customer packages'} = [ $fsurl.'search/cust_pkg.cgi?magic=suspended', 'List suspended packages' ];
$report_packages{'Customer packages with unconfigured services'} = [ $fsurl.'search/cust_pkg.cgi?APKG_pkgnum', 'List packages which have provisionable services' ];
+$report_packages{'FCC Form 477 packages'} = [ $fsurl.'search/report_477.html', 'Summarize packages by census tract for particular types' ]
+ if $conf->exists('cust_main-require_censustract');
$report_packages{'Advanced package reports'} = [ $fsurl.'search/report_cust_pkg.html', 'by agent, date range, status, package definition' ];
tie my %report_rating, 'Tie::IxHash',
@@ -178,57 +191,106 @@ tie my %report_rating, 'Tie::IxHash',
'Time worked' => [ $fsurl.'search/report_rt_transaction.html', '' ],
;
+tie my %report_ticketing_statistics, 'Tie::IxHash',
+ 'Tickets per day per Queue' => [ $fsurl.'rt/RTx/Statistics/CallsQueueDay', 'View the number of tickets created, resolved or deleted in a specific Queue, over the requested period of days' ],
+ 'Ticket status by Queue' => [ $fsurl.'rt/RTx/Statistics/OpenStalled', 'View numbers of new, open and stalled tickets in a selected Queue' ],
+ 'Tickets per day (multiple Queues)' => [ $fsurl.'rt/RTx/Statistics/CallsMultiQueue', 'View tickets created, resolved or deleted on in one or more Queues over a specified time period' ],
+ 'Tickets per Day of Week' => [ $fsurl.'rt/RTx/Statistics/DayOfWeek', 'View trends showing when tickets are created, resolved or deleted' ],
+ 'Time to resolve' => [ $fsurl.'rt/RTx/Statistics/Resolution', 'View how long tickets take to be resolved by Queue' ],
+ 'Time to resolve (scatter graph)' => [ $fsurl.'rt/RTx/Statistics/TimeToResolve', 'View a detailed scatter graph of time to resolve tickets by Queue' ],
+;
+
+tie my %report_ticketing, 'Tie::IxHash',
+ 'Resolved by owner' => [ $fsurl.'rt/Tools/Reports/ResolvedByOwner.html', '' ],
+ 'Resolved in date range' => [ $fsurl.'rt/Tools/Reports/ResolvedByDates.html', '' ],
+ 'Created in date range' => [ $fsurl.'rt/Tools/Reports/CreatedByDates.html', '' ],
+ 'separator' => '',
+ 'Statistics' => [ \%report_ticketing_statistics, '' ],
+ 'separator2' => '',
+ 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html', 'List tickets by any criteria' ],
+;
+
tie my %report_bill_event, 'Tie::IxHash',
'All billing events' => [ $fsurl.'search/report_cust_event.html', 'All billing events for a date range' ],
'Billing event errors' => [ $fsurl.'search/report_cust_event.html?failed=1', 'Failed credit cards, processor or printer problems, etc.' ],
- 'All invoice events' => [ $fsurl.'search/cust_bill_event.html', 'Reports on deprecated, old-style invoice events for a date range' ],
- 'Invoice event errors' => [ $fsurl.'search/cust_bill_event.html?failed=1', 'Reports on deprecated, old-style events for failed credit cards, processor or printer problems, etc.' ],
+# 'All invoice events' => [ $fsurl.'search/cust_bill_event.html', 'Reports on deprecated, old-style invoice events for a date range' ],
+# 'Invoice event errors' => [ $fsurl.'search/cust_bill_event.html?failed=1', 'Reports on deprecated, old-style events for failed credit cards, processor or printer problems, etc.' ],
;
-tie my %report_financial, 'Tie::IxHash',
- 'Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time.html', 'Sales, credits and receipts summary graph' ],
- 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ],
- 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ],
- 'Payment Report' => [ $fsurl.'search/report_cust_pay.html', 'Payment report (by type and/or date range)' ],
+tie my %report_payments, 'Tie::IxHash',
+ 'Payments' => [ $fsurl.'search/report_cust_pay.html', 'Payment report (by type and/or date range)' ],
;
-$report_financial{'Pending Payment Report'} = [ $fsurl.'search/cust_pay_pending.html?magic=_date;statusNOT=done', 'Pending real-time payments' ]
+$report_payments{'Pending Payments'} = [ $fsurl.'search/cust_pay_pending.html?magic=_date;statusNOT=done', 'Pending real-time payments' ]
if $curuser->access_right('View customer pending payments');
-$report_financial{'Payment Batch Report'} = [ $fsurl.'search/pay_batch.html', 'Payment batches (by status and/or date range)' ]
+$report_payments{'Voided Payments'} = [ $fsurl.'search/report_cust_pay.html?void=1', 'Voided payment report (by type and/or date range)' ]
+ if $curuser->access_right('View customer pending payments');
+$report_payments{'Payment Batches'} = [ $fsurl.'search/pay_batch.html', 'Payment batches (by status and/or date range)' ]
if $conf->exists('batch-enable') || $conf->config('batch-enable_payby');
-$report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ];
-$report_financial{'Prepaid Income'} = [ $fsurl.'search/report_prepaid_income.html', 'Prepaid income (unearned revenue) report' ];
-$report_financial{'Sales Tax Liability'} = [ $fsurl.'search/report_tax.html', 'Sales tax liability report (old taxclass system)' ];
-$report_financial{'Tax Liability'} = [ $fsurl.'search/report_newtax.html', 'Tax liability report (new tax products system)' ]
- if $conf->exists('enable_taxproducts');
-;
+$report_payments{'Unapplied Payment Aging'} = [ $fsurl.'search/report_unapplied_cust_pay.html', 'Unapplied payment aging report' ];
+
+tie my %report_financial, 'Tie::IxHash';
+if($curuser->access_right('Financial reports')) {
+
+ %report_financial = (
+ 'Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time.html', 'Sales, credits and receipts summary graph' ],
+ 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ],
+ 'Rated Call Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg_detail.html', 'Sales report and graph (by agent, package class, usage class and/or date range)' ],
+ 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ],
+ );
+ $report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ];
+ $report_financial{'Prepaid Income'} = [ $fsurl.'search/report_prepaid_income.html', 'Prepaid income (unearned revenue) report' ];
+ $report_financial{'Sales Tax Liability'} = [ $fsurl.'search/report_tax.html', 'Sales tax liability report (internal taxclass system)' ];
+ $report_financial{'Tax Liability'} = [ $fsurl.'search/report_newtax.html', 'Tax liability report (vendor data tax products system)' ]
+ if $conf->exists('enable_taxproducts');
+
+} elsif($curuser->access_right('Receivables report')) {
+
+ $report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ];
+
+} # else $report_financial contains nothing.
tie my %report_menu, 'Tie::IxHash';
$report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ]
if $curuser->access_right('List customers');
$report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ]
if $curuser->access_right('List invoices');
+$report_menu{'Payments'} = [ \%report_payments, 'Payment reports' ]
+ if $curuser->access_right('Financial reports');
$report_menu{'Packages'} = [ \%report_packages, 'Package reports' ]
if $curuser->access_right('List packages');
$report_menu{'Services'} = [ \%report_services, 'Services reports' ]
if $curuser->access_right('List services');
$report_menu{'Usage'} = [ \%report_rating, 'Usage reports' ]
if $curuser->access_right('List rating data');
+$report_menu{'Tickets'} = [ \%report_ticketing, 'Ticket reports' ]
+ if $conf->config('ticket_system')
+ ;#&& FS::TicketSystem->access_right(\%session, 'Something');
$report_menu{'Billing events'} = [ \%report_bill_event, 'Billing events' ]
if $curuser->access_right('Billing event reports');
$report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ]
- if $curuser->access_right('Financial reports');
+ if $curuser->access_right('Financial reports')
+ or $curuser->access_right('Receivables report');
$report_menu{'SQL Query'} = [ $fsurl.'search/report_sql.html', 'SQL Query' ]
if $curuser->access_right('Raw SQL');
tie my %tools_importing, 'Tie::IxHash',
- 'Import customers' => [ $fsurl.'misc/cust_main-import.cgi', '' ],
- 'Import customer comments from CSV file' => [ $fsurl.'misc/cust_main_note-import.html', '' ],
- 'Import one-time charges from CSV file' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
- 'Import payments from CSV file' => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
- 'Import phone numbers (DIDs)' => [ $fsurl.'misc/phone_avail-import.html', '' ],
- 'Import Call Detail Records (CDRs) from CSV file' => [ $fsurl.'misc/cdr-import.html', '' ],
- 'Import tax rates from CSV files' => [ $fsurl.'misc/tax-import.cgi', '' ],
+ 'Customers' => [ $fsurl.'misc/cust_main-import.cgi', '' ],
+ 'Customer comments from CSV file' => [ $fsurl.'misc/cust_main_note-import.html', '' ],
+ 'One-time charges from CSV file' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
+ 'Payments from CSV file' => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
+ 'Phone numbers (DIDs)' => [ $fsurl.'misc/phone_avail-import.html', '' ],
+ 'Call Detail Records (CDRs)' => [ $fsurl.'misc/cdr-import.html', '' ],
+# 'Import call rates and regions' => [ $fsurl.'misc/rate-import.html', '' ],
;
+if ( $conf->exists('enable_taxproducts') ) {
+ if ( $conf->exists('taxdatadirectdownload') ) {
+ $tools_importing{'Tax rates from vendor site'} =
+ [ $fsurl.'misc/tax-fetch_and_import.cgi', '' ];
+ } else {
+ $tools_importing{'Tax rates from CSV files'} =
+ [ $fsurl.'misc/tax-import.cgi', '' ];
+ }
+}
tie my %tools_exporting, 'Tie::IxHash',
'Download database dump' => [ $fsurl. 'misc/dump.cgi', '' ],
@@ -239,6 +301,14 @@ tie my %tools_exporting, 'Tie::IxHash',
# <!-- or <A HREF="browse/nas-sqlradius.cgi">RADIUS</A>
# <BR> -->
+tie my %tools_ticketing, 'Tie::IxHash',
+ 'Offline' => [ $fsurl.'rt/Tools/Offline.html', '' ],
+ 'My Day' => [ $fsurl.'rt/Tools/MyDay.html', '' ],
+ 'My Approvals' => [ $fsurl.'rt/Approvals/', '' ],
+;
+$tools_ticketing{'Cron Tool'} = [ $fsurl.'rt/Developer/CronTool/', '' ]
+ if $conf->exists('rt-crontool');
+
tie my %tools_menu, 'Tie::IxHash', ();
$tools_menu{'Quick payment entry'} = [ $fsurl.'misc/batch-cust_pay.html', 'Enter multiple payments in a batch' ]
if $curuser->access_right('Post payment batch');
@@ -247,6 +317,8 @@ $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_d
&& $curuser->access_right('Process batches');
$tools_menu{'Job Queue'} = [ $fsurl.'search/queue.html', 'View pending job queue' ]
if $curuser->access_right('Job queue');
+$tools_menu{'Ticketing'} = [ \%tools_ticketing, 'Ticketing tools' ]
+ if $conf->config('ticket_system');
$tools_menu{'Time Queue'} = [ $fsurl.'search/timeworked.html', 'View pending support time' ]
if $curuser->access_right('Time queue');
$tools_menu{'Importing'} = [ \%tools_importing, 'Import tools' ]
@@ -255,72 +327,98 @@ $tools_menu{'Exporting'} = [ \%tools_exporting, 'Export tools' ]
if $curuser->access_right('Export');
tie my %config_employees, 'Tie::IxHash',
- 'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ],
- 'View/Edit employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ],
+ 'Employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ],
+ 'Employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ],
;
-tie my %config_export_svc_pkg, 'Tie::IxHash', ();
+tie my %config_export_svc, 'Tie::IxHash', ();
if ( $curuser->access_right('Configuration') ) {
- $config_export_svc_pkg{'View/Edit exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ];
- $config_export_svc_pkg{'View/Edit service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ];
+ $config_export_svc{'Exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ];
+ $config_export_svc{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ];
}
-$config_export_svc_pkg{'View/Edit package definitions'} = [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ]
+
+tie my %config_pkg, 'Tie::IxHash', ();
+$config_pkg{'Package definitions'} = [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ]
if $curuser->access_right('Edit package definitions')
|| $curuser->access_right('Edit global package definitions');
if ( $curuser->access_right('Configuration') ) {
- $config_export_svc_pkg{'View/Edit package categories'} = [ $fsurl.'browse/pkg_category.html', 'Package categories define groups of package classes, for reporting and convenience purposes.' ];
- $config_export_svc_pkg{'View/Edit package classes'} = [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ];
- $config_export_svc_pkg{'View/Edit cancel reason types'} = [ $fsurl.'browse/reason_type.html?class=C', 'Cancel reason types define groups of reasons, for reporting and convenience purposes.' ];
- $config_export_svc_pkg{'View/Edit cancel reasons'} = [ $fsurl.'browse/reason.html?class=C', 'Cancel reasons explain why a service was cancelled.' ];
- $config_export_svc_pkg{'View/Edit suspend reason types'} = [ $fsurl.'browse/reason_type.html?class=S', 'Suspend reason types define groups of reasons, for reporting and convenience purposes.' ];
- $config_export_svc_pkg{'View/Edit suspend reasons'} = [ $fsurl.'browse/reason.html?class=S', 'Suspend reasons explain why a service was suspended.' ];
+ $config_pkg{'Package categories'} = [ $fsurl.'browse/pkg_category.html', 'Package categories define groups of package classes, for reporting and convenience purposes.' ];
+ $config_pkg{'Package tax classes'} = [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ];
+ $config_pkg{'Package report classes'} = [ $fsurl.'browse/part_pkg_report_option.html', 'Package classes define optional groups of packages for reporting purposes.' ];
+ $config_pkg{'Cancel reason types'} = [ $fsurl.'browse/reason_type.html?class=C', 'Cancel reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_pkg{'Cancel reasons'} = [ $fsurl.'browse/reason.html?class=C', 'Cancel reasons explain why a service was cancelled.' ];
+ $config_pkg{'Suspend reason types'} = [ $fsurl.'browse/reason_type.html?class=S', 'Suspend reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_pkg{'Suspend reasons'} = [ $fsurl.'browse/reason.html?class=S', 'Suspend reasons explain why a service was suspended.' ];
}
tie my %config_agent, 'Tie::IxHash',
- 'View/Edit agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ],
- 'View/Edit agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ],
- 'View/Edit agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ];
+ 'Agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ],
+ 'Agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ],
+ 'Agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ];
;
tie my %config_billing_rates, 'Tie::IxHash',
- 'View/Edit rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ],
- 'View/Edit regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ],
- 'View/Edit usage classes' => [ $fsurl.'browse/usage_class.html', 'Usage classes define groups of usage for taxation purposes.' ],
+ 'Rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ],
+ 'Regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ],
+ 'Usage classes' => [ $fsurl.'browse/usage_class.html', 'Usage classes define groups of usage for taxation purposes.' ],
+ 'Edit rates with Excel' => [ $fsurl.'misc/rate_edit_excel.html', 'Download and edit rates with Excel, then upload changes.' ], #"Edit with Excel" ?
;
tie my %config_billing, 'Tie::IxHash';
-# 'View/Edit payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ];
-$config_billing{'View/Edit billing events'} = [ $fsurl.'browse/part_event.html', 'Billing actions for customers, invoices and packages' ]
+# 'Payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ];
+$config_billing{'Billing events'} = [ $fsurl.'browse/part_event.html', 'Billing actions for customers, invoices and packages' ]
if $curuser->access_right('Edit billing events')
|| $curuser->access_right('Edit global billing events');
if ( $curuser->access_right('Configuration') ) {
- $config_billing{'View/Edit invoice events'} = [ $fsurl.'browse/part_bill_event.cgi', 'Deprecated, old-style actions for overdue invoices' ];
- $config_billing{'View/Edit invoice templates'} = [ $fsurl.'browse/invoice_template.html', 'Edit templates for HTML, plaintext and typeset invoices' ];
- $config_billing{'View/Edit prepaid cards'} = [ $fsurl.'search/prepay_credit.html', 'View outstanding cards, generate new cards' ];
- $config_billing{'View/Edit call rates and regions'} = [ \%config_billing_rates, 'Manage rate plans, regions and prefixes for VoIP and call billing' ];
- $config_billing{'View/Edit locales and tax rates (old tax class system)'} = [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ];
- $config_billing{'View/Edit tax rates (new tax products system)'} = [ $fsurl.'browse/tax_rate.cgi', 'Edit tax rates for the new tax products system' ];
- $config_billing{'View/Edit credit reason types'} = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons, for reporting and convenience purposes.' ];
- $config_billing{'View/Edit credit reasons'} = [ $fsurl.'browse/reason.html?class=R', 'Credit reasons explain why a credit was issued.' ];
+ #$config_billing{'Invoice events'} = [ $fsurl.'browse/part_bill_event.cgi', 'Deprecated, old-style actions for overdue invoices' ];
+ $config_billing{'Invoice templates'} = [ $fsurl.'browse/invoice_template.html', 'Edit templates for HTML, plaintext and typeset invoices' ];
+ $config_billing{'Prepaid cards'} = [ $fsurl.'search/prepay_credit.html', 'View outstanding cards, generate new cards' ];
+ $config_billing{'Call rates and regions'} = [ \%config_billing_rates, 'Manage rate plans, regions and prefixes for VoIP and call billing' ];
+
+ my $config_taxes_name = 'Locales and tax rates'.
+ ( $conf->exists('enable_taxproducts')
+ ? ' (internal tax class system)'
+ : ''
+ );
+ $config_billing{$config_taxes_name} = [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ];
+ $config_billing{'Tax rates (vendor data tax products system)'} = [ $fsurl.'browse/tax_rate.cgi', 'Edit tax rates for the vendor data tax products system' ]
+ if $conf->exists('enable_taxproducts');
+ $config_billing{'Tax classes'} = [ $fsurl. 'browse/part_pkg_taxclass.html', 'Tax classes' ];
+
+ $config_billing{'Credit reason types'} = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_billing{'Credit reasons'} = [ $fsurl.'browse/reason.html?class=R', 'Credit reasons explain why a credit was issued.' ];
}
+tie my %config_ticketing, 'Tie::IxHash',
+ 'Ticketing Users' => [ $fsurl.'rt/Admin/Users', 'View/Edit ticketing users' ], #XXX to be unified
+ 'Ticketing Groups' => [ $fsurl.'rt/Admin/Groups', 'View/Edit ticketing groups and group membership' ], #XXX to be unified
+ 'Ticketing Queues' => [ $fsurl.'rt/Admin/Queues', 'View/Edit ticketing queues and queue-specific properties' ],
+ 'Ticket Custom Fields' => [ $fsurl.'rt/Admin/CustomFields', 'View/Edit ticketing custom fields' ],
+ 'Ticketing Global' => [ $fsurl.'rt/Admin/Global', 'View/Edit ticketing configuration applicable to all queues' ],
+ #"System Configuraiton"? useless, just makes people report errors about missing Module::Versions::Report #'Ticketing Tools' => [ $fsurl.'rt/Admin/Tools', '' ],
+;
+
tie my %config_dialup, 'Tie::IxHash',
- 'View/Edit access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ],
+ 'Access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ],
;
tie my %config_broadband, 'Tie::IxHash',
- 'View/Edit routers' => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ],
- 'View/Edit address blocks' => [ $fsurl.'browse/addr_block.cgi', 'Manage address blocks and block assignments to broadband routers' ],
+ 'Routers' => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ],
+ 'Address blocks' => [ $fsurl.'browse/addr_block.cgi', 'Manage address blocks and block assignments to broadband routers' ],
+;
+
+tie my %config_phone, 'Tie::IxHash',
+ 'View/Edit phone device types' => [ $fsurl.'browse/part_device.html', 'Phone device types' ],
;
tie my %config_misc, 'Tie::IxHash';
-$config_misc{'View/Edit advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service. Tracked for informational purposes' ]
+$config_misc{'Advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service. Tracked for informational purposes' ]
if $curuser->access_right('Edit advertising sources')
|| $curuser->access_right('Edit global advertising sources');
if ( $curuser->access_right('Configuration') ) {
- $config_misc{'View/Edit virtual fields'} = [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ];
- $config_misc{'View/Edit message catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ];
- $config_misc{'View/Edit inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ];
+ $config_misc{'Virtual fields'} = [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ];
+ $config_misc{'Message catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ];
+ $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ];
}
tie my %config_menu, 'Tie::IxHash';
@@ -331,8 +429,9 @@ if ( $curuser->access_right('Configuration' ) ) {
'Employees' => [ \%config_employees, '' ],
);
}
-$config_menu{'Provisioning, services and packages'} =
- [ \%config_export_svc_pkg, '' ]
+$config_menu{'Provisioning and services'} = [ \%config_export_svc, '' ]
+ if $curuser->access_right('Configuration' );
+$config_menu{'Packages'} = [ \%config_pkg, '' ]
if $curuser->access_right('Configuration' )
|| $curuser->access_right('Edit package definitions')
|| $curuser->access_right('Edit global package definitions');
@@ -341,10 +440,15 @@ $config_menu{'Resellers'} = [ \%config_agent, '' ]
$config_menu{'Billing'} = [ \%config_billing, '' ]
if $curuser->access_right('Edit billing events')
|| $curuser->access_right('Edit global billing events');
+$config_menu{'Ticketing'} = [ \%config_ticketing, '' ]
+ if $conf->config('ticket_system')
+ && FS::TicketSystem->access_right(\%session, 'ShowConfigTab');
$config_menu{'Dialup'} = [ \%config_dialup, '' ]
if ( $curuser->access_right('Dialup configuration') );
$config_menu{'Fixed (username-less) broadband'} = [ \%config_broadband, '' ]
if ( $curuser->access_right('Broadband configuration') );
+$config_menu{'Phone'} = [ \%config_phone, '' ]
+ if ( $curuser->access_right('Configuration') );
$config_menu{'Miscellaneous'} = [ \%config_misc, '' ]
if $curuser->access_right('Edit advertising sources')
|| $curuser->access_right('Edit global advertising sources');
@@ -362,6 +466,8 @@ if ( $conf->config('ticket_system') ) {
'Ticketing start page',
],
}
+$menu{'New customer'} = [ $fsurl.'edit/cust_main.cgi', 'Add a new customer' ]
+ if $curuser->access_right('New customer');
$menu{'Reports'} = [ \%report_menu, 'Lists, reporting and graphing' ]
if keys %report_menu;
$menu{'Tools'} = [ \%tools_menu, 'Tools' ]
@@ -374,6 +480,7 @@ $menu{'Configuration'} = [ \%config_menu, 'Configuraiton and setup' ]
|| $curuser->access_right('Edit global billing events')
|| $curuser->access_right('Dialup configuration')
|| $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Phone configuration')
|| $curuser->access_right('Edit advertising sources')
|| $curuser->access_right('Edit global advertising sources');
@@ -417,7 +524,7 @@ sub submenu {
} keys %$submenu )
). "\n".
- "myMenu$menunum.width = 280;\n",
+ "myMenu$menunum.width = 256;\n",
"myMenu$menunum";
diff --git a/httemplate/elements/menuarrow.gif b/httemplate/elements/menuarrow.gif
new file mode 100644
index 0000000..ed2dee0
--- /dev/null
+++ b/httemplate/elements/menuarrow.gif
Binary files differ
diff --git a/httemplate/elements/menubar.html b/httemplate/elements/menubar.html
index ec6c13f..e6b7fb1 100644
--- a/httemplate/elements/menubar.html
+++ b/httemplate/elements/menubar.html
@@ -1,10 +1,108 @@
-%
-% my($item, $url, @html);
-% while (@_) {
-% ($item, $url) = splice(@_,0,2);
-% next if $item =~ /^\s*Main\s+Menu\s*$/i;
-% push @html, qq!<A HREF="$url">$item</A>!;
-% }
-%
-
-<% join(' | ', @html) %>
+<%doc>
+
+Example:
+
+ include( '/elements/menubar.html',
+
+ #options hashref (optional)
+ { 'newstyle' => 1, #may become the default at some point
+ 'url_base' => '', #prepended to menubar URLs, for convenience
+ 'selected' => '', #currently selected label
+ },
+
+ #menubar entries (required)
+ 'label' => $url,
+ 'label2' => $url2,
+ #etc.
+
+ );
+
+</%doc>
+%if ( $opt->{'newstyle'} ) {
+
+% #false laziness w/header.html... shouldn't these just go in freeside.css?
+
+ <style type="text/css">
+ a.fsblackbutton {
+ background-color:#333333;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
+ }
+
+ a.fsblackbuttonselected {
+ background-color:#7e0079;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
+ }
+ </style>
+
+ <TABLE BGCOLOR="#000000" BORDER=0 CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD><IMG SRC="<%$fsurl%>images/gray-black-side.png" WIDTH=13 HEIGHT=25></TD>
+ <TD>
+ <% join(' ', @html ) %>
+ </TD>
+ <TD><IMG SRC="<%$fsurl%>images/black-gray-side.png" WIDTH=13 HEIGHT=25></TD>
+ </TD>
+ </TR>
+ </TABLE>
+
+%} else {
+
+ <% join(' | ', @html) %>
+
+%}
+<%init>
+
+my $opt = ref($_[0]) ? shift : {};
+
+my $url_base = $opt->{'url_base'};
+
+my @html;
+while (@_) {
+
+ my ($item, $url) = splice(@_,0,2);
+ next if $item =~ /^\s*Main\s+Menu\s*$/i;
+
+ my $style = '';
+ if ( $opt->{'newstyle'} ) {
+
+ my $dclass = $item eq $opt->{'selected'}
+ ? 'fsblackbuttonselected'
+ : 'fsblackbutton';
+
+ $style =
+ qq( CLASS="$dclass" ).
+ qq( onMouseOver="this.className='fsblackbuttonselected'; return true;" ).
+ qq( onMouseOut="this.className='$dclass'; return true;" );
+ }
+
+ push @html, qq!<A HREF="$url_base$url" $style>$item</A>!;
+
+}
+
+</%init>
diff --git a/httemplate/elements/popup_link-cust_main.html b/httemplate/elements/popup_link-cust_main.html
index 6d92301..454fcc4 100644
--- a/httemplate/elements/popup_link-cust_main.html
+++ b/httemplate/elements/popup_link-cust_main.html
@@ -4,7 +4,7 @@ Example:
include('/elements/init_overlib.html')
- include( '/elements/cust_popup_link.html', { #hashref or a list, either way
+ include( '/elements/popup_link-cust_main.html', { #hashref or a list, either way
#required
'action' => 'content.html', # uri for content of popup which should
diff --git a/httemplate/elements/popup_link-ping.html b/httemplate/elements/popup_link-ping.html
new file mode 100644
index 0000000..9e5f143
--- /dev/null
+++ b/httemplate/elements/popup_link-ping.html
@@ -0,0 +1,30 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/popup_link-ping.html', { #hashref or a list, either way
+ 'ip' => '10.9.8.7',
+ })
+
+</%doc>
+<% include('/elements/popup_link.html', $params ) %>\
+<%init>
+
+my $params = { 'closetext' => 'Close' };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'label'} ||= 'ping';
+$params->{'actionlabel'} ||= 'Ping '. $params->{'ip'};
+$params->{'width'} ||= 350;
+$params->{'height'} ||= 220;
+
+$params->{'action'} = $p. 'misc/ping.html?'. $params->{'ip'};
+
+</%init>
diff --git a/httemplate/elements/popup_link.html b/httemplate/elements/popup_link.html
index 2019387..49b624c 100644
--- a/httemplate/elements/popup_link.html
+++ b/httemplate/elements/popup_link.html
@@ -22,14 +22,16 @@ Example:
#uncommon opt
'aname' => "target", # link NAME= value, useful for #targets
'target' => '_parent',
+ 'style' => 'css-attribute:value',
} )
</%doc>
% if ($params->{'action'} && $label) {
<A HREF="javascript:void(0);"
- onClick="<% $onclick %>"
- <% $params->{'aname'} ? 'NAME="'. $params->{'aname'}. '"' : '' %>
- <% $params->{'target'} ? 'TARGET="'. $params->{'target'}. '"' : '' %>
+ onClick="<% $onclick |n %>"
+ <% $params->{'aname'} ? 'NAME="'. $params->{'aname'}. '"' : '' |n %>
+ <% $params->{'target'} ? 'TARGET="'. $params->{'target'}. '"' : '' |n %>
+ <% $params->{'style'} ? 'STYLE="'. $params->{'style'}. '"' : '' |n %>
><% $label %></A>\
% }
<%init>
diff --git a/httemplate/elements/progress-popup.html b/httemplate/elements/progress-popup.html
index 0bd71ff..8a55efb 100644
--- a/httemplate/elements/progress-popup.html
+++ b/httemplate/elements/progress-popup.html
@@ -31,10 +31,12 @@ function updateStatus( status_statustext ) {
var statusArray = eval('(' + status_statustext + ')');
var status = statusArray[0];
var statustext = statusArray[1];
+ var actiontext = statusArray[2];
//if ( status == 'progress' ) {
//IE workaround, no i have no idea why
if ( status.indexOf('progress') > -1 ) {
+ document.getElementById("progress_message").innerHTML = actiontext + '...';
document.getElementById("progress_percent").innerHTML = statustext + '%';
bar1.set(statustext);
bar1.update;
diff --git a/httemplate/elements/select-county.html b/httemplate/elements/select-county.html
index 59f235a..aa88abe 100644
--- a/httemplate/elements/select-county.html
+++ b/httemplate/elements/select-county.html
@@ -58,10 +58,12 @@ Example:
if ( countiesArray.length > 1 ) {
what.form.<% $pre %>county.style.display = '';
- countyFormLabel.style.visibility = 'visible';
+ //countyFormLabel.style.visibility = 'visible';
+ countyFormLabel.style.display = '';
} else {
what.form.<% $pre %>county.style.display = 'none';
- countyFormLabel.style.visibility = 'hidden';
+ //countyFormLabel.style.visibility = 'hidden';
+ countyFormLabel.style.display = 'none';
}
//run the callback
diff --git a/httemplate/elements/select-cust-part_pkg.html b/httemplate/elements/select-cust-part_pkg.html
index 2926629..7f91e81 100644
--- a/httemplate/elements/select-cust-part_pkg.html
+++ b/httemplate/elements/select-cust-part_pkg.html
@@ -31,11 +31,11 @@ my( %opt ) = @_;
my $cust_main = $opt{'cust_main'}
or die "cust_main not specified";
-$opt{'extra_sql'} .=
- ' AND ( agentnum IS NOT NULL '.
- ' OR 0 < ( SELECT COUNT(*) FROM type_pkgs '.
- ' WHERE typenum = '. $cust_main->agent->typenum.
- ' AND type_pkgs.pkgpart = part_pkg.pkgpart )'.
- ' )';
+$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent );
+# ' AND ( agentnum IS NOT NULL '.
+# ' OR 0 < ( SELECT COUNT(*) FROM type_pkgs '.
+# ' WHERE typenum = '. $cust_main->agent->typenum.
+# ' AND type_pkgs.pkgpart = part_pkg.pkgpart )'.
+# ' )';
</%init>
diff --git a/httemplate/elements/select-cust-pkg_class.html b/httemplate/elements/select-cust-pkg_class.html
new file mode 100644
index 0000000..5c19efa
--- /dev/null
+++ b/httemplate/elements/select-cust-pkg_class.html
@@ -0,0 +1,12 @@
+<% include( '/elements/select-pkg_class.html',
+ 'pre_options' => [ '-1' => 'all' ], #XXX a config ?
+ #'pre_options' => [ '-2' => 'Select package class' ],
+ 'disable_empty' => 1,
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/select-cust_main-status.html b/httemplate/elements/select-cust_main-status.html
index 2e0b6cb..bdbaac7 100644
--- a/httemplate/elements/select-cust_main-status.html
+++ b/httemplate/elements/select-cust_main-status.html
@@ -8,7 +8,9 @@
% foreach my $option ( @{ $opt{'statuses'} } ) {
<OPTION VALUE="<% $option %>"
- <% $option eq $curr_value ? 'SELECTED' : '' %>
+ <% ref($value) && $value->{$option} || $option eq $value
+ ? 'SELECTED' : ''
+ %>
><% $option %>
% }
@@ -25,6 +27,7 @@ my $onchange = $opt{'onchange'}
? 'onChange="'. $opt{'onchange'}. '(this)"'
: '';
-my $curr_value = $opt{'curr_value'} || $opt{'value'};
+my $value = $opt{'curr_value'} || $opt{'value'};
+$value = [ split(/\s*,\s*/, $value) ] if $opt{'multiple'} && $value =~ /,/;
</%init>
diff --git a/httemplate/elements/select-cust_pkg-balances.html b/httemplate/elements/select-cust_pkg-balances.html
new file mode 100644
index 0000000..cd2e1a8
--- /dev/null
+++ b/httemplate/elements/select-cust_pkg-balances.html
@@ -0,0 +1,32 @@
+<SELECT NAME="pkgnum">
+ <OPTION VALUE="">(any)
+% foreach my $cust_pkg (@cust_pkg) {
+% my $sel = ( $cgi->param('pkgnum') == $cust_pkg->pkgnum ) ? 'SELECTED' : '';
+ <OPTION <% $sel %> VALUE="<% $cust_pkg->pkgnum %>"><% $cust_pkg->pkg_label_long |h %>
+% }
+</SELECT>
+<%init>
+
+my %opt = @_;
+
+my $cgi = $opt{'cgi'};
+
+my @cust_pkg;
+if ( $opt{'cust_pkg'} ) {
+
+ @cust_pkg = @{ $opt{'cust_pkg'} };
+
+} else {
+
+ my $custnum = $opt{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or die "unknown custnum $custnum\n";
+
+ @cust_pkg =
+ grep { ! $_->get('cancel') || $cust_main->balance_pkgnum($_->pkgnum) }
+ $cust_main->all_pkgs;
+
+}
+
+</%init>
diff --git a/httemplate/elements/select-cust_pkg-status.html b/httemplate/elements/select-cust_pkg-status.html
index 2d545c0..ec37eaf 100644
--- a/httemplate/elements/select-cust_pkg-status.html
+++ b/httemplate/elements/select-cust_pkg-status.html
@@ -8,7 +8,9 @@
% foreach my $option ( @{ $opt{'statuses'} } ) {
<OPTION VALUE="<% $option %>"
- <% $option eq $curr_value ? 'SELECTED' : '' %>
+ <% ref($value) && $value->{$option} || $option eq $value
+ ? 'SELECTED' : ''
+ %>
><% $option %>
% }
@@ -25,6 +27,7 @@ my $onchange = $opt{'onchange'}
? 'onChange="'. $opt{'onchange'}. '(this)"'
: '';
-my $curr_value = $opt{'curr_value'} || $opt{'value'};
+my $value = $opt{'curr_value'} || $opt{'value'};
+$value = [ split(/\s*,\s*/, $value) ] if $opt{'multiple'} && $value =~ /,/;
</%init>
diff --git a/httemplate/elements/select-did.html b/httemplate/elements/select-did.html
index 0695164..af8d595 100644
--- a/httemplate/elements/select-did.html
+++ b/httemplate/elements/select-did.html
@@ -68,8 +68,11 @@ my %opt = @_;
my $conf = new FS::Conf;
my $country = $conf->config('countrydefault') || 'US';
+#false laziness w/tr-select-did.html
#XXX make sure this comes through on errors too
-my $svcpart = $opt{'svcpart'} || $opt{'object'}->svcpart;
+my $svcpart = $opt{'svcpart'}
+ || $opt{'object'}->svcpart
+ || $opt{'object'}->cust_svc->svcpart;
my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
die "unknown svcpart $svcpart" unless $part_svc;
diff --git a/httemplate/elements/select-domain.html b/httemplate/elements/select-domain.html
index a9998da..3372e06 100644
--- a/httemplate/elements/select-domain.html
+++ b/httemplate/elements/select-domain.html
@@ -7,7 +7,7 @@
' LEFT JOIN cust_pkg USING ( pkgnum ) '.
' LEFT JOIN cust_main USING ( custnum ) ',
'agent_virt' => 1,
- 'agent_null-right' => 'View/link unlinked services',
+ 'agent_null_right' => 'View/link unlinked services',
@_,
)
%>
diff --git a/httemplate/elements/select-part_pkg.html b/httemplate/elements/select-part_pkg.html
index 52b1cca..6b697ab 100644
--- a/httemplate/elements/select-part_pkg.html
+++ b/httemplate/elements/select-part_pkg.html
@@ -22,17 +22,27 @@ Example:
'name_col' => 'pkg',
'empty_label' => 'Select package', #should this be the default?
'label_callback' => sub { shift->pkg_comment },
- 'hashref' => { 'disabled' => '' },
+ 'hashref' => \%hash,
%opt,
)
%>
<%init>
-
+
my( %opt ) = @_;
$opt{'records'} = delete $opt{'part_pkg'}
if $opt{'part_pkg'};
+my %hash = ( 'disabled' => '' );
+
+if ( exists($opt{'classnum'}) && defined($opt{'classnum'}) ) {
+ if ( $opt{'classnum'} > 0 ) {
+ $hash{'classnum'} = $opt{'classnum'};
+ } elsif ( $opt{'classnum'} eq '' || $opt{'classnum'} == 0 ) {
+ $hash{'classnum'} = '';
+ } #else -1 or not specified, all classes, so don't set classnum
+}
+
$opt{'extra_sql'} .= ' AND '. FS::part_pkg->curuser_pkgs_sql;
</%init>
diff --git a/httemplate/elements/select-part_svc.html b/httemplate/elements/select-part_svc.html
new file mode 100644
index 0000000..72ab7f6
--- /dev/null
+++ b/httemplate/elements/select-part_svc.html
@@ -0,0 +1,18 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'part_svc',
+ 'name_col' => 'svc',
+ 'label_showkey' => 1,
+ #N/A 'empty_label' => '(none)',
+ %opt,
+ )
+%>
+<%init>
+
+my( %opt ) = @_;
+
+$opt{'records'} = delete $opt{'part_svc'}
+ if $opt{'part_svc'};
+
+$opt{'records'} ||= [ qsearch( 'part_svc', {} ) ]; # { disabled=>'' } )
+
+</%init>
diff --git a/httemplate/elements/select-svc_acct-domain.html b/httemplate/elements/select-svc_acct-domain.html
new file mode 100644
index 0000000..c9a9206
--- /dev/null
+++ b/httemplate/elements/select-svc_acct-domain.html
@@ -0,0 +1,46 @@
+<SELECT NAME="domsvc" SIZE=1>
+% foreach my $svcnum (
+% sort { $svc_domain{$a} cmp $svc_domain{$b} }
+% keys %svc_domain
+% ) {
+% my $svc_domain = $svc_domain{$svcnum};
+% my $selected = ($svcnum == $domsvc) ? ' SELECTED' : ''
+
+ <OPTION VALUE="<% $svcnum %>" <% $selected %>><% $svc_domain{$svcnum} %>
+
+% }
+
+</SELECT>
+<%init>
+
+my %opt = @_;
+
+my $domsvc = $opt{'curr_value'};
+my $part_svc = $opt{'part_svc'}
+ || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} });
+
+#optional
+my $cust_pkg = $opt{'cust_pkg'};
+$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} })
+ if $opt{'pkgnum'};
+
+my $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : '';
+
+my %svc_domain = ();
+
+if ( $domsvc ) {
+ my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $domsvc } );
+ if ( $svc_domain ) {
+ $svc_domain{$svc_domain->svcnum} = $svc_domain;
+ } else {
+ warn "unknown svc_domain.svcnum for svc_acct.domsvc: $domsvc";
+ }
+}
+
+%svc_domain = (
+ %svc_domain,
+ FS::svc_acct->domain_select_hash( 'svcpart' => $part_svc->svcpart,
+ 'pkgnum' => $pkgnum,
+ )
+);
+</%init>
diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html
index 4efbcba..10a8b27 100644
--- a/httemplate/elements/select-table.html
+++ b/httemplate/elements/select-table.html
@@ -34,6 +34,7 @@ Example:
'empty_label' => '', #better specify it though, the default might change
'multiple' => 0, # bool
'disable_empty' => 0, # bool (implied by multiple)
+ 'label_showkey' => 0, # bool
'label_callback' => sub { my $record = shift; return "label"; },
#more params controlling HTML stuff about the <SELECT>
@@ -64,21 +65,32 @@ Example:
>
% while ( @pre_options ) {
- <OPTION VALUE="<% shift(@pre_options) %>"><% shift(@pre_options) %>
-
+% my $pre_opt = shift(@pre_options);
+% my $pre_label = shift(@pre_options);
+% my $selected = ( ref($value) && $value->{$pre_opt} )
+% || ( $value eq $pre_opt );
+ <OPTION VALUE="<% $pre_opt %>"
+ <% $selected ? 'SELECTED' : '' %>
+ ><% $pre_label %>
% }
% unless ( $opt{'multiple'} || $opt{'disable_empty'} ) {
<OPTION VALUE=""><% $opt{'empty_label'} || 'all' %>
% }
-% foreach my $record ( sort { $a->$name_col() cmp $b->$name_col() } @records ) {
+% foreach my $record ( sort { $a->$name_col() cmp $b->$name_col()
+% || $a->$key() <=> $b->$key()
+% }
+% @records
+% )
+% {
% my $recvalue = $record->$key();
<OPTION VALUE="<% $recvalue %>"
<% ref($value) && $value->{$recvalue} || $value == $recvalue
? ' SELECTED' : ''
%>
- ><% $opt{'label_callback'}
+ ><% $opt{'label_showkey'} ? "$recvalue: " : '' %>
+ <% $opt{'label_callback'}
? &{ $opt{'label_callback'} }( $record )
: $record->$name_col()
%>
@@ -139,7 +151,7 @@ if ( $opt{'records'} ) {
});
}
-unless ( ! $value
+unless ( $value < 1 # !$value #ignore negatives too
or ref($value)
or ! exists( $opt{hashref}->{disabled} ) #??
or grep { $value == $_->$key() } @records
diff --git a/httemplate/elements/select-taxclass.html b/httemplate/elements/select-taxclass.html
index 2504a5b..6845d23 100644
--- a/httemplate/elements/select-taxclass.html
+++ b/httemplate/elements/select-taxclass.html
@@ -1,6 +1,6 @@
% if ( $conf->exists('enable_taxclasses') ) {
- <SELECT NAME="<% $opt{'name'} || 'taxclass' %>">
+ <SELECT NAME="<% $opt{'element_name'} || $opt{'field'} || 'taxclass' %>">
% if ( $conf->exists('require_taxclasses') ) {
<OPTION VALUE="(select)">Select tax class
@@ -16,7 +16,7 @@
% } else {
- <INPUT TYPE="hidden" NAME="taxclass" VALUE="<% $selected_taxclass %>">
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'taxclass' %>" VALUE="<% $selected_taxclass %>">
% }
@@ -30,9 +30,9 @@ my $conf = new FS::Conf;
unless ( $opt{'taxclasses'} ) {
#my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
- my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+ my $sth = dbh->prepare("SELECT taxclass FROM part_pkg_taxclass WHERE disabled IS NULL OR disabled = '' OR taxclass = ?")
or die dbh->errstr;
- $sth->execute or die $sth->errstr;
+ $sth->execute($selected_taxclass) or die $sth->errstr;
my %taxclasses = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
@{ $opt{'taxclasses'} } = grep $_, keys %taxclasses;
diff --git a/httemplate/elements/select-terms.html b/httemplate/elements/select-terms.html
new file mode 100644
index 0000000..629d1e4
--- /dev/null
+++ b/httemplate/elements/select-terms.html
@@ -0,0 +1,26 @@
+<SELECT NAME = "invoice_terms"
+ ID = "invoice_terms"
+ <% $opt{'disabled'} ? 'DISABLED' : ''%>
+>
+ <OPTION VALUE=""><% $empty_label %>
+% foreach my $term ( @terms ) {
+ <OPTION VALUE="<% $term %>" <% $curr_value eq $term ? ' SELECTED' : '' %>><% $term %>
+% }
+</SELECT>
+<%init>
+
+my %opt = @_;
+my $curr_value = $opt{'curr_value'};
+my $conf = new FS::Conf;
+
+my $empty_label =
+ $opt{'empty_label'}
+ || 'Default ('.
+ ($conf->config('invoice_default_terms') || 'Payable upon receipt').
+ ')';
+
+my @terms = ( 'Payable upon receipt',
+ ( map "Net $_", 0, 10, 15, 20, 30, 45, 60 ),
+ );
+
+</%init>
diff --git a/httemplate/elements/selectlayers.html b/httemplate/elements/selectlayers.html
index 82f5dd1..89fe41b 100644
--- a/httemplate/elements/selectlayers.html
+++ b/httemplate/elements/selectlayers.html
@@ -14,7 +14,7 @@ Example:
#XXX put this handling it its own selectlayers-fields.html element?
'layer_prefix' => 'prefix_', #optional prefix for fieldnames
- 'layer_fields' => [ 'layer' => [ 'fieldname',
+ 'layer_fields' => { 'layer' => [ 'fieldname',
{ label => 'fieldname2',
type => 'text', #implemented:
# text, money, fixed,
@@ -23,6 +23,7 @@ Example:
# select, select-agent,
# select-pkg_class,
# select-part_referral,
+ # select-taxclass,
# select-table,
#XXX tbd:
# more?
@@ -32,6 +33,7 @@ Example:
'layer2' => [ 'l2fieldname',
...
],
+ },
#current values for layer fields above
'layer_values' => { 'layer' => { 'fieldname' => 'current_value',
@@ -63,18 +65,29 @@ Example:
<SCRIPT TYPE="text/javascript">
% }
% unless ( grep $opt{$_}, qw(html_only select_only layers_only) ) {
- //alert('start function define');
+
+% if ( $opt{layermap} ) {
+% my %map = %{ $opt{layermap} };
+ var layermap = { "":"",
+ <% join(',', map { qq("$_":"$map{$_}") } keys %map ) %>
+ };
+% }
+
function <% $key %>changed(what) {
<% $opt{'onchange'} %>
var <% $key %>layer = what.options[what.selectedIndex].value;
-% foreach my $layer ( keys %$options ) {
-
+% foreach my $layer ( @layers ) {
+%
+% if ( $opt{layermap} ) {
+ if ( layermap[ <% $key %>layer ] == "<% $layer %>" ) {
+% } else {
if (<% $key %>layer == "<% $layer %>" ) {
+% }
-% foreach my $not ( grep { $_ ne $layer } keys %$options ) {
+% foreach my $not ( grep { $_ ne $layer } @layers ) {
% my $element = "document.getElementById('${key}d$not').style";
<% $element %>.display = "none";
<% $element %>.zIndex = 0;
@@ -90,7 +103,6 @@ Example:
//<% $opt{'onchange'} %>
}
- //alert('end function define');
% }
% unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
</SCRIPT>
@@ -124,10 +136,16 @@ Example:
%
% unless ( grep $opt{$_}, qw(js_only select_only) ) {
-% foreach my $layer ( keys %$options ) {
+% foreach my $layer ( @layers ) {
+% my $selected_layer;
+% if ( $opt{layermap} ) {
+% $selected_layer = $opt{layermap}->{$selected};
+% } else {
+% $selected_layer = $selected;
+% }
<DIV ID="<% $key %>d<% $layer %>"
- STYLE="<% $layer eq $selected
+ STYLE="<% $selected_layer eq $layer
? 'display: "" ; z-index: 1'
: 'display: none; z-index: 0'
%>"
@@ -162,6 +180,14 @@ tie my %options, 'Tie::IxHash',
my $between = exists($opt{html_between}) ? $opt{html_between} : '';
my $options = \%options;
+my @layers = ();
+if ( $opt{layermap} ) {
+ my %layers = map { $opt{layermap}->{$_} => 1 } keys %options;
+ @layers = keys %layers;
+} else {
+ @layers = keys %options;
+}
+
my $selected = exists($opt{curr_value}) ? $opt{curr_value} : '';
#XXX eek. also eek $layer_fields in the layer_callback() call...
diff --git a/httemplate/elements/tr-checkbox.html b/httemplate/elements/tr-checkbox.html
index 2e6d1f1..c3cf92d 100644
--- a/httemplate/elements/tr-checkbox.html
+++ b/httemplate/elements/tr-checkbox.html
@@ -1,13 +1,7 @@
<% include('tr-td-label.html', @_ ) %>
<TD <% $style %>>
- <INPUT TYPE = "checkbox"
- NAME = "<% $opt{field} %>"
- ID = "<% $opt{id} %>"
- VALUE = "<% $opt{value} %>"
- <% $opt{curr_value} eq $opt{value} ? ' CHECKED' : '' %>
- <% $onchange %>
- >
+ <% include('checkbox.html', @_) %>
</TD>
</TR>
diff --git a/httemplate/elements/tr-input-date-field.html b/httemplate/elements/tr-input-date-field.html
index 11581d5..2a731e1 100644
--- a/httemplate/elements/tr-input-date-field.html
+++ b/httemplate/elements/tr-input-date-field.html
@@ -23,17 +23,30 @@
<%init>
-my($name, $value, $label, $format, $usedatetime) = @_;
+my($name, $value, $label, $format, $usedatetime);
+if ( ref($_[0]) ) {
+ my $opt = shift;
+ $name = $opt->{'name'};
+ $value = $opt->{'value'};
+ $label = $opt->{'label'};
+ $format = $opt->{'format'};
+ $usedatetime = $opt->{'usedatetime'};
+} else {
+ ($name, $value, $label, $format, $usedatetime) = @_;
+}
$format = "%m/%d/%Y" unless $format;
$label = $name unless $label;
-if ($usedatetime) {
- my $dt = DateTime->from_epoch(epoch => $value, time_zone => 'floating');
- $value = $dt->strftime($format)
- unless $value eq '';
-}else{
- $value = time2str($format, $value);
+if ( $value =~ /\S/ ) {
+ if ( $usedatetime ) {
+ my $dt = DateTime->from_epoch(epoch => $value, time_zone => 'floating');
+ $value = $dt->strftime($format);
+ } elsif ( $value =~ /^\d+$/ ) {
+ $value = time2str($format, $value);
+ }
+} else {
+ $value = '';
}
</%init>
diff --git a/httemplate/elements/tr-justtitle.html b/httemplate/elements/tr-justtitle.html
index 7839a8c..8c14d34 100644
--- a/httemplate/elements/tr-justtitle.html
+++ b/httemplate/elements/tr-justtitle.html
@@ -1,5 +1,5 @@
<TR>
- <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <TH BGCOLOR="#e8e8e8" COLSPAN=<% $opt{colspan} || 2 %> ALIGN="left">
<FONT SIZE="+1"><% $opt{value} %></FONT>
</TH>
</TR>
diff --git a/httemplate/elements/tr-select-cust-part_pkg.html b/httemplate/elements/tr-select-cust-part_pkg.html
new file mode 100644
index 0000000..75f1f6f
--- /dev/null
+++ b/httemplate/elements/tr-select-cust-part_pkg.html
@@ -0,0 +1,107 @@
+%if ( scalar(@pkg_class) > 1 && ! $conf->exists('disable-cust-pkg_class') ) {
+
+ <% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/cust-part_pkg.cgi',
+ 'subs' => [ 'get_part_pkg' ],
+ )
+ %>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function classnum_changed(what) {
+
+ what.form.pkgpart.disabled = 'disabled'; //disable part_pkg dropdown
+ what.form.submit.disabled = true; //disable the submit button
+
+ classnum = what.options[what.selectedIndex].value;
+
+ function update_part_pkg(part_pkg) {
+
+ // blank the current packages
+ for ( var i = what.form.pkgpart.length; i>= 0; i-- )
+ what.form.pkgpart.options[i] = null;
+
+ // add the new packages
+ opt(what.form.pkgpart, '', 'Select package');
+ var packagesArray = eval('(' + part_pkg + ')' );
+ for ( var s = 0; s < packagesArray.length; s=s+2 ) {
+ var packagesLabel = packagesArray[s+1];
+ opt(what.form.pkgpart, packagesArray[s], packagesLabel);
+ }
+
+ what.form.pkgpart.disabled = ''; //re-enable part_pkg dropdown
+
+ }
+
+ get_part_pkg( <% $cust_main->custnum %>, classnum, update_part_pkg );
+
+ }
+
+ </SCRIPT>
+
+ <TR>
+ <TH ALIGN="right">Package Class</TH>
+ <TD COLSPAN=7>
+ <% include('/elements/select-cust-pkg_class.html',
+ 'curr_value' => $opt{'classnum'},
+ 'pkg_class' => \@pkg_class,
+ 'onchange' => 'classnum_changed',
+ )
+ %>
+ </TD>
+ </TR>
+
+%}
+
+<TR>
+ <TH ALIGN="right">Package</TH>
+ <TD COLSPAN=7>
+ <% include('/elements/select-cust-part_pkg.html',
+ 'curr_value' => $opt{'curr_value'}, #$pkgpart
+ 'classnum' => $opt{'classnum'},
+ 'cust_main' => $opt{'cust_main'}, #$cust_main
+ 'onchange' => 'enable_order_pkg',
+ )
+ %>
+ </TD>
+</TR>
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my %opt = @_;
+
+my $pre_label = $opt{'pre_label'} || '';
+$pre_label .= ' ' if length($pre_label) && $pre_label =~ /\S$/;
+
+my $cust_main = $opt{'cust_main'}
+ or die "cust_main not specified";
+
+#my @pkg_class = sort { $a->classname cmp $b->classname }
+# qsearch( 'pkg_class', { 'disabled' => '' } );
+
+#"normal" part_pkg agent virtualization (agentnum or type)
+my @part_pkg = qsearch({
+ 'select' => 'DISTINCT classnum',
+ 'table' => 'part_pkg',
+ 'hashref' => { 'disabled' => '' },
+ 'extra_sql' =>
+ ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ).
+ ' AND '. FS::part_pkg->agent_pkgs_sql( $opt{'cust_main'}->agent ),
+});
+
+my @pkg_class =
+ sort { $a->classname cmp $b->classname } #should get a sort order in config
+ map { $_->pkg_class || new FS::pkg_class { 'classnum' => '',
+ 'classname' => '(none)' }
+ }
+ @part_pkg;
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_pkg-balances.html b/httemplate/elements/tr-select-cust_pkg-balances.html
new file mode 100644
index 0000000..89dc5d4
--- /dev/null
+++ b/httemplate/elements/tr-select-cust_pkg-balances.html
@@ -0,0 +1,31 @@
+% if ( scalar(@cust_pkg) == 0 ) {
+ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="">
+% } elsif ( scalar(@cust_pkg) == 1 ) {
+ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $cust_pkg[0]->pkgnum %>">
+% } else {
+ <TR>
+ <TD ALIGN="right">For package</TD>
+ <TD COLSPAN=2>
+ <% include('select-cust_pkg-balances.html',
+ 'cust_pkg' => \@cust_pkg,
+ 'cgi' => $opt{'cgi'},
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+my %opt = @_;
+
+my $custnum = $opt{'custnum'};
+
+my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or die "unknown custnum $custnum\n";
+
+my @cust_pkg =
+ grep { ! $_->get('cancel') || $cust_main->balance_pkgnum($_->pkgnum) }
+ $cust_main->all_pkgs;
+
+</%init>
diff --git a/httemplate/elements/tr-select-did.html b/httemplate/elements/tr-select-did.html
index c784033..987ade6 100644
--- a/httemplate/elements/tr-select-did.html
+++ b/httemplate/elements/tr-select-did.html
@@ -1,6 +1,6 @@
<% include('tr-td-label.html', @_ ) %>
-% if ( $opt{'curr_value'} ne '' ) {
+% if ( $opt{'curr_value'} ne '' && $use_selector ) {
<TD BGCOLOR="#dddddd" <% $cell_style %>><% $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'} |h %></TD>
@@ -19,7 +19,23 @@
<%init>
my %opt = @_;
-
+#warn Dumper(\%opt); if $DEBUG;
my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+#false laziness w/select-did.html
+#XXX make sure this comes through on errors too
+my $svcpart = $opt{'svcpart'}
+ || $opt{'object'}->svcpart
+ || $opt{'object'}->cust_svc->svcpart;
+
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @exports = $part_svc->part_export_did;
+if ( scalar(@exports) > 1 ) {
+ die "more than one DID-providing export attached to svcpart $svcpart";
+}
+
+my $use_selector = scalar(@exports) ? 1 : 0;
+
</%init>
diff --git a/httemplate/elements/tr-select-part_svc.html b/httemplate/elements/tr-select-part_svc.html
index 0274ef1..af51487 100644
--- a/httemplate/elements/tr-select-part_svc.html
+++ b/httemplate/elements/tr-select-part_svc.html
@@ -7,11 +7,8 @@
<TR>
<TD ALIGN="right"><% $opt{'label'} || 'Package definition' %></TD>
<TD>
- <% include( '/elements/select-table.html',
- 'table' => 'part_svc',
- 'name_col' => 'svc',
- 'multiple' => 1,
- #N/A 'empty_label' => '(none)',
+ <% include( '/elements/select-part_svc.html',
+ 'multiple' => 1,
%opt,
)
%>
diff --git a/httemplate/elements/tr-select-pkg_class.html b/httemplate/elements/tr-select-pkg_class.html
index aa27609..ece4b58 100644
--- a/httemplate/elements/tr-select-pkg_class.html
+++ b/httemplate/elements/tr-select-pkg_class.html
@@ -1,6 +1,6 @@
-% if ( scalar(@{ $opt{'pkg_class'} }) == 0 ) {
+% if ( $count == 0 ) {
- <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'classnum' %>" VALUE="">
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'classnum' %>" VALUE="">
% } else {
@@ -22,6 +22,6 @@
my %opt = @_;
my $classnum = $opt{'curr_value'} || $opt{'value'};
-$opt{'pkg_class'} ||= [ qsearch( 'pkg_class', {} ) ]; # { disabled=>'' } )
+my $count = scalar( qsearch( 'pkg_class', {} ) );
</%init>
diff --git a/httemplate/elements/tr-select-svc_acct-domain.html b/httemplate/elements/tr-select-svc_acct-domain.html
new file mode 100644
index 0000000..9d1a4b6
--- /dev/null
+++ b/httemplate/elements/tr-select-svc_acct-domain.html
@@ -0,0 +1,34 @@
+%if ( $columnflag eq 'F' ) {
+ <INPUT TYPE="hidden" NAME="domsvc" VALUE="<% $domsvc %>">
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Domain' %></TD>
+ <TD>
+ <% include('/elements/select-svc_acct-domain.html',
+ 'curr_value' => $domsvc,
+ 'part_svc' => $part_svc,
+ 'cust_pkg' => $cust_pkg,
+ )
+ %>
+ </TD>
+ </TR>
+% }
+<%init>
+
+my %opt = @_;
+
+my $domsvc = $opt{'curr_value'};
+
+#required
+my $part_svc = $opt{'part_svc'}
+ || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} });
+
+my $columnflag = $part_svc->part_svc_column('domsvc')->columnflag;
+
+#optional
+my $cust_pkg = $opt{'cust_pkg'};
+$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} })
+ if $opt{'pkgnum'};
+
+</%init>
diff --git a/httemplate/elements/tr-select-taxclass.html b/httemplate/elements/tr-select-taxclass.html
index 981c1a5..97f3cad 100644
--- a/httemplate/elements/tr-select-taxclass.html
+++ b/httemplate/elements/tr-select-taxclass.html
@@ -9,7 +9,11 @@
<TR>
<TD ALIGN="right"><% $opt{'label'} || 'Tax class: ' %></TD>
<TD>
- <% include( '/elements/select-taxclass.html', 'curr_value' => $selected_taxclass, %opt ) %>
+ <% include( '/elements/select-taxclass.html',
+ 'curr_value' => $selected_taxclass,
+ %opt
+ )
+ %>
</TD>
</TR>
@@ -23,9 +27,9 @@ my $selected_taxclass = $opt{'curr_value'}; # || $opt{'value'} necessary?
unless ( $opt{'taxclasses'} ) {
#my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
- my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+ my $sth = dbh->prepare("SELECT taxclass FROM part_pkg_taxclass WHERE disabled IS NULL OR disabled = '' OR taxclass = ?")
or die dbh->errstr;
- $sth->execute or die $sth->errstr;
+ $sth->execute($selected_taxclass) or die $sth->errstr;
my %taxclasses = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
@{ $opt{'taxclasses'} } = grep $_, keys %taxclasses;
diff --git a/httemplate/elements/tr-selectmultiple-part_pkg.html b/httemplate/elements/tr-selectmultiple-part_pkg.html
index 455038d..d959a5b 100644
--- a/httemplate/elements/tr-selectmultiple-part_pkg.html
+++ b/httemplate/elements/tr-selectmultiple-part_pkg.html
@@ -2,11 +2,10 @@
<TD ALIGN="right"><% $opt{'label'} || 'Packages' %></TD>
<TD>
<% include( '/elements/select-table.html',
- 'table' => 'part_pkg',
- 'name_col' => 'pkg',
- 'value' => '',
- 'empty_label' => '(none)',
- 'element_etc' => 'multiple',
+ 'table' => 'part_pkg',
+ 'name_col' => 'pkg',
+ 'disable_empty' => 1,
+ 'element_etc' => 'multiple',
%opt,
)
%>
diff --git a/httemplate/elements/tr-textarea.html b/httemplate/elements/tr-textarea.html
new file mode 100644
index 0000000..ae2ef81
--- /dev/null
+++ b/httemplate/elements/tr-textarea.html
@@ -0,0 +1,30 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $cell_style %>>
+
+ <TEXTAREA NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id} %>"
+ <% $rows %>
+ <% $cols %>
+ <% $onchange %>
+ ><% $curr_value |h %></TEXTAREA>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $rows = $opt{'rows'} ? 'ROWS="'.$opt{'rows'}.'"' : '';
+my $cols = $opt{'cols'} ? 'COLS="'.$opt{'cols'}.'"' : '';
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+my $curr_value = $opt{'curr_value'};
+
+</%init>
diff --git a/httemplate/elements/tr-title.html b/httemplate/elements/tr-title.html
index 8517737..f2d269e 100644
--- a/httemplate/elements/tr-title.html
+++ b/httemplate/elements/tr-title.html
@@ -1,5 +1,10 @@
<TR>
- <TD BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TD>
+ <TD BGCOLOR="#e8e8e8" COLSPAN=<% $opt{colspan} || 2 %>>&nbsp;</TD>
</TR>
<% include('tr-justtitle.html', @_) %>
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css
index 97c7da8..33ad90c 100644
--- a/httemplate/elements/xmenu.css
+++ b/httemplate/elements/xmenu.css
@@ -128,6 +128,8 @@
padding: 1px 5px 1px 5px;
+ font-size: 14px;
+
/* color: black; */
color: white;
text-decoration: none;
diff --git a/httemplate/elements/xmenu.top.css b/httemplate/elements/xmenu.top.css
index 7591703..e86e4a6 100644
--- a/httemplate/elements/xmenu.top.css
+++ b/httemplate/elements/xmenu.top.css
@@ -125,6 +125,8 @@
padding: 1px 5px 1px 5px;
+ font-size: 16px;
+
/* color: black; */
color: white;
text-decoration: none;
diff --git a/httemplate/graph/cust_bill_pkg.cgi b/httemplate/graph/cust_bill_pkg.cgi
index d7cae80..832660f 100644
--- a/httemplate/graph/cust_bill_pkg.cgi
+++ b/httemplate/graph/cust_bill_pkg.cgi
@@ -9,7 +9,7 @@
'links' => \@links,
'remove_empty' => 1,
'bottom_total' => 1,
- 'bottom_link' => "$link;",
+ 'bottom_link' => $bottom_link,
'agentnum' => $agentnum,
)
%>
@@ -18,34 +18,62 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+my $link = "${p}search/cust_bill_pkg.cgi?nottax=1;include_comp_cust=1";
+my $bottom_link = "$link;";
+
#XXX or virtual
my( $agentnum, $sel_agent ) = ('', '');
if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
$agentnum = $1;
+ $bottom_link .= "agentnum=$agentnum;";
$sel_agent = qsearchs('agent', { 'agentnum' => $agentnum } );
die "agentnum $agentnum not found!" unless $sel_agent;
}
my $title = $sel_agent ? $sel_agent->agent.' ' : '';
-#false lazinessish w/search/cust_pkg.cgi
+#classnum (here)
+# 0: all classes
+# not specified: empty class
+# N: classnum
+#classnum (link)
+# not specified: all classes
+# 0: empty class
+# N: classnum
+
+#false lazinessish w/FS::cust_pkg::search_sql (previously search/cust_pkg.cgi)
my $classnum = 0;
my @pkg_class = ();
if ( $cgi->param('classnum') =~ /^(\d*)$/ ) {
$classnum = $1;
- if ( $classnum ) {
+
+ if ( $classnum ) { #a specific class
+
@pkg_class = ( qsearchs('pkg_class', { 'classnum' => $classnum } ) );
die "classnum $classnum not found!" unless $pkg_class[0];
$title .= $pkg_class[0]->classname.' ';
- } elsif ( $classnum eq '' ) {
+ $bottom_link .= "classnum=$classnum;";
+
+ } elsif ( $classnum eq '' ) { #the empty class
+
$title .= 'Empty class ';
@pkg_class = ( '(empty class)' );
- } elsif ( $classnum eq '0' ) {
+ $bottom_link .= "classnum=0;";
+
+ } elsif ( $classnum eq '0' ) { #all classes
+
@pkg_class = qsearch('pkg_class', {} ); # { 'disabled' => '' } );
push @pkg_class, '(empty class)';
+
}
}
#eslaf
+my $use_override = 0;
+$use_override = 1 if ( $cgi->param('use_override') );
+
+my $use_usage = 0;
+$use_usage = 1 if ( $cgi->param('use_usage') );
+
my $hue = 0;
#my $hue_increment = 170;
#my $hue_increment = 145;
@@ -57,8 +85,6 @@ my @labels = ();
my @colors = ();
my @links = ();
-my $link = "${p}search/cust_bill_pkg.cgi?nottax=1;include_comp_cust=1";
-
foreach my $agent ( $sel_agent || qsearch('agent', { 'disabled' => '' } ) ) {
my $col_scheme = Color::Scheme->new
@@ -69,34 +95,40 @@ foreach my $agent ( $sel_agent || qsearch('agent', { 'disabled' => '' } ) ) {
my @onetime_colors = ();
### fixup the color handling for package classes...
+ ### and usage
my $n = 0;
foreach my $pkg_class ( @pkg_class ) {
-
- push @items, 'cust_bill_pkg';
-
-
- push @labels,
- ( $sel_agent ? '' : $agent->agent.' ' ).
- ( $classnum eq '0'
- ? ( ref($pkg_class) ? $pkg_class->classname : $pkg_class )
- : ''
- );
-
- my $row_classnum = ref($pkg_class) ? $pkg_class->classnum : 0;
- my $row_agentnum = $agent->agentnum;
- push @params, [ 'classnum' => $row_classnum,
- 'agentnum' => $row_agentnum,
- ];
-
- push @links, "$link;agentnum=$row_agentnum;classnum=$row_classnum;";
-
- @recur_colors = ($col_scheme->colors)[0,4,8,1,5,9]
- unless @recur_colors;
- @onetime_colors = ($col_scheme->colors)[2,6,10,3,7,11]
- unless @onetime_colors;
- push @colors, shift @recur_colors;
-
+ foreach my $component ( $use_usage ? ('recurring', 'usage') : ('') ) {
+
+ push @items, 'cust_bill_pkg';
+
+ push @labels,
+ ( $sel_agent ? '' : $agent->agent.' ' ).
+ ( $classnum eq '0'
+ ? ( ref($pkg_class) ? $pkg_class->classname : $pkg_class )
+ : ''
+ ).
+ " $component";
+
+ my $row_classnum = ref($pkg_class) ? $pkg_class->classnum : 0;
+ my $row_agentnum = $agent->agentnum;
+ push @params, [ 'classnum' => $row_classnum,
+ 'agentnum' => $row_agentnum,
+ 'use_override' => $use_override,
+ 'use_usage' => $component,
+ ];
+
+ push @links, "$link;agentnum=$row_agentnum;classnum=$row_classnum;".
+ "use_override=$use_override;use_usage=$component;";
+
+ @recur_colors = ($col_scheme->colors)[0,4,8,1,5,9]
+ unless @recur_colors;
+ @onetime_colors = ($col_scheme->colors)[2,6,10,3,7,11]
+ unless @onetime_colors;
+ push @colors, shift @recur_colors;
+
+ }
}
$hue += $hue_increment;
diff --git a/httemplate/graph/cust_bill_pkg_detail.cgi b/httemplate/graph/cust_bill_pkg_detail.cgi
new file mode 100644
index 0000000..642a9ec
--- /dev/null
+++ b/httemplate/graph/cust_bill_pkg_detail.cgi
@@ -0,0 +1,137 @@
+<% include('elements/monthly.html',
+ 'title' => $title. 'Rated Call Sales Report (Gross)',
+ 'graph_type' => 'Mountain',
+ 'items' => \@items,
+ 'params' => \@params,
+ 'labels' => \@labels,
+ 'graph_labels' => \@labels,
+ 'colors' => \@colors,
+ 'remove_empty' => 1,
+ 'bottom_total' => 1,
+ 'agentnum' => $agentnum,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+#XXX or virtual
+my( $agentnum, $sel_agent ) = ('', '');
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+ $sel_agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ die "agentnum $agentnum not found!" unless $sel_agent;
+}
+my $title = $sel_agent ? $sel_agent->agent.' ' : '';
+
+#false lazinessish w/FS::cust_pkg::search_sql (previously search/cust_pkg.cgi)
+my $classnum = '';
+if ( $cgi->param('classnum') =~ /^(\d*)$/ ) {
+ $classnum = $1;
+
+ if ( $classnum ) { #a specific class
+
+ my $pkg_class = ( qsearchs('pkg_class', { 'classnum' => $classnum } ) );
+ die "classnum $classnum not found!" unless $pkg_class;
+ $title .= $pkg_class->classname.' ';
+
+ } elsif ( $classnum eq '' ) { #the empty class
+
+ $title .= 'Empty class ';
+ # FS::Report::Table::Monthly.pm has the converse view
+ $classnum = 0;
+
+ } elsif ( $classnum eq '0' ) { #all classes
+
+ # FS::Report::Table::Monthly.pm has the converse view
+ $classnum = '';
+ }
+}
+#eslaf
+
+my $use_override = 0;
+$use_override = 1 if ( $cgi->param('use_override') );
+
+my $usageclass = 0;
+my @usage_class = ();
+if ( $cgi->param('usageclass') =~ /^(\d*)$/ ) {
+ $usageclass = $1;
+
+ if ( $usageclass ) { #a specific class
+
+ @usage_class = ( qsearchs('usage_class', { 'classnum' => $usageclass } ) );
+ die "usage class $usageclass not found!" unless $usage_class[0];
+ $title .= $usage_class[0]->classname.' ';
+
+ } elsif ( $usageclass eq '' ) { #the empty class -- legacy
+
+ $title .= 'Empty usage class ';
+ @usage_class = ( '(empty usage class)' );
+
+ } elsif ( $usageclass eq '0' ) { #all classes
+
+ @usage_class = qsearch('usage_class', {} ); # { 'disabled' => '' } );
+ push @usage_class, '(empty usage class)';
+
+ }
+}
+#eslaf
+
+my $hue = 0;
+#my $hue_increment = 170;
+#my $hue_increment = 145;
+my $hue_increment = 125;
+
+my @items = ();
+my @params = ();
+my @labels = ();
+my @colors = ();
+
+foreach my $agent ( $sel_agent || qsearch('agent', { 'disabled' => '' } ) ) {
+
+ my $col_scheme = Color::Scheme->new
+ ->from_hue($hue) #->from_hex($agent->color)
+ ->scheme('analogic')
+ ;
+ my @recur_colors = ();
+ my @onetime_colors = ();
+
+ ### fixup the color handling for usage classes...
+ my $n = 0;
+
+ foreach my $usage_class ( @usage_class ) {
+
+ push @items, 'cust_bill_pkg_detail';
+
+ push @labels,
+ ( $sel_agent ? '' : $agent->agent.' ' ).
+ ( $usageclass eq '0'
+ ? ( ref($usage_class) ? $usage_class->classname : $usage_class )
+ : ''
+ );
+
+ my $row_classnum = ref($usage_class) ? $usage_class->classnum : 0;
+ my $row_agentnum = $agent->agentnum;
+ push @params, [ 'usageclass' => $row_classnum,
+ 'agentnum' => $row_agentnum,
+ 'use_override' => $use_override,
+ 'classnum' => $classnum,
+ ];
+
+ @recur_colors = ($col_scheme->colors)[0,4,8,1,5,9]
+ unless @recur_colors;
+ @onetime_colors = ($col_scheme->colors)[2,6,10,3,7,11]
+ unless @onetime_colors;
+ push @colors, shift @recur_colors;
+
+ }
+
+ $hue += $hue_increment;
+
+}
+
+#use Data::Dumper;
+#warn Dumper(\@items);
+
+</%init>
diff --git a/httemplate/graph/report_cust_bill_pkg.html b/httemplate/graph/report_cust_bill_pkg.html
index 5193bf4..51655a9 100644
--- a/httemplate/graph/report_cust_bill_pkg.html
+++ b/httemplate/graph/report_cust_bill_pkg.html
@@ -25,6 +25,17 @@
</TR>
-->
+<TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="use_override" VALUE="1"></TD>
+ <TD>Separate sub-packages from parents</TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="use_usage" VALUE="1"></TD>
+ <TD>Separate rated usage from recurring fees</TD>
+</TR>
+
+
</TABLE>
<BR><INPUT TYPE="submit" VALUE="Display">
diff --git a/httemplate/graph/report_cust_bill_pkg_detail.html b/httemplate/graph/report_cust_bill_pkg_detail.html
new file mode 100644
index 0000000..3b85d52
--- /dev/null
+++ b/httemplate/graph/report_cust_bill_pkg_detail.html
@@ -0,0 +1,48 @@
+<% include('/elements/header.html', 'Usage Sales Report' ) %>
+
+<FORM ACTION="cust_bill_pkg_detail.cgi" METHOD="GET">
+
+<TABLE>
+
+<% include('/elements/tr-select-from_to.html' ) %>
+
+<% include('/elements/tr-select-agent.html',
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0,
+ )
+%>
+
+<% include('/elements/tr-select-pkg_class.html',
+ 'pre_options' => [ '0' => 'all' ],
+ 'empty_label' => '(empty class)',
+ )
+%>
+
+<TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="use_override" VALUE="1"></TD>
+ <TD>Separate sub-packages from parents</TD>
+</TR>
+
+<% include('/elements/tr-select-table.html',
+ 'label' => 'Usage class: ',
+ 'element_name' => 'usageclass',
+ 'table' => 'usage_class',
+ 'name_col' => 'classname',
+ 'hashref' => { 'disabled' => '' },
+ 'pre_options' => [ '0' => 'all' ],
+ 'empty_label' => '(empty class)',
+ )
+%>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Display">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/images/gray-black-side.png b/httemplate/images/gray-black-side.png
new file mode 100644
index 0000000..b384930
--- /dev/null
+++ b/httemplate/images/gray-black-side.png
Binary files differ
diff --git a/httemplate/misc/bulk_change_pkg.cgi b/httemplate/misc/bulk_change_pkg.cgi
index 9334985..7f47a84 100755
--- a/httemplate/misc/bulk_change_pkg.cgi
+++ b/httemplate/misc/bulk_change_pkg.cgi
@@ -7,17 +7,23 @@
<FORM ACTION="<% $p %>misc/process/bulk_change_pkg.cgi" METHOD=POST>
-<INPUT TYPE="hidden" NAME="query" VALUE="<% $cgi->keywords %>">
-% for my $param (qw(agentnum magic status classnum pkgpart)) {
-<INPUT TYPE="hidden" NAME="<% $param %>" VALUE="<% $cgi->param($param) %>">
+%# some false laziness w/search/cust_pkg.cgi
+
+<INPUT TYPE="hidden" NAME="query" VALUE="<% $cgi->keywords |h %>">
+% for my $param (qw(agentnum magic status classnum custom censustract)) {
+<INPUT TYPE="hidden" NAME="<% $param %>" VALUE="<% $cgi->param($param) |h %>">
% }
%
+% foreach my $pkgpart ($cgi->param('pkgpart')) {
+<INPUT TYPE="hidden" NAME="pkgpart" VALUE="<% $pkgpart |h %>">
+% }
+%
% foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
%
- <INPUT TYPE="hidden" NAME="<% $field %>begin" VALUE="<% $cgi->param("${field}.begin") %>">
- <INPUT TYPE="hidden" NAME="<% $field %>beginning" VALUE="<% $cgi->param("${field}beginning") %>">
- <INPUT TYPE="hidden" NAME="<% $field %>end" VALUE="<% $cgi->param("${field}.end") %>">
- <INPUT TYPE="hidden" NAME="<% $field %>ending" VALUE="<% $cgi->param("${field}.ending") %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>begin" VALUE="<% $cgi->param("${field}.begin") |h %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>beginning" VALUE="<% $cgi->param("${field}beginning") |h %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>end" VALUE="<% $cgi->param("${field}.end") |h %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>ending" VALUE="<% $cgi->param("${field}.ending") |h %>">
% }
<% ntable('#cccccc') %>
@@ -28,10 +34,7 @@
'table' => 'part_pkg',
'name_col' => 'pkg',
'empty_label' => 'Select package',
- 'label_callback' => sub { $_[0]->pkgpart. ': '.
- $_[0]->pkg. ' - '.
- $_[0]->comment;
- },
+ 'label_callback' => sub { $_[0]->pkg_comment },
'element_name' => 'new_pkgpart',
'curr_value' => ( $cgi->param('error')
? scalar($cgi->param('new_pkgpart'))
diff --git a/httemplate/misc/cancel_pkg.html b/httemplate/misc/cancel_pkg.html
index e0e5fd1..607ce13 100755
--- a/httemplate/misc/cancel_pkg.html
+++ b/httemplate/misc/cancel_pkg.html
@@ -17,7 +17,7 @@
<BR><BR>
-<% ucfirst($method) . " $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% ucfirst($method) %> <% $part_pkg->pkg_comment %>
<% ntable("#cccccc", 2) %>
% if ($method eq 'expire' || $method eq 'adjourn') {
diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi
index c4dfca2..16b7071 100755
--- a/httemplate/misc/change_pkg.cgi
+++ b/httemplate/misc/change_pkg.cgi
@@ -13,19 +13,15 @@
<% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B> - <% $part_pkg->comment |h %>
</TD>
</TR>
-
- <TR>
- <TH ALIGN="right">New package</TH>
- <TD COLSPAN=7>
- <% include('/elements/select-cust-part_pkg.html',
- 'cust_main' => $cust_main,
- 'element_name' => 'pkgpart',
- #'extra_sql' => ' AND pkgpart != '. $cust_pkg->pkgpart,
- 'curr_value' => scalar($cgi->param('pkgpart')),
- )
- %>
- </TD>
- </TR>
+
+ <% include('/elements/tr-select-cust-part_pkg.html',
+ 'pre_label' => 'New',
+ 'curr_value' => scalar($cgi->param('pkgpart')),
+ 'classnum' => $part_pkg->classnum,
+ 'cust_main' => $cust_main,
+ #'extra_sql' => ' AND pkgpart != '. $cust_pkg->pkgpart,
+ )
+ %>
<% include('/elements/tr-select-cust_location.html',
'cgi' => $cgi,
diff --git a/httemplate/misc/cust-part_pkg.cgi b/httemplate/misc/cust-part_pkg.cgi
new file mode 100644
index 0000000..a249f03
--- /dev/null
+++ b/httemplate/misc/cust-part_pkg.cgi
@@ -0,0 +1,29 @@
+<% objToJson( \@return ) %>
+<%init>
+
+my( $custnum, $classnum ) = $cgi->param('arg');
+
+#XXX i guess i should be agent-virtualized. cause "packages a customer can
+#order" is such a huge deal
+my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+
+my %hash = ( 'disabled' => '' );
+if ( $classnum > 0 ) {
+ $hash{'classnum'} = $classnum;
+} elsif ( $classnum eq '' || $classnum == 0 ) {
+ $hash{'classnum'} = '';
+} #else -1, all classes, so don't set classnum
+
+my @part_pkg = qsearch({
+ 'table' => 'part_pkg',
+ 'hashref' => \%hash,
+ 'extra_sql' =>
+ ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ).
+ ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent ),
+});
+
+my @return = map { $_->pkgpart => $_->pkg_comment }
+ sort { $a->pkg_comment cmp $b->pkg_comment }
+ @part_pkg;
+
+</%init>
diff --git a/httemplate/misc/cust_main-import.cgi b/httemplate/misc/cust_main-import.cgi
index b822c5d..9c1f984 100644
--- a/httemplate/misc/cust_main-import.cgi
+++ b/httemplate/misc/cust_main-import.cgi
@@ -56,7 +56,7 @@ Import a file containing customer records.
<SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) {
- <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+ <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg_comment %></OPTION>
% }
</SELECT>
diff --git a/httemplate/misc/delay_susp_pkg.html b/httemplate/misc/delay_susp_pkg.html
index 1158a35..d4a6da1 100755
--- a/httemplate/misc/delay_susp_pkg.html
+++ b/httemplate/misc/delay_susp_pkg.html
@@ -12,7 +12,7 @@
<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
<BR><BR>
-<% "Delay automatic suspension of $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% "Delay automatic suspension of " .$part_pkg->pkg_comment %>
<% ntable("#cccccc", 2) %>
<TR>
diff --git a/httemplate/misc/delete-cust_bill.html b/httemplate/misc/delete-cust_bill.html
new file mode 100644
index 0000000..3a642b0
--- /dev/null
+++ b/httemplate/misc/delete-cust_bill.html
@@ -0,0 +1,21 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal crednum";
+my $invnum = $1;
+
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+my $custnum = $cust_bill->custnum;
+
+my $error = $cust_bill->delete;
+
+</%init>
diff --git a/httemplate/misc/delete-phone_device.html b/httemplate/misc/delete-phone_device.html
new file mode 100755
index 0000000..7220c41
--- /dev/null
+++ b/httemplate/misc/delete-phone_device.html
@@ -0,0 +1,23 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/svc_phone.cgi?". $svcnum) %>
+% }
+<%init>
+
+# :/ needs agent-virt so you can't futz with arbitrary devices
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+#untaint devicenum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal devicenum";
+my $devicenum = $1;
+
+my $phone_device = qsearchs('phone_device', { 'devicenum' => $devicenum } );
+my $svcnum = $phone_device->svcnum;
+
+my $error = $phone_device->delete;
+
+</%init>
diff --git a/httemplate/misc/download-batch.cgi b/httemplate/misc/download-batch.cgi
index 57905da..01bf5d2 100644
--- a/httemplate/misc/download-batch.cgi
+++ b/httemplate/misc/download-batch.cgi
@@ -1,146 +1,9 @@
-%if ($format eq "BoM") {
-%
-% my($origid,$datacenter,$typecode,$shortname,$longname,$mybank,$myacct) =
-% $conf->config("batchconfig-$format");
-%
-<% sprintf( "A%10s%04u%06u%05u%54s\n",$origid,$pay_batch->batchnum,$jdate,$datacenter,"").
- sprintf( "XD%03u%06u%-15s%-30s%09u%-12s \n",$typecode,$jdate,$shortname,$longname,$mybank,$myacct )
- %>
-%
-%}elsif ($format eq "PAP"){
-%
-% my($origid,$datacenter,$typecode,$shortname,$longname,$mybank,$myacct) =
-% $conf->config("batchconfig-$format");
-%
-<% sprintf( "H%10sD%3s%06u%-15s%09u%-12s%04u%19s\n",$origid,$typecode,$cdate,$shortname,$mybank,$myacct,$pay_batch->batchnum,"") %>
-%
-%
-%}elsif ($format eq "csv-td_canada_trust-merchant_pc_batch"){
-%# 1;
-%}elsif ($format eq "csv-chase_canada-E-xactBatch"){
-%
-% my($origid) = $conf->config("batchconfig-$format");
-<% sprintf( '$$E-xactBatchFileV1.0$$%s:%03u$$%s',$sdate,$pay_batch->batchnum, $origid)
- %>
-%
-%}elsif ($format eq "ach-spiritone"){
-%# 1;
-%}else{
-% die "Unknown format for batch in batchconfig. \n";
-%}
-%
-%
-%for my $cust_pay_batch ( sort { $a->paybatchnum <=> $b->paybatchnum }
-% qsearch('cust_pay_batch',
-% {'batchnum'=>$pay_batch->batchnum} )
-%) {
-%
-% $cust_pay_batch->exp =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
-% my( $mon, $y ) = ( $2, $1 );
-% if ( $conf->exists('batch-increment_expiration') ) {
-% my( $curmon, $curyear ) = (localtime(time))[4,5];
-% $curmon++; $curyear-=100;
-% $y++ while $y < $curyear || ( $y == $curyear && $mon < $curmon );
-% }
-% $mon = "0$mon" if $mon =~ /^\d$/;
-% $y = "0$y" if $y =~ /^\d$/;
-% my $exp = "$mon$y";
-%
-% if ( $first_download ) {
-% my $balance = $cust_pay_batch->cust_main->balance;
-% if ( $balance <= 0 ) {
-% my $error = $cust_pay_batch->delete;
-% if ( $error ) {
-% $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
-% die $error;
-% }
-% next;
-% } elsif ( $balance < $cust_pay_batch->amount ) {
-% $cust_pay_batch->amount($balance);
-% my $error = $cust_pay_batch->replace;
-% if ( $error ) {
-% $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
-% die $error;
-% }
-% #} elsif ( $balance > $cust_pay_batch->amount ) {
-% }
-% }
-%
-% $batchcount++;
-% $batchtotal += $cust_pay_batch->amount;
-%
-% if ($format eq "BoM") {
-%
-% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
-%
-<% sprintf( "D%010.0f%09u%-12s%-29s%-19s\n",$cust_pay_batch->amount*100,$aba,$account,$cust_pay_batch->payname,$cust_pay_batch->paybatchnum) %>
-%
-%
-% } elsif ($format eq "PAP"){
-%
-% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
-%
-<% sprintf( "D%-23s%06u%-19s%09u%-12s%010.0f\n",$cust_pay_batch->payname,$cdate,$cust_pay_batch->paybatchnum,$aba,$account,$cust_pay_batch->amount*100) %>
-%
-%
-% } elsif ($format eq "csv-td_canada_trust-merchant_pc_batch") {
-%
-%
-,,,,<% $cust_pay_batch->payinfo %>,<% $exp %>,<% $cust_pay_batch->amount %>,<% $cust_pay_batch->paybatchnum %>
-%
-%
-% } elsif ($format eq "csv-chase_canada-E-xactBatch"){
-%
-% my $payname=$cust_pay_batch->payname; $payname =~ tr/",/ /; #payinfo too? :P
-<% $cust_pay_batch->paybatchnum %>,<% $cust_pay_batch->custnum %>,<% $cust_pay_batch->invnum %>,"<% $payname %>",00,<% $cust_pay_batch->payinfo %>,<% $cust_pay_batch->amount %>,<% $exp %>,,
-%
-%
-% }elsif ($format eq "ach-spiritone"){
-%
-% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
-% my $payname=$cust_pay_batch->first. " ". $cust_pay_batch->last;
-% $payname =~ tr/",/ /; #payinfo too?
-% my $batchline = qq!"$payname","!.$cust_pay_batch->paybatchnum.
-% qq!","$aba","$account","27","!.$cust_pay_batch->amount.
-% qq!","27","0.00"!;
-% push @batchlines, $batchline;
-<% $batchline %>
-%
-% } else {
-% die "I'm already dead, but you did not know that.\n";
-% }
-%
-%}
-%
-%if ($format eq "BoM") {
-%
-%
-<% sprintf( "YD%08u%014.0f%56s\n",$batchcount,$batchtotal*100,"" ).
- sprintf( "Z%014u%05u%014u%05u%41s\n",$batchtotal*100,$batchcount,"0","0","" ) %>
-%
-%
-%} elsif ($format eq "PAP"){
-%
-%
-<% sprintf( "T%08u%014.0f%57s\n",$batchcount,$batchtotal*100,"" ) %>
-%
-%
-%} elsif ($format eq "csv-td_canada_trust-merchant_pc_batch"){
-% #1;
-%} elsif ($format eq "csv-chase_canada-E-xactBatch"){
-% #1;
-%} elsif ($format eq "ach-spiritone"){
-% #1;
-%} else {
-% die "I'm already dead (again), but you did not know that.\n";
-%}
-%
-<%init>
+<% $pay_batch->export_batch($format) %>
-my $conf=new FS::Conf;
+<%init>
#http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
-http_header('Content-Type' => 'text/plain' );
+http_header('Content-Type' => 'text/plain' ); # not necessarily correct...
my $batchnum;
if ( $cgi->param('batchnum') =~ /^(\d+)$/ ) {
@@ -152,62 +15,9 @@ if ( $cgi->param('batchnum') =~ /^(\d+)$/ ) {
my $format;
if ( $cgi->param('format') =~ /^([\w\- ]+)$/ ) {
$format = $1;
-} else {
- $format = $conf->config('batch-default_format');
-}
-
-my $autopost;
-if ( $format eq 'ach-spiritone' ) {
- $autopost = 1;
-}else{
- $autopost = 0;
-}
-
-my $oldAutoCommit = $FS::UID::AutoCommit;
-local $FS::UID::AutoCommit = 0;
-my $dbh = dbh;
-
-my $pay_batch = qsearchs('pay_batch', {'batchnum'=>$batchnum, 'status'=>'O'} );
-my $first_download = 1;
-unless ($pay_batch) {
- $pay_batch = qsearchs('pay_batch', {'batchnum'=>$batchnum, 'status'=>'I'} )
- if $FS::CurrentUser::CurrentUser->access_right('Reprocess batches');
- $first_download = 0;
}
-die "No pending batch. \n" unless $pay_batch;
-my $error = $pay_batch->set_status('I');
-die "error updating batch status: $error\n" if $error;
+my $pay_batch = qsearchs('pay_batch', { batchnum => $batchnum } );
+die "Batch not found: '$batchnum'" if !$pay_batch;
-my $batchtotal=0;
-my $batchcount=0;
-
-my (@date)=localtime($pay_batch->download);
-my $jdate = sprintf("%03d", $date[5] % 100).sprintf("%03d", $date[7] + 1);
-my $cdate = sprintf("%02d", $date[3]).sprintf("%02d", $date[4] + 1).
- sprintf("%02d", $date[5] % 100);
-my $sdate = sprintf("%02d", $date[5] % 100).'/'.sprintf("%02d", $date[4] + 1).
- '/'.sprintf("%02d", $date[3]);
-
-my @batchlines = ();
</%init>
-<%cleanup>
-if ($autopost) {
- my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
- my $fh = new File::Temp(
- TEMPLATE => 'paybatch.'. $batchnum .'.XXXXXXXX',
- DIR => $dir,
- ) or die "can't open temp file: $!\n";
-
- print $fh map{ "$_\n" } @batchlines;
- seek $fh, 0, 0;
-
- $error = $pay_batch->import_results( 'filehandle' => $fh,
- 'format' => $format,
- );
- die $error if $error;
-}
-
-$dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
-</%cleanup>
diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html
index 0d3d622..f644db9 100644
--- a/httemplate/misc/email-customers.html
+++ b/httemplate/misc/email-customers.html
@@ -126,7 +126,7 @@ die "access denied"
my %search = $cgi->Vars;
delete $search{$_} for qw( magic from subject html_body text_body );
$search{$_} = [ split(/\0/, $search{$_}) ]
- foreach grep $search{$_} =~ /\0/, keys %search;
+ foreach grep { $_ eq 'payby' || $search{$_} =~ /\0/ } keys %search;
my $title = 'Bulk send customer notices';
diff --git a/httemplate/misc/link.cgi b/httemplate/misc/link.cgi
index 748eaa1..f37f769 100755
--- a/httemplate/misc/link.cgi
+++ b/httemplate/misc/link.cgi
@@ -58,6 +58,7 @@ die "access denied"
my %link_field = (
'svc_acct' => 'username',
'svc_domain' => 'domain',
+ 'svc_phone' => 'phonenum',
);
my %link_field2 = (
diff --git a/httemplate/misc/meta-import.cgi b/httemplate/misc/meta-import.cgi
index 5b3470c..8c158bd 100644
--- a/httemplate/misc/meta-import.cgi
+++ b/httemplate/misc/meta-import.cgi
@@ -46,7 +46,7 @@ Import data from a DBI data source<BR><BR>
First package: <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) {
- <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+ <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg_comment %></OPTION>
% }
</SELECT><BR><BR>
diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html
index 2c83351..a7571ca 100644
--- a/httemplate/misc/order_pkg.html
+++ b/httemplate/misc/order_pkg.html
@@ -1,5 +1,10 @@
<% include('/elements/header-popup.html', 'Order new package' ) %>
+<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+
<SCRIPT TYPE="text/javascript">
function enable_order_pkg () {
@@ -19,18 +24,42 @@
<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $cust_main->custnum %>">
<% ntable("#cccccc", 2) %>
+<% include('/elements/tr-select-cust-part_pkg.html',
+ 'curr_value' => $pkgpart,
+ 'classnum' => -1,
+ 'cust_main' => $cust_main,
+ 'onchange' => 'enable_order_pkg',
+ )
+%>
+
+%# false laziness w/edit/quick-charge.html
<TR>
- <TH ALIGN="right">Package</TH>
- <TD COLSPAN=7>
- <% include('/elements/select-cust-part_pkg.html',
- 'curr_value' => $pkgpart,
- 'cust_main' => $cust_main,
- 'onchange' => 'enable_order_pkg',
- )
- %>
+ <TH ALIGN="right">Start date </TD>
+ <TD COLSPAN=6>
+ <INPUT TYPE = "text"
+ NAME = "start_date"
+ SIZE = 32
+ ID = "start_date_text"
+ VALUE = "<% $start_date %>"
+ >
+ <IMG SRC = "../images/calendar.png"
+ ID = "start_date_button"
+ STYLE = "cursor: pointer"
+ TITLE = "Select date"
+ >
+ <FONT SIZE=-1>(leave blank to start immediately)</FONT>
</TD>
</TR>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "start_date_text",
+ ifFormat: "%m/%d/%Y",
+ button: "start_date_button",
+ align: "BR"
+ });
+</SCRIPT>
+
% if ( $conf->exists('pkg_referral') ) {
<% include('/elements/tr-select-part_referral.html',
'curr_value' => scalar( $cgi->param('refnum') ), #get rid of empty_label first# || $cust_main->refnum,
@@ -72,4 +101,8 @@ my $cust_main = qsearchs({
my $pkgpart = scalar($cgi->param('pkgpart'));
+my $format = "%m/%d/%Y %T %z (%Z)"; #false laziness w/REAL_cust_pkg.cgi?
+my $start_date = $cust_main->next_bill_date;
+$start_date = $start_date ? time2str($format, $start_date) : '';
+
</%init>
diff --git a/httemplate/misc/part_device-import.html b/httemplate/misc/part_device-import.html
new file mode 100644
index 0000000..7bd6404
--- /dev/null
+++ b/httemplate/misc/part_device-import.html
@@ -0,0 +1,53 @@
+<% include("/elements/header.html", 'Import device types') %>
+
+Import a file containing phone device types, one per line.
+<BR><BR>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'PartDeviceImportForm',
+ 'action' => 'process/part_device-import.html',
+ 'num_files' => 1,
+ 'fields' => [ 'format', ],
+ 'message' => 'Device type import successful',
+ 'url' => $p.'browse/part_device.html',
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <INPUT TYPE="hidden" NAME="format" VALUE="default">
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => 'Filename',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Import file"
+ onClick = "document.PartDeviceImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+
+Upload file can be a text file or Excel spreadsheet. If an Excel spreadsheet,
+ should have an .XLS extension.
+<BR><BR>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/part_svc-columns.cgi b/httemplate/misc/part_svc-columns.cgi
new file mode 100644
index 0000000..0602561
--- /dev/null
+++ b/httemplate/misc/part_svc-columns.cgi
@@ -0,0 +1,13 @@
+<% objToJson(\@output) %>
+<%init>
+
+my $conf = new FS::Conf;
+
+my $pkgpart_svcpart = $cgi->param('arg');
+$pkgpart_svcpart =~ /^\d+_(\d+)$/;
+my $part_svc = qsearchs('part_svc', { 'svcpart' => $1 }) if $1;
+
+my @output = map { ( $_->columnname, $_->columnflag, $_->columnvalue ) }
+ $part_svc->all_part_svc_column;
+
+</%init>
diff --git a/httemplate/misc/payment.cgi b/httemplate/misc/payment.cgi
index 0047004..813b560 100644
--- a/httemplate/misc/payment.cgi
+++ b/httemplate/misc/payment.cgi
@@ -12,23 +12,66 @@
<% ntable('#cccccc') %>
<TR>
- <TD ALIGN="right">Payment amount</TD>
- <TD>
+ <TH ALIGN="right">Payment amount</TH>
+ <TD COLSPAN=7>
<TABLE><TR><TD BGCOLOR="#ffffff">
- $<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<% $balance > 0 ? sprintf("%.2f", $balance) : '' %>">
+ <% $money_char %><INPUT NAME = "amount"
+ TYPE = "text"
+ VALUE = "<% $amount %>"
+ SIZE = 8
+ STYLE = "text-align:right;"
+% if ( $fee ) {
+ onChange = "amount_changed(this)"
+ onKeyDown = "amount_changed(this)"
+ onKeyUp = "amount_changed(this)"
+ onKeyPress = "amount_changed(this)"
+% }
+ >
+ </TD><TD BGCOLOR="#cccccc">
+% if ( $fee ) {
+ <INPUT TYPE="hidden" NAME="fee_pkgpart" VALUE="<% $fee_pkg->pkgpart %>">
+ <INPUT TYPE="hidden" NAME="fee" VALUE="<% $fee_display eq 'add' ? $fee : '' %>">
+ <B><FONT SIZE='+1'><% $fee_op %></FONT>
+ <% $money_char . $fee %>
+ </B>
+ <% $fee_pkg->pkg |h %>
+ <B><FONT SIZE='+1'>=</FONT></B>
+ </TD><TD ID="ajax_total_cell" BGCOLOR="#dddddd" STYLE="border:1px solid blue">
+ <FONT SIZE="+1"><% length($amount) ? $money_char. sprintf('%.2f', ($fee_display eq 'add') ? $amount + $fee : $amount - $fee ) : '' %> <% $fee_display eq 'add' ? 'TOTAL' : 'AVAILABLE' %></FONT>
+
+% }
</TD></TR></TABLE>
</TD>
</TR>
+% if ( $fee ) {
+
+ <SCRIPT TYPE="text/javascript">
+
+ function amount_changed(what) {
+
+
+ var total = '';
+ if ( what.value.length ) {
+ total = parseFloat(what.value) <% $fee_op %> <% $fee %>;
+ /* total = Math.round(total*100)/100; */
+ total = '<% $money_char %>' + total.toFixed(2);
+ }
+
+ var total_cell = document.getElementById('ajax_total_cell');
+ total_cell.innerHTML = '<FONT SIZE="+1">' + total + ' <% $fee_display eq 'add' ? 'TOTAL' : 'AVAILABLE' %></FONT>';
+
+ }
+
+ </SCRIPT>
+
+% }
+
+
% if ( $payby eq 'CARD' ) {
%
% my( $payinfo, $paycvv, $month, $year ) = ( '', '', '', '' );
% my $payname = $cust_main->first. ' '. $cust_main->getfield('last');
-% my $address1 = $cust_main->address1;
-% my $address2 = $cust_main->address2;
-% my $city = $cust_main->city;
-% my $state = $cust_main->state;
-% my $zip = $cust_main->zip;
% if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) {
% $payinfo = $cust_main->paymask;
% $paycvv = $cust_main->paycvv;
@@ -37,13 +80,13 @@
% }
<TR>
- <TD ALIGN="right">Card&nbsp;number</TD>
- <TD>
+ <TH ALIGN="right">Card&nbsp;number</TH>
+ <TD COLSPAN=7>
<TABLE>
<TR>
<TD>
<INPUT TYPE="text" NAME="payinfo" SIZE=20 MAXLENGTH=19 VALUE="<%$payinfo%>"> </TD>
- <TD>Exp.</TD>
+ <TH>Exp.</TH>
<TD>
<SELECT NAME="month">
% for ( ( map "0$_", 1 .. 9 ), 10 .. 12 ) {
@@ -68,51 +111,23 @@
</TD>
</TR>
<TR>
- <TD ALIGN="right">CVV2</TD>
+ <TH ALIGN="right">CVV2</TH>
<TD><INPUT TYPE="text" NAME="paycvv" VALUE="<% $paycvv %>" SIZE=4 MAXLENGTH=4>
(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)
</TD>
</TR>
<TR>
- <TD ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TD>
+ <TH ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TH>
<TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%$payname%>"></TD>
- </TR><TR>
- <TD ALIGN="right">Card&nbsp;billing&nbsp;address</TD>
- <TD>
- <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address1" VALUE="<%$address1%>">
- </TD>
- </TR><TR>
- <TD ALIGN="right">Address&nbsp;line&nbsp;2</TD>
- <TD>
- <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address2" VALUE="<%$address2%>">
- </TD>
- </TR><TR>
- <TD ALIGN="right">City</TD>
- <TD>
- <TABLE>
- <TR>
- <TD>
- <INPUT TYPE="text" NAME="city" SIZE="12" MAXLENGTH=80 VALUE="<%$city%>">
- </TD>
- <TD>State</TD>
- <TD>
- <SELECT NAME="state">
-% for ( @states ) {
-
- <OPTION<% $_ eq $state ? ' SELECTED' : '' %>><% $_ %>
-% }
-
- </SELECT>
- </TD>
- <TD>Zip</TD>
- <TD>
- <INPUT TYPE="text" NAME="zip" SIZE=11 MAXLENGTH=10 VALUE="<%$zip%>">
- </TD>
- </TR>
- </TABLE>
- </TD>
</TR>
+ <% include( '/elements/location.html',
+ 'object' => $cust_main, #XXX errors???
+ 'no_asterisks' => 1,
+ 'address1_label' => 'Card billing address',
+ )
+ %>
+
% } elsif ( $payby eq 'CHEK' ) {
%
% my( $payinfo1, $payinfo2, $payname, $ss, $paytype, $paystate,
@@ -270,16 +285,51 @@ my $balance = $cust_main->balance;
my $payinfo = '';
-#false laziness w/selfservice make_payment.html shortcut for one-country
my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+#false laziness w/selfservice make_payment.html shortcut for one-country
my %states = map { $_->state => 1 }
qsearch('cust_main_county', {
'country' => $conf->config('countrydefault') || 'US'
} );
my @states = sort { $a cmp $b } keys %states;
+my $fee = '';
+my $fee_pkg = '';
+my $fee_display = '';
+my $fee_op = '';
+my $num_payments = scalar($cust_main->cust_pay);
+#handle old cust_main.pm (remove...)
+$num_payments = scalar( @{ [ $cust_main->cust_pay ] } )
+ unless defined $num_payments;
+if ( $conf->config('manual_process-pkgpart')
+ and ! $conf->exists('manual_process-skip_first') || $num_payments
+ )
+{
+
+ $fee_display = $conf->config('manual_process-display') || 'add';
+ $fee_op = $fee_display eq 'add' ? '+' : '-';
+
+ $fee_pkg =
+ qsearchs('part_pkg', { pkgpart=>$conf->config('manual_process-pkgpart') } );
+
+ #well ->unit_setup or ->calc_setup both call for a $cust_pkg
+ # (though ->unit_setup doesn't use it...)
+ $fee = $fee_pkg->option('setup_fee')
+ if $fee_pkg; #in case.. better than dying with a perl traceback
+
+}
+
+my $amount = '';
+if ( $balance > 0 ) {
+ $amount = $balance;
+ $amount += $fee
+ if $fee && $fee_display eq 'subtract';
+ $amount = sprintf("%.2f", $amount);
+}
+
my $payunique = "webui-payment-". time. "-$$-". rand() * 2**32;
</%init>
-
-
diff --git a/httemplate/misc/ping.html b/httemplate/misc/ping.html
new file mode 100644
index 0000000..4f0360e
--- /dev/null
+++ b/httemplate/misc/ping.html
@@ -0,0 +1,102 @@
+<% include('/elements/header-popup.html', "Ping $ip" ) %>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p. 'misc/xmlhttp-ping.html',
+ 'subs' => [ 'ping' ],
+ )
+%>
+
+%# <img src="<%$p%>images/bullet_red.png" border=0>
+
+
+<%ntable("#cccccc", 2)%>
+
+<TR>
+ <TD>Status</TD>
+ <TD BGCOLOR="#ffffff" ID="ping_status">Checking...</TD>
+</TR>
+<TR>
+ <TD>Packet loss</TD>
+ <TD BGCOLOR="#ffffff" ID="ping_packetloss"></TD>
+</TR>
+<TR>
+ <TD>Latency</TD>
+ <TD BGCOLOR="#ffffff" ID="ping_latency"></TD>
+</TR>
+<TR>
+ <TD>Packets</TD>
+ <TD BGCOLOR="#ffffff" ID="ping_packets"></TD>
+</TR>
+
+</TABLE>
+
+<BR>
+<CENTER>
+<INPUT TYPE="button" VALUE="Close" onClick="parent.nd(1);">
+</CENTER>
+
+<SCRIPT TYPE="text/javascript">
+
+ var fails = 0;
+ var pongs = 0;
+ var totaltime = 0;
+ var avg = 0;
+
+ function ping_update ( updatetext ) {
+ var pingArray = eval('(' + updatetext + ')');
+ var status = pingArray[0];
+ var rtt = pingArray[1];
+
+ if ( status == 0 ) {
+ fails++;
+ } else if ( status == 1 ) {
+ pongs++;
+ totaltime = totaltime + rtt;
+ avg = totaltime / pongs;
+ }
+
+ var loss = 100 * fails / ( fails + pongs );
+
+ var statusCell = document.getElementById('ping_status');
+ var packetlossCell = document.getElementById('ping_packetloss');
+ var latencyCell = document.getElementById('ping_latency');
+ var packetsCell = document.getElementById('ping_packets');
+
+ var status = '';
+ // red conditions
+ if ( loss == 100 ) {
+ status = '<FONT COLOR="#ff0000">Unreachable</FONT>';
+ } else
+ // yellow conditions
+ if ( loss > 50 ) {
+ status = '<FONT COLOR="#ff9900">High packet loss</FONT>';
+ } else
+ if ( avg > 1 ) {
+ status = '<FONT COLOR="#ff9900">High latency</FONT>';
+ } else {
+ status = '<FONT COLOR="#00cc00">Up</FONT>';
+ }
+
+ statusCell.innerHTML = '<B>' + status + '</B>';
+ packetlossCell.innerHTML = '<B>' + Math.round(loss) + '%</B>';
+ if ( avg > 0 ) {
+ latencyCell.innerHTML = '<B>' + Math.round( avg*1000 ) + 'ms</B>';
+ }
+ var packets = fails + pongs;
+ packetsCell.innerHTML = '<B>' + packets + '</B>';
+
+ setTimeout( "ping('<%$ip%>', ping_update)", 1000 );
+
+ }
+
+ ping( '<%$ip%>', ping_update );
+
+</SCRIPT>
+
+<%init>
+
+my($query) = $cgi->keywords;
+$query =~ /^([\d\.]+)$/ or die 'Illegal IP';
+my $ip = $1;
+
+</%init>
diff --git a/httemplate/misc/process/link.cgi b/httemplate/misc/process/link.cgi
index df15dca..77546f3 100755
--- a/httemplate/misc/process/link.cgi
+++ b/httemplate/misc/process/link.cgi
@@ -1,14 +1,20 @@
%unless ($error) {
% #no errors, so let's view this customer.
% my $custnum = $new->cust_pkg->custnum;
-<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum#cust_pkg$pkgnum" ) %>
+% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+% ? ''
+% : ';show=packages';
+% my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag" ) %>
%} else {
% errorpage($error);
%}
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('View/link unlinked services');
+ unless $curuser->access_right('View/link unlinked services');
my $DEBUG = 0;
diff --git a/httemplate/misc/process/part_device-import.html b/httemplate/misc/process/part_device-import.html
new file mode 100644
index 0000000..eac111a
--- /dev/null
+++ b/httemplate/misc/process/part_device-import.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server = new FS::UI::Web::JSRPC 'FS::part_device::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/payment.cgi b/httemplate/misc/process/payment.cgi
index 2baca1e..1e9501d 100644
--- a/httemplate/misc/process/payment.cgi
+++ b/httemplate/misc/process/payment.cgi
@@ -32,6 +32,11 @@ $cgi->param('amount') =~ /^\s*(\d*(\.\d\d)?)\s*$/
my $amount = $1;
errorpage("amount <= 0") unless $amount > 0;
+if ( $cgi->param('fee') =~ /^\s*(\d*(\.\d\d)?)\s*$/ ) {
+ my $fee = $1;
+ $amount = sprintf('%.2f', $amount + $fee);
+}
+
$cgi->param('year') =~ /^(\d+)$/
or errorpage("illegal year ". $cgi->param('year'));
my $year = $1;
@@ -44,7 +49,7 @@ $cgi->param('payby') =~ /^(CARD|CHEK)$/
or errorpage("illegal payby ". $cgi->param('payby'));
my $payby = $1;
my %payby2fields = (
- 'CARD' => [ qw( address1 address2 city state zip ) ],
+ 'CARD' => [ qw( address1 address2 city county state zip country ) ],
'CHEK' => [ qw( ss paytype paystate stateid stateid_state ) ],
);
my %type = ( 'CARD' => 'credit card',
@@ -143,6 +148,22 @@ if ( $cgi->param('batch') ) {
);
errorpage($error) if $error;
+ #no error, so order the fee package if applicable...
+ if ( $cgi->param('fee_pkgpart') =~ /^(\d+)$/ ) {
+
+ my $cust_pkg = new FS::cust_pkg { 'pkgpart' => $1 };
+
+ my $error = $cust_main->order_pkg( 'cust_pkg' => $cust_pkg );
+ errorpage("payment processed successfully, but error ordering fee: $error")
+ if $error;
+
+ #and generate an invoice for it now too
+ $error = $cust_main->bill( 'pkg_list' => [ $cust_pkg ] );
+ errorpage("payment processed and fee ordered sucessfully, but error billing fee: $error")
+ if $error;
+
+ }
+
$cust_main->apply_payments;
}
diff --git a/httemplate/misc/process/rate_edit_excel.html b/httemplate/misc/process/rate_edit_excel.html
new file mode 100644
index 0000000..acd5f49
--- /dev/null
+++ b/httemplate/misc/process/rate_edit_excel.html
@@ -0,0 +1,10 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::rate_detail::process_edit_import', $cgi;
+
+</%init>
+
diff --git a/httemplate/misc/process/recharge_svc.html b/httemplate/misc/process/recharge_svc.html
index 147b953..5f68bf1 100755
--- a/httemplate/misc/process/recharge_svc.html
+++ b/httemplate/misc/process/recharge_svc.html
@@ -1,62 +1,13 @@
-%unless ($error) {
-%
-% my ($amount, $seconds, $up, $down, $total) = (0, 0, 0, 0, 0);
-% #should probably use payby.pm but whatever
-% if ($payby eq 'PREP') {
-% $error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down, \$total)
-% || $svc_acct->increment_seconds($seconds)
-% || $svc_acct->increment_upbytes($up)
-% || $svc_acct->increment_downbytes($down)
-% || $svc_acct->increment_totalbytes($total)
-% || $cust_main->insert_cust_pay_prepay( $amount, $prepaid );
-% } elsif ( $payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP)$/ ) {
-% my $part_pkg = $svc_acct->cust_svc->cust_pkg->part_pkg;
-% $amount = $part_pkg->option('recharge_amount', 1);
-% my %rhash = map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_) }
-% grep { $part_pkg->option($_, 1) }
-% qw ( recharge_seconds recharge_upbytes recharge_downbytes
-% recharge_totalbytes );
-%
-% my $description = "Recharge";
-% $description .= " $rhash{seconds}s" if $rhash{seconds};
-% $description .= " $rhash{upbytes} up" if $rhash{upbytes};
-% $description .= " $rhash{downbytes} down" if $rhash{downbytes};
-% $description .= " $rhash{totalbytes} total" if $rhash{totalbytes};
-%
-% $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label,
-% $description, $part_pkg->taxclass);
-%
-% if ($part_pkg->option('recharge_reset', 1)) {
-% $error ||= $svc_acct->set_usage(\%rhash);
-% }else{
-% $error ||= $svc_acct->recharge(\%rhash);
-% }
-%
-% my $old_balance = $cust_main->balance;
-% $error ||= $cust_main->bill;
-% $error ||= $cust_main->apply_payments_and_credits;
-% my $bill_error = $cust_main->collect('realtime' => 1) unless $error;
-% $error ||= "Failed to collect - $bill_error"
-% if $cust_main->balance > $old_balance && $cust_main->balance > 0
-% && $payby ne 'BILL';
-%
-% } else {
-% $error = "fatal error - unknown payby: $payby";
-% }
-%}
-%
%if ($error) {
% $cgi->param('error', $error);
-% $dbh->rollback if $oldAutoCommit;
-% print $cgi->redirect(popurl(2). "recharge_svc.html?". $cgi->query_string );
-%}
-%$dbh->commit or die $dbh->errstr if $oldAutoCommit;
-%
+<% $cgi->redirect(popurl(2). "recharge_svc.html?". $cgi->query_string ) %>
+%} else {
<% header("Package recharged") %>
<SCRIPT TYPE="text/javascript">
window.top.location.reload();
</SCRIPT>
</BODY></HTML>
+%}
<%init>
my $conf = new FS::Conf;
@@ -89,4 +40,52 @@ my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
+unless ($error) {
+
+ #should probably use payby.pm but whatever
+ if ($payby eq 'PREP') {
+ $error = $cust_main->recharge_prepay( $prepaid );
+ } elsif ( $payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP)$/ ) {
+ my $part_pkg = $svc_acct->cust_svc->cust_pkg->part_pkg;
+ my $amount = $part_pkg->option('recharge_amount', 1);
+ my %rhash = map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_) }
+ grep { $part_pkg->option($_, 1) }
+ qw ( recharge_seconds recharge_upbytes recharge_downbytes
+ recharge_totalbytes );
+
+ my $description = "Recharge";
+ $description .= " $rhash{seconds}s" if $rhash{seconds};
+ $description .= " $rhash{upbytes} up" if $rhash{upbytes};
+ $description .= " $rhash{downbytes} down" if $rhash{downbytes};
+ $description .= " $rhash{totalbytes} total" if $rhash{totalbytes};
+
+ $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label,
+ $description, $part_pkg->taxclass);
+
+ if ($part_pkg->option('recharge_reset', 1)) {
+ $error ||= $svc_acct->set_usage(\%rhash, 'null' => 1);
+ }else{
+ $error ||= $svc_acct->recharge(\%rhash);
+ }
+
+ my $old_balance = $cust_main->balance;
+ $error ||= $cust_main->bill;
+ $error ||= $cust_main->apply_payments_and_credits;
+ my $bill_error = $cust_main->collect('realtime' => 1) unless $error;
+ $error ||= "Failed to collect - $bill_error"
+ if $cust_main->balance > $old_balance && $cust_main->balance > 0
+ && $payby ne 'BILL';
+
+ } else {
+ $error = "fatal error - unknown payby: $payby";
+ }
+
+}
+
+if ($error) {
+ $dbh->rollback if $oldAutoCommit;
+} else {
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+}
+
</%init>
diff --git a/httemplate/misc/process/tax-fetch_and_import.cgi b/httemplate/misc/process/tax-fetch_and_import.cgi
new file mode 100644
index 0000000..553c755
--- /dev/null
+++ b/httemplate/misc/process/tax-fetch_and_import.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::tax_rate::process_download_and_update', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/tax-fetch_and_replace.cgi b/httemplate/misc/process/tax-fetch_and_replace.cgi
new file mode 100644
index 0000000..1a9b626
--- /dev/null
+++ b/httemplate/misc/process/tax-fetch_and_replace.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::tax_rate::process_download_and_reload', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/tax-import.cgi b/httemplate/misc/process/tax-import.cgi
index 016d4b6..f800dbd 100644
--- a/httemplate/misc/process/tax-import.cgi
+++ b/httemplate/misc/process/tax-import.cgi
@@ -2,7 +2,7 @@
<%init>
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
my $server = new FS::UI::Web::JSRPC 'FS::tax_rate::process_batch_import', $cgi;
diff --git a/httemplate/misc/rate_edit_excel.html b/httemplate/misc/rate_edit_excel.html
new file mode 100644
index 0000000..e73133c
--- /dev/null
+++ b/httemplate/misc/rate_edit_excel.html
@@ -0,0 +1,61 @@
+<% include('/elements/header.html', 'Edit rates with Excel' ) %>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'RateImportForm',
+ 'action' => 'process/rate_edit_excel.html',
+ 'num_files' => 1,
+ 'fields' => [ 'format' ],
+ 'message' => 'Rate edit successful',
+ 'url' => $p."browse/rate_region.html",
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <TR>
+ <TH ALIGN="left">1. Download current rates:</TH>
+ <TD>
+ <A HREF="<%$p%>/browse/rate_region.html?show_rates=1;_type=regions.xls">Download rate spreadsheet</A>
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="left" COLSPAN=2>2. Edit rates with Excel (or other .XLS-compatible application)</TH>
+ </TR>
+
+ <TR>
+ <TD ALIGN="left" COLSPAN=2>
+ &nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;To add rates, add four columns like an existing rate, with headers starting with "NEW: Rate Name" or "Rate Name".<BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;<FONT SIZE="-2"><I>For rate addition, protection can be turned off in Excel via the Tools-&gt;Protection-&gt;Unprotect Sheet menu command. Note that only new rates can be added; modified grayed out cells will not be imported.</I></FONT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => '3. Upload edited rate file: ',
+ 'label_align' => 'left',
+ )
+ %>
+
+ <INPUT TYPE="hidden" NAME="format" VALUE="default">
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Upload"
+ onClick = "document.RateImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+
+</TABLE>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/misc/send-invoice.cgi b/httemplate/misc/send-invoice.cgi
new file mode 100644
index 0000000..32dfe27
--- /dev/null
+++ b/httemplate/misc/send-invoice.cgi
@@ -0,0 +1,30 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%once>
+
+my %method = ( map { $_=>1 } qw( email print fax_invoice ) );
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $invnum = $cgi->param('invnum');
+my $template = $cgi->param('template');
+my $notice_name = $cgi->param('notice_name') if $cgi->param('notice_name');
+my $method = $cgi->param('method');
+
+$method .= '_invoice' if $method eq 'fax'; #!
+
+die "unknown method $method" unless $method{$method};
+
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+die "Can't find invoice!\n" unless $cust_bill;
+
+$cust_bill->$method({ 'template' => $template,
+ 'notice_name' => $notice_name,
+ });
+
+my $custnum = $cust_bill->getfield('custnum');
+
+</%init>
diff --git a/httemplate/misc/send-statement.cgi b/httemplate/misc/send-statement.cgi
new file mode 100755
index 0000000..e363fbd
--- /dev/null
+++ b/httemplate/misc/send-statement.cgi
@@ -0,0 +1,28 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%once>
+
+my %method = map { $_=>1 } qw( email print fax_invoice );
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $statementnum = $cgi->param('statementnum');
+my $template = $cgi->param('template') || 'statement'; #XXX configure... via event?? eh..
+my $notice_name = $cgi->param('notice_name') if $cgi->param('notice_name');
+my $method = $cgi->param('method');
+
+$method .= '_invoice' if $method eq 'fax'; #!
+
+die "unknown method $method" unless $method{$method};
+
+my $cust_statement = qsearchs('cust_statement',{'statementnum'=>$statementnum});
+die "Can't find statement!\n" unless $cust_statement;
+
+$cust_statement->$method({ 'template' => $template });
+
+my $custnum = $cust_statement->getfield('custnum');
+
+</%init>
diff --git a/httemplate/misc/states.cgi b/httemplate/misc/states.cgi
index cf2b46e..02b7be4 100644
--- a/httemplate/misc/states.cgi
+++ b/httemplate/misc/states.cgi
@@ -1,7 +1,7 @@
-%
-%
-% my $country = $cgi->param('arg');
-% my @output = states_hash($country);
-%
-%
[ <% join(', ', map { qq("$_") } @output) %> ]
+<%init>
+
+my $country = $cgi->param('arg');
+my @output = states_hash($country);
+
+</%init>
diff --git a/httemplate/misc/tax-fetch_and_import.cgi b/httemplate/misc/tax-fetch_and_import.cgi
new file mode 100644
index 0000000..33a6c9b
--- /dev/null
+++ b/httemplate/misc/tax-fetch_and_import.cgi
@@ -0,0 +1,48 @@
+<% include("/elements/header.html",'Tax Rate Download and Import') %>
+
+Import a tax data update.
+<BR><BR>
+
+<% include( '/elements/progress-init.html', 'TaxRateImport',[ 'format', ],
+ 'process/tax-fetch_and_import.cgi', { 'message' => 'Tax rates imported' },
+ )
+%>
+
+<FORM NAME="TaxRateImport" ACTION="javascript:void()" METHOD="POST">
+<% &ntable("#cccccc", 2) %>
+
+ <TR>
+ <TH ALIGN="right">Format</TH>
+ <TD>
+ <SELECT NAME="format">
+ <OPTION VALUE="cch">CCH import
+ </SELECT>
+ </TD>
+ </TR>
+ <TR>
+ <TH ALIGN="right">Update Password</TH>
+ <TD>
+ <INPUT TYPE="text" NAME="password">
+ </TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ VALUE = "Download and Import"
+ onClick = "document.TaxRateImport.submit.disabled=true; process();"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/tax-fetch_and_replace.cgi b/httemplate/misc/tax-fetch_and_replace.cgi
new file mode 100644
index 0000000..3290a3c
--- /dev/null
+++ b/httemplate/misc/tax-fetch_and_replace.cgi
@@ -0,0 +1,48 @@
+<% include("/elements/header.html",'Tax Rate Download and Import') %>
+
+Replace tax data.
+<BR><BR>
+
+<% include( '/elements/progress-init.html', 'TaxRateImport',[ 'format', ],
+ 'process/tax-fetch_and_replace.cgi', { 'message' => 'Tax rates replaced' },
+ )
+%>
+
+<FORM NAME="TaxRateImport" ACTION="javascript:void()" METHOD="POST">
+<% &ntable("#cccccc", 2) %>
+
+ <TR>
+ <TH ALIGN="right">Format</TH>
+ <TD>
+ <SELECT NAME="format">
+ <OPTION VALUE="cch">CCH import
+ </SELECT>
+ </TD>
+ </TR>
+ <TR>
+ <TH ALIGN="right">Update Password</TH>
+ <TD>
+ <INPUT TYPE="text" NAME="password">
+ </TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ VALUE = "Download and Import"
+ onClick = "document.TaxRateImport.submit.disabled=true; process();"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/tax-import.cgi b/httemplate/misc/tax-import.cgi
index a695e97..5116e54 100644
--- a/httemplate/misc/tax-import.cgi
+++ b/httemplate/misc/tax-import.cgi
@@ -6,7 +6,7 @@ Import a CSV file set containing tax rate records.
<% include( '/elements/form-file_upload.html',
'name' => 'TaxRateUpload',
'action' => 'process/tax-import.cgi',
- 'num_files' => 5,
+ 'num_files' => 6,
'fields' => [ 'format', ],
'message' => 'Tax rates imported',
)
@@ -27,13 +27,15 @@ Import a CSV file set containing tax rate records.
</TR>
<% include( '/elements/file-upload.html',
- 'field' => [ 'codefile',
+ 'field' => [ 'geofile',
+ 'codefile',
'plus4file',
'zipfile',
'txmatrix',
'detail',
],
- 'label' => [ 'code filename',
+ 'label' => [ 'geocode filename',
+ 'code filename',
'plus4 filename',
'zip filename',
'txmatrix filename',
diff --git a/httemplate/misc/xmlhttp-cust_main-address_standardize.html b/httemplate/misc/xmlhttp-cust_main-address_standardize.html
index 72fa4a4..3b9e142 100644
--- a/httemplate/misc/xmlhttp-cust_main-address_standardize.html
+++ b/httemplate/misc/xmlhttp-cust_main-address_standardize.html
@@ -50,6 +50,9 @@ if ( $sub eq 'address_standardize' ) {
unless ( $verifier->is_error ) {
+ my $zip = $hash->{Zip5};
+ $zip .= '-'. $hash->{Zip4} if $hash->{Zip4} =~ /\d/;
+
$return = {
%$return,
"new_$pre".'company' => $hash->{FirmName},
@@ -57,7 +60,7 @@ if ( $sub eq 'address_standardize' ) {
"new_$pre".'address2' => $hash->{Address1},
"new_$pre".'city' => $hash->{City},
"new_$pre".'state' => $hash->{State},
- "new_$pre".'zip' => $hash->{Zip5}. '-'. $hash->{Zip4},
+ "new_$pre".'zip' => $zip,
};
my @fields = (qw( company address1 address2 city state zip )); #hmm
diff --git a/httemplate/misc/xmlhttp-cust_main-censustract.html b/httemplate/misc/xmlhttp-cust_main-censustract.html
new file mode 100644
index 0000000..9d588d7
--- /dev/null
+++ b/httemplate/misc/xmlhttp-cust_main-censustract.html
@@ -0,0 +1,105 @@
+<% objToJson($return) %>
+<%init>
+
+my $DEBUG = 0;
+
+my $url='http://www.ffiec.gov/Geocode/default.aspx';
+
+my $sub = $cgi->param('sub');
+
+my $return = {};
+my $error = '';
+
+use LWP::UserAgent;
+use HTTP::Request;
+use HTTP::Request::Common qw( GET POST );
+use HTML::TokeParser;
+
+if ( $sub eq 'censustract' ) {
+
+ my %arg = $cgi->param('arg');
+ warn join('', map "$_: $arg{$_}\n", keys %arg )
+ if $DEBUG;
+
+ my $ua = new LWP::UserAgent;
+ my $res = $ua->request( GET( $url ) );
+
+ warn $res->as_string
+ if $DEBUG > 1;
+
+ unless ($res->code eq '200') {
+
+ $error = $res->message;
+
+ } else {
+
+ my $content = $res->content;
+ my $p = new HTML::TokeParser \$content;
+ my $viewstate;
+ while (my $token = $p->get_tag('input') ) {
+ next unless $token->[1]->{name} eq '__VIEWSTATE';
+ $viewstate = $token->[1]->{value};
+ last;
+ }
+
+ unless ($viewstate) {
+
+ $error = "no __VIEWSTATE found";
+
+ } else {
+
+ my($zip5, $zip4) = split('-',$arg{zip});
+
+ my @ffiec_args = (
+ __VIEWSTATE => $viewstate,
+ ddlbYear => $arg{year},
+ txtAddress => $arg{address},
+ txtCity => $arg{city},
+ ddlbState => $arg{state},
+ txtZipCode => $zip5,
+ btnSearch => 'Search',
+ );
+ warn join("\n", @ffiec_args )
+ if $DEBUG;
+
+ $res = $ua->request( POST( $url, \@ffiec_args ) );
+ warn $res->as_string
+ if $DEBUG > 1;
+
+ unless ($res->code eq '200') {
+
+ $error = $res->message;
+
+ } else {
+
+ my @id = qw( MSACode StateCode CountyCode TractCode );
+ $content = $res->content;
+ $p = new HTML::TokeParser \$content;
+ my $prefix = 'UcGeoResult11_lb';
+ my $compare =
+ sub { my $t=shift; scalar( grep { lc($t) eq lc("$prefix$_")} @id ) };
+
+ while (my $token = $p->get_tag('span') ) {
+ next unless ( $token->[1]->{id} && &$compare( $token->[1]->{id} ) );
+ $token->[1]->{id} =~ /^$prefix(\w+)$/;
+ $return->{lc($1)} = $p->get_trimmed_text("/span");
+ }
+
+ $error = "No census tract found" unless $return->{tractcode};
+ $return->{tractcode} .= ' '
+ unless $error || $JSON::VERSION >= 2; #broken JSON 1 workaround
+
+ } #unless ($res->code eq '200')
+
+ } #unless ($viewstate)
+
+ } #unless ($res->code eq '200')
+
+ $error = "FFIEC Geocoding error: $error" if $error;
+ $return->{'error'} = $error;
+
+ $return;
+
+}
+
+</%init>
diff --git a/httemplate/misc/xmlhttp-ping.html b/httemplate/misc/xmlhttp-ping.html
new file mode 100644
index 0000000..e993032
--- /dev/null
+++ b/httemplate/misc/xmlhttp-ping.html
@@ -0,0 +1,20 @@
+<% objToJson($return) %>
+<%init>
+
+my $conf = new FS::Conf;
+
+my $sub = $cgi->param('sub');
+
+die "$sub not supported" unless $sub eq 'ping';
+
+my $ip = $cgi->param('arg');
+
+my $ping = new Net::Ping('external', 5);
+$ping->hires(1);
+#my $a=time; warn "pinging\n";
+my ($ret, $duration, $ip2) = $ping->ping($ip);
+#warn "done pinging (". int(time-$a). "s)\n";
+
+my $return = [ $ret, $duration ];
+
+</%init>
diff --git a/httemplate/pref/pref-process.html b/httemplate/pref/pref-process.html
index 9661516..378164e 100644
--- a/httemplate/pref/pref-process.html
+++ b/httemplate/pref/pref-process.html
@@ -1,58 +1,67 @@
-% my $error = '';
-%
-% my $access_user;
-% if ( grep { $cgi->param($_) !~ /^\s*$/ }
-% qw(_password new_password new_password2)
-% ) {
-%
-% $access_user = qsearchs( 'access_user', {
-% 'username' => getotaker,
-% '_password' => $cgi->param('_password'),
-% } );
-%
-% $error = 'Current password incorrect; password not changed'
-% unless $access_user;
-%
-% $error ||= "New passwords don't match"
-% unless $cgi->param('new_password') eq $cgi->param('new_password2');
-%
-% $error ||= "No new password entered"
-% unless length($cgi->param('new_password'));
-%
-% $access_user->_password($cgi->param('new_password')) unless $error;
-%
-% } else {
-%
-% $access_user = $FS::CurrentUser::CurrentUser;
-%
-% }
-%
-% my %param = $access_user->options;
-%
-% #XXX autogen
-% my @paramlist = qw( menu_position
-% email_address
-% vonage-fromnumber vonage-username vonage-password
-% show_pkgnum show_db_profile save_db_profile
-% height width availHeight availWidth colorDepth
-% );
-%
-% foreach (@paramlist) {
-% scalar($cgi->param($_)) =~ /^[,.\-\@\w]*$/ && next;
-% $error ||= "Illegal value for parameter $_";
-% last;
-% }
-%
-% foreach (@paramlist) {
-% $param{$_} = scalar($cgi->param($_));
-% }
-%
-% $error ||= $access_user->replace( \%param );
-%
% if ( $error ) {
% $cgi->param('error', $error);
-% print $cgi->redirect(popurl(1). "pref.html?". $cgi->query_string );
+<% $cgi->redirect(popurl(1). "pref.html?". $cgi->query_string ) %>
% } else {
<% include('/elements/header.html', 'Preferences updated') %>
<% include('/elements/footer.html') %>
% }
+<%init>
+
+my $error = '';
+my $access_user = '';
+
+if ( grep { $cgi->param($_) !~ /^\s*$/ }
+ qw(_password new_password new_password2)
+ ) {
+
+ $access_user = qsearchs( 'access_user', {
+ 'username' => getotaker,
+ '_password' => $cgi->param('_password'),
+ } );
+
+ $error = 'Current password incorrect; password not changed'
+ unless $access_user;
+
+ $error ||= "New passwords don't match"
+ unless $cgi->param('new_password') eq $cgi->param('new_password2');
+
+ $error ||= "No new password entered"
+ unless length($cgi->param('new_password'));
+
+ $access_user->_password($cgi->param('new_password')) unless $error;
+
+} else {
+
+ $access_user = $FS::CurrentUser::CurrentUser;
+
+}
+
+#well, if you got your password change wrong, you don't get anything else
+#changed right now. but it should be sticky on the form
+unless ( $error ) { # if ($access_user) {
+
+ my %param = $access_user->options;
+
+ #XXX autogen
+ my @paramlist = qw( menu_position default_customer_view
+ email_address
+ vonage-fromnumber vonage-username vonage-password
+ show_pkgnum show_db_profile save_db_profile
+ height width availHeight availWidth colorDepth
+ );
+
+ foreach (@paramlist) {
+ scalar($cgi->param($_)) =~ /^[,.\-\@\w]*$/ && next;
+ $error ||= "Illegal value for parameter $_";
+ last;
+ }
+
+ foreach (@paramlist) {
+ $param{$_} = scalar($cgi->param($_));
+ }
+
+ $error ||= $access_user->replace( \%param );
+
+}
+
+</%init>
diff --git a/httemplate/pref/pref.html b/httemplate/pref/pref.html
index 57e22b3..562ef29 100644
--- a/httemplate/pref/pref.html
+++ b/httemplate/pref/pref.html
@@ -31,7 +31,7 @@ Interface
<% ntable("#cccccc",2) %>
<TR>
- <TH>Menu location: </TH>
+ <TH ALIGN="right">Menu location: </TH>
<TD>
<INPUT TYPE="radio" NAME="menu_position" VALUE="left" onClick="document.images['menu_example'].src='../images/menu-left-example.png';" <% $menu_position eq 'left' ? ' CHECKED' : ''%>> Left<BR>
<INPUT TYPE="radio" NAME="menu_position" VALUE="top"onClick="document.images['menu_example'].src='../images/menu-top-example.png';" <% $menu_position eq 'top' ? ' CHECKED' : ''%>> Top <BR>
@@ -39,6 +39,21 @@ Interface
<TD><IMG NAME="menu_example" SRC="../images/menu-<% $menu_position %>-example.png"></TD>
</TR>
+ <TR>
+ <TH ALIGN="right">Default customer view: </TD>
+ <TD COLSPAN=2>
+ <SELECT NAME="default_customer_view">
+% foreach my $view ( keys %customer_views ) {
+% my $selected =
+% $customer_views{$view} eq $curuser->option('default_customer_view')
+% ? 'SELECTED'
+% : '';
+ <OPTION VALUE="<%$customer_views{$view}%>" <%$selected%>><%$view%></OPTION>
+% }
+ </SELECT>
+ </TD>
+ </TR>
+
</TABLE>
<BR>
@@ -113,8 +128,21 @@ Vonage integration (see <a href="https://secure.click2callu.com/">Click2Call</a>
my $curuser = $FS::CurrentUser::CurrentUser;
+#false laziness w/view/cust_main.cgi and Conf.pm (cust_main-default_view)
+
+tie my %customer_views, 'Tie::IxHash',
+ 'Basics' => 'basics',
+ 'Notes' => 'notes', #notes and files?
+ 'Tickets' => 'tickets',
+ 'Packages' => 'packages',
+ 'Payment History' => 'payment_history',
+;
+$customer_views{'Change History'} = 'change_history'
+ if $curuser->access_right('View customer history');
+$customer_views{'Jumbo'} = 'jumbo';
+
# XSS via your own preferences? seems unlikely, but nice try anyway...
-( $curuser->option('menu_position') || 'left' )
+( $curuser->option('menu_position') || 'top' )
=~ /^(\w+)$/ or die "illegal menu_position";
my $menu_position = $1;
( $curuser->option('email_address') )
diff --git a/httemplate/search/477.html b/httemplate/search/477.html
new file mode 100755
index 0000000..9102c20
--- /dev/null
+++ b/httemplate/search/477.html
@@ -0,0 +1,155 @@
+<% include( 'elements/search.html',
+ 'title' => 'FCC Form 477 Results',
+ 'html_init' => $html_init,
+ 'name' => 'regions',
+ 'query' => [ @sql_query ],
+ 'count_query' => $count_query,
+ 'order_by' => 'ORDER BY censustract',
+ 'header' => [
+ 'County code',
+ 'Census tract code',
+ 'Upload rate',
+ 'Download rate',
+ 'Technology code',
+ 'Technology code other',
+ 'Quantity',
+ 'Percentage residential',
+ ],
+ 'fields' => [
+ sub { my $row = shift; substr($row->censustract, 2, 3) },
+ sub { my $row = shift; substr($row->censustract, 5) },
+ 'upload',
+ 'download',
+ sub { 7 },
+ sub { '' },
+ 'quantity',
+ sub { my $row = shift; sprintf "%.2f", $row->residential },
+ ],
+ 'links' => [
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ [ $link, $link_suffix ],
+ ],
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('List packages');
+
+my %search_hash = ();
+my @sql_query = ();
+
+for ( qw(agentnum magic classnum) ) {
+ $search_hash{$_} = $cgi->param($_) if $cgi->param($_);
+}
+
+my @column_option = $cgi->param('column_option')
+ if $cgi->param('column_option');
+
+my @row_option = $cgi->param('row_option')
+ if $cgi->param('row_option');
+
+my $where = join(' OR ', map { "num = $_" } grep { /^\d+$/ } @column_option );
+my %column_option_name = $where ?
+ ( map { $_->name => $_->num }
+ qsearch({ 'table' => 'part_pkg_report_option',
+ 'hashref' => {},
+ 'extra_sql' => "WHERE $where",
+ })
+ ) :
+ ( 'all packages' => '' );
+
+$where = join(' OR ', map { "num = $_" } grep { /^\d+$/ } @row_option );
+my %row_option_name = $where ?
+ ( map { $_->name => $_->num }
+ qsearch({ 'table' => 'part_pkg_report_option',
+ 'hashref' => {},
+ 'extra_sql' => "WHERE $where",
+ })
+ ) :
+ ( 'all packages' => '' );
+
+@row_option = map { $row_option_name{$_} } sort keys %row_option_name;
+@column_option = map { $column_option_name{$_} } sort keys %column_option_name;
+
+#$search_hash{row_option} = join(',', @row_option) if @row_option;
+my $html_init = '<H2>Summary</H2>'. include('/elements/table.html');
+ $html_init .= '<TR><TH></TH>';
+foreach my $column ( sort keys %column_option_name ) {
+ $html_init .= "<TH>$column</TH>";
+}
+ $html_init .= "</TR>";
+
+my $rowcount = 1;
+foreach my $row ( sort keys %row_option_name ) {
+
+ $html_init .= "<TR><TH>$row</TH>";
+
+ my $columncount = 2;
+ foreach my $column ( sort keys %column_option_name ) {
+ my @report_option = ();
+ push @report_option, $row_option_name{$row}
+ if $row_option_name{$row};
+ push @report_option, $column_option_name{$column}
+ if $column_option_name{$column};
+ my $report_option = join(',', @report_option) if @report_option;
+
+ my $sql_query = FS::cust_pkg->search_sql(
+ { %search_hash,
+ ($report_option ? ( 'report_option' => $report_option ) : () ),
+ }
+ );
+ my $extracolumns = "$rowcount AS upload, $columncount AS download";
+ my $percent = "100-100*cast(count(cust_main.company) as numeric)/cast(count(*) as numeric) AS residential";
+ $sql_query->{select} = "count(*) AS quantity, $extracolumns, censustract, $percent";
+ $sql_query->{extra_sql} =~ /^(.*)(ORDER BY pkgnum)(.*)$/s
+ or die "couldn't parse extra_sql";
+ $sql_query->{extra_sql} = "$1 GROUP BY censustract $3";
+
+ my $count_sql = delete($sql_query->{'count_query'});
+
+ my $count_sth = dbh->prepare($count_sql)
+ or die "Error preparing $count_sql: ". dbh->errstr;
+ $count_sth->execute
+ or die "Error executing $count_sql: ". $count_sth->errstr;
+ my $count_arrayref = $count_sth->fetchrow_arrayref;
+ my $count = $count_arrayref->[0];
+
+ $html_init .= "<TD>$count</TD>";
+ push @sql_query, $sql_query;
+ $columncount++;
+ }
+
+ $html_init .= "</TR>";
+ $rowcount++;
+}
+
+$html_init .= "</TABLE><BR><H2>Details</H2>";
+
+my $count_query = 'SELECT count(*) FROM ( ('.
+ join( ') UNION (',
+ map { my $extra = $_->{extra_sql}; my $addl = $_->{addl_from};
+ "SELECT censustract from cust_pkg $addl $extra";
+ }
+ @sql_query
+ ). ') ) AS foo';
+
+my $link = 'cust_pkg.cgi?'.
+ join(';', map{ "$_=". $search_hash{$_} } keys %search_hash). ';';
+my $link_suffix = sub { my $row = shift;
+ my $result = 'censustract='. $row->censustract. ';';
+ $result .= 'report_option='. @row_option[$row->upload - 1]
+ if @row_option[$row->upload - 1];
+ $result .= 'report_option='. @column_option[$row->download - 1]
+ if @column_option[$row->download - 1];
+ $result;
+ };
+</%init>
diff --git a/httemplate/search/cdr.html b/httemplate/search/cdr.html
index 852eeba..d1f68c5 100644
--- a/httemplate/search/cdr.html
+++ b/httemplate/search/cdr.html
@@ -10,7 +10,7 @@
'count_query' => $count_query,
'header' => [
'', # checkbox column
- fields('cdr'), #XXX fill in some nice names
+ @header,
],
'fields' => [
sub {
@@ -20,9 +20,10 @@
my $acctid = $cdr->acctid;
qq!<INPUT NAME="acctid$acctid" TYPE="checkbox" VALUE="1">!;
},
- fields('cdr'), #XXX fill in some pretty-print
+ @fields, #XXX fill in some pretty-print
#processing, etc.
],
+ 'links' => \@links,
'html_form' => qq!<FORM NAME="cdrForm" ACTION="$p/misc/cdr.cgi" METHOD="POST">!,
#false laziness w/queue.html
@@ -65,46 +66,87 @@ my $hashref = {};
my @search = ();
###
+# dates
+###
+
+my $str2time_sql = str2time_sql;
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "$str2time_sql calldate) >= $beginning ",
+ "$str2time_sql calldate) <= $ending";
+
+###
+# duration / billsec
+###
+
+push @search, FS::UI::Web::parse_lt_gt($cgi, 'duration');
+push @search, FS::UI::Web::parse_lt_gt($cgi, 'billsec');
+
+#above here things just push @search
+#below here things also have to define $hashref->{} or push @qsearch
+my @qsearch = @search;
+
+###
# freesidestatus
###
if ( $cgi->param('freesidestatus') eq 'NULL' ) {
- my $title = "Unprocessed $title";
+ $title = "Unprocessed $title";
$hashref->{'freesidestatus'} = ''; # Record.pm will take care of it
push @search, "( freesidestatus IS NULL OR freesidestatus = '' )";
} elsif ( $cgi->param('freesidestatus') =~ /^([\w ]+)$/ ) {
- my $title = "Processed $title";
+ $title = "Processed $title";
$hashref->{'freesidestatus'} = $1;
push @search, "freesidestatus = '$1'";
}
###
-# dates
+# termpartNstatus
###
-my $str2time_sql = str2time_sql;
+foreach my $param ( grep /^termpart\d+status$/, $cgi->param ) {
-my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
-push @search, "$str2time_sql calldate) >= $beginning ",
- "$str2time_sql calldate) <= $ending";
+ my $status = $cgi->param($param);
-###
-# duration / billsec
-###
+ $param =~ /^termpart(\d+)status$/ or die 'guru meditation 54something';
+ my $termpart = $1;
-push @search, FS::UI::Web::parse_lt_gt($cgi, 'duration');
-push @search, FS::UI::Web::parse_lt_gt($cgi, 'billsec');
+ my $search = '';
+ if ( $status eq 'NULL' ) {
+
+ #false lazienss w/cdr_termination.pm (i should be a part_termination method)
+ my $where_term =
+ "( cdr.acctid = cdr_termination.acctid AND termpart = $termpart ) ";
+ #my $join_term = "LEFT JOIN cdr_termination ON ( $where_term )";
+ $search =
+ "NOT EXISTS ( SELECT 1 FROM cdr_termination WHERE $where_term )";
+
+ } elsif ( $cgi->param('freesidestatus') =~ /^([\w ]+)$/ ) {
+
+ #false lazienss w/cdr_termination.pm (i should be a part_termination method)
+ my $where_term =
+ "( cdr.acctid = cdr_termination.acctid AND termpart = $termpart AND status = '$1' ) ";
+ #my $join_term = "LEFT JOIN cdr_termination ON ( $where_term )";
+ $search =
+ "EXISTS ( SELECT 1 FROM cdr_termination WHERE $where_term )";
+
+ }
+
+ if ( $search ) {
+ push @search, $search;
+ push @qsearch, $search;
+ }
+
+}
###
# src/dest/charged_party
###
-my @qsearch = @search;
-
if ( $cgi->param('src') =~ /^\s*([\d\-\+\ ]+)\s*$/ ) {
( my $src = $1 ) =~ s/\D//g;
$hashref->{'src'} = $src;
@@ -117,15 +159,23 @@ if ( $cgi->param('dst') =~ /^\s*([\d\-\+ ]+)\s*$/ ) {
push @search, "dst = '$dst'";
}
+if ( $cgi->param('dcontext') =~ /^\s*(.+)\s*$/ ) {
+ my $dcontext = $1;
+ $hashref->{'dcontext'} = $dcontext;
+ push @search, "dcontext = '$dcontext'";
+}
+
if ( $cgi->param('charged_party') =~ /^\s*([\d\-\+\ ]+)\s*$/ ) {
( my $charged_party = $1 ) =~ s/\D//g;
#$hashref->{'charged_party'} = $charged_party;
#push @search, "charged_party = '$charged_party'";
#XXX countrycode
- push @search, " ( charged_party = '$charged_party'
- OR charged_party = '1$charged_party' ) ";
- push @qsearch, " ( charged_party = '$charged_party'
- OR charged_party = '1$charged_party' ) ";
+
+ my $search = " ( charged_party = '$charged_party'
+ OR charged_party = '1$charged_party' ) ";
+
+ push @search, $search;
+ push @qsearch, $search;
}
###
@@ -144,6 +194,23 @@ if ( $cgi->param('cdrbatch') ne '__ALL__' ) {
}
###
+# acctid
+###
+
+if ( $cgi->param('acctid') =~ /\d/ ) {
+ my $acctid = $cgi->param('acctid');
+ $acctid =~ s/\r\n/\n/g; #browsers?
+ my @acctid = map { /^\s*(\d+)\s*$/ or die "guru meditation #4"; $1; }
+ grep { /^\s*(\d+)\s*$/ }
+ split(/\n/, $acctid);
+ if ( @acctid ) {
+ my $search = 'acctid IN ( '. join(',', @acctid). ' )';
+ push @qsearch, $search;
+ push @search, $search;
+ }
+}
+
+###
# finish it up
###
@@ -156,4 +223,53 @@ my $qsearch = join(' AND ', @qsearch);
$qsearch = ( scalar(keys %$hashref) ? ' AND ' : ' WHERE ' ) . $qsearch
if $qsearch;
+###
+# display fields
+###
+
+my %header = %{ FS::cdr->table_info->{'fields'} };
+
+my @first = qw( acctid calldate clid charged_party src dst dcontext );
+my %first = map { $_=>1 } @first;
+
+my @fields = ( @first, grep !$first{$_}, fields('cdr') );
+
+if ( $cgi->param('show') ) {
+ @fields = grep $cgi->param("show_$_"), @fields;
+}
+
+my @header = map {
+ if ( exists($header{$_}) ) {
+ $header{$_};
+ } else {
+ my $header = $_;
+ $header =~ s/\_/ /g; #//wtf
+ ucfirst($header);
+ }
+ } @fields;
+
+my $date_sub_factory = sub {
+ my $column = shift;
+ sub {
+ #my $cdr = shift;
+ my $date = shift->$column();
+ $date ? time2str( '%Y-%m-%d %T', $date ) : ''; #config time2str format?
+ };
+};
+
+my %fields = (
+ #any other formatters?
+ map { $_ => &{ $date_sub_factory }($_) } qw( startdate answerdate enddate )
+);
+
+my %links = (
+ 'svcnum' =>
+ sub { $_[0]->svcnum ? [ $p.'view/svc_phone.cgi?', 'svcnum' ] : ''; },
+);
+
+@fields = map { exists($fields{$_}) ? $fields{$_} : $_ } @fields;
+
+ #checkbox column
+my @links = ( '', map { exists($links{$_}) ? $links{$_} : '' } @fields );
+
</%init>
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index 89901ac..52f59de 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -8,7 +8,10 @@
'#',
'Description',
'Setup charge',
- 'Recurring charge',
+ ( $use_usage eq 'usage'
+ ? 'Usage charge'
+ : 'Recurring charge'
+ ),
'Invoice',
'Date',
FS::UI::Web::cust_header(),
@@ -16,13 +19,23 @@
'fields' => [
'billpkgnum',
sub { $_[0]->pkgnum > 0
- ? $_[0]->get('pkg')
- : $_[0]->get('itemdesc')
+ ? $_[0]->get('pkg') # possibly use override.pkg
+ : $_[0]->get('itemdesc') # but i think this correct
},
#strikethrough or "N/A ($amount)" or something these when
# they're not applicable to pkg_tax search
sub { sprintf($money_char.'%.2f', shift->setup ) },
- sub { sprintf($money_char.'%.2f', shift->recur ) },
+ sub { my $row = shift;
+ my $value = 0;
+ if ( $use_usage eq 'recurring' ) {
+ $value = $row->recur - $row->usage;
+ } elsif ( $use_usage eq 'usage' ) {
+ $value = $row->usage;
+ } else {
+ $value = $row->recur;
+ }
+ sprintf($money_char.'%.2f', $value );
+ },
'invnum',
sub { time2str('%b %d %Y', shift->_date ) },
\&FS::UI::Web::cust_fields,
@@ -83,32 +96,66 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
push @where, "cust_main.agentnum = $1";
}
+#classnum
+# not specified: all classes
+# 0: empty class
+# N: classnum
+my $use_override = $cgi->param('use_override');
if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
+ my $comparison = '';
if ( $1 == 0 ) {
- push @where, "classnum IS NULL";
+ $comparison = "IS NULL";
} else {
- push @where, "classnum = $1";
+ $comparison = "= $1";
+ }
+
+ if ( $use_override ) {
+ push @where, "(
+ part_pkg.classnum $comparison AND pkgpart_override IS NULL OR
+ override.classnum $comparison AND pkgpart_override IS NOT NULL
+ )";
+ } else {
+ push @where, "part_pkg.classnum $comparison";
}
}
-#sub _where {
-# my $table = shift;
-# my $prefix = @_ ? shift : '';
-# "
-# ( cust_main_county.county = $table.${prefix}.county
-# OR ( cust_main_county.county IS NULL AND $table.${prefix}.county = '' )
-# OR ( cust_main_county.county = '' AND $table.${prefix}.county IS NULL)
-# OR ( cust_main_county.county IS NULL AND $table.${prefix}.county IS NULL)
-# )
-# AND ( cust_main_county.state = $table.${prefix}.state
-# OR ( cust_main_county.state IS NULL AND $table.${prefix}.state = '' )
-# OR ( cust_main_county.state = '' AND $table.${prefix}.state IS NULL )
-# OR ( cust_main_county.state IS NULL AND $table.${prefix}.state IS NULL )
-# )
-# AND cust_main_county.country = $table.${prefix}.country
-# ";
-#
-#}
+if ( $cgi->param('taxclass')
+ && ! $cgi->param('istax') #no part_pkg.taxclass in this case
+ #(should we save a taxclass or a link to taxnum
+ # in cust_bill_pkg or something like
+ # cust_bill_pkg_tax_location?)
+ )
+{
+
+ #override taxclass when use_override is specified? probably
+ #if ( $use_override ) {
+ #
+ # push @where,
+ # ' ( '. join(' OR ',
+ # map {
+ # ' ( part_pkg.taxclass = '. dbh->quote($_).
+ # ' AND pkgpart_override IS NULL '.
+ # ' OR '.
+ # ' override.taxclass = '. dbh->quote($_).
+ # ' AND pkgpart_override IS NOT NULL '.
+ # ' ) '
+ # }
+ # $cgi->param('taxclass')
+ # ).
+ # ' ) ';
+ #
+ #} else {
+
+ push @where,
+ ' ( '. join(' OR ',
+ map ' part_pkg.taxclass = '.dbh->quote($_),
+ $cgi->param('taxclass')
+ ).
+ ' ) ';
+
+ #}
+
+}
if ( $cgi->param('out') ) {
@@ -143,17 +190,49 @@ if ( $cgi->param('out') ) {
}
-} elsif ( $cgi->param('country' ) ) {
+} elsif ( $cgi->param('country') ) {
- my %ph = map { $_ => dbh->quote( $cgi->param($_) ) }
- qw( county state country );
+ my @counties = $cgi->param('county');
+
+ if ( scalar(@counties) > 1 ) {
- my ( $loc_sql, @param ) = FS::cust_pkg->location_sql;
- while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
- $loc_sql =~ s/\?/$ph{shift(@param)}/e;
- }
+ #hacky, could be more efficient. care if it is ever used for more than the
+ # tax-report_groups filtering kludge
+
+ my $locs_sql =
+ ' ( '. join(' OR ', map {
+
+ my %ph = ( 'county' => dbh->quote($_),
+ map { $_ => dbh->quote( $cgi->param($_) ) }
+ qw( state country )
+ );
+
+ my ( $loc_sql, @param ) = FS::cust_pkg->location_sql;
+ while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
+ $loc_sql =~ s/\?/$ph{shift(@param)}/e;
+ }
+
+ $loc_sql;
- push @where, $loc_sql;
+ } @counties
+
+ ). ' ) ';
+
+ push @where, $locs_sql;
+
+ } else {
+
+ my %ph = map { $_ => dbh->quote( $cgi->param($_) ) }
+ qw( county state country );
+
+ my ( $loc_sql, @param ) = FS::cust_pkg->location_sql;
+ while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
+ $loc_sql =~ s/\?/$ph{shift(@param)}/e;
+ }
+
+ push @where, $loc_sql;
+
+ }
if ( $cgi->param('istax') ) {
if ( $cgi->param('taxname') ) {
@@ -168,13 +247,6 @@ if ( $cgi->param('out') ) {
#warn "neither nottax nor istax parameters specified";
}
- push @where, ' taxclass = '. dbh->quote( $cgi->param('taxclass') )
- if $cgi->param('taxclass')
- && ! $cgi->param('istax'); #no part_pkg.taxclass in this case
- #(should we save a taxclass or a link to taxnum
- # in cust_bill_pkg or something like
- # cust_bill_pkg_tax_location?)
-
if ( $cgi->param('taxclassNULL') ) {
my %hash = ( 'country' => scalar($cgi->param('country')) );
@@ -189,19 +261,72 @@ if ( $cgi->param('out') ) {
}
+} elsif ( scalar( grep( /locationtaxid/, $cgi->param ) ) ) {
+
+ # this should really be shoved out to FS::cust_pkg->location_sql or something
+ # along with the code in report_newtax.cgi
+
+ my %pn = (
+ 'county' => 'tax_rate_location.county',
+ 'state' => 'tax_rate_location.state',
+ 'city' => 'tax_rate_location.city',
+ 'locationtaxid' => 'cust_bill_pkg_tax_rate_location.locationtaxid',
+ );
+
+ my %ph = map { ( $pn{$_} => dbh->quote( $cgi->param($_) || '' ) ) }
+ qw( county state city locationtaxid );
+
+ push @where,
+ join( ' AND ', map { "( $_ = $ph{$_} OR $ph{$_} = '' AND $_ IS NULL)" }
+ keys %ph
+ );
+
}
-if ($cgi->param('itemdesc')) {
- if ($cgi->param('itemdesc') eq 'Tax') {
+if ( $cgi->param('itemdesc') ) {
+ if ( $cgi->param('itemdesc') eq 'Tax' ) {
push @where, "(itemdesc='Tax' OR itemdesc is null)";
- }else{
+ } else {
push @where, 'itemdesc='. dbh->quote($cgi->param('itemdesc'));
}
}
+
+if ( $cgi->param('report_group') =~ /^(=|!=) (.*)$/ && $cgi->param('istax') ) {
+ my ( $group_op, $group_value ) = ( $1, $2 );
+ if ( $group_op eq '=' ) {
+ #push @where, 'itemdesc LIKE '. dbh->quote($group_value.'%');
+ push @where, 'itemdesc = '. dbh->quote($group_value);
+ } elsif ( $group_op eq '!=' ) {
+ push @where, '( itemdesc != '. dbh->quote($group_value) .' OR itemdesc IS NULL )';
+ } else {
+ die "guru meditation #00de: group_op $group_op\n";
+ }
+
+}
+
push @where, 'cust_bill_pkg.pkgnum != 0' if $cgi->param('nottax');
push @where, 'cust_bill_pkg.pkgnum = 0' if $cgi->param('istax');
-push @where, " tax = 'Y' " if $cgi->param('cust_tax');
+if ( $cgi->param('cust_tax') ) {
+ #false laziness -ish w/report_tax.cgi
+ my $cust_exempt;
+ if ( $cgi->param('taxname') ) {
+ my $q_taxname = dbh->quote($cgi->param('taxname'));
+ $cust_exempt =
+ "( tax = 'Y'
+ OR EXISTS ( SELECT 1 FROM cust_main_exemption
+ WHERE cust_main_exemption.custnum = cust_main.custnum
+ AND cust_main_exemption.taxname = $q_taxname )
+ )
+ ";
+ } else {
+ $cust_exempt = " tax = 'Y' ";
+ }
+
+ push @where, $cust_exempt;
+}
+
+my $use_usage = $cgi->param('use_usage');
my $count_query;
if ( $cgi->param('pkg_tax') ) {
@@ -267,8 +392,15 @@ if ( $cgi->param('pkg_tax') ) {
} else {
- $count_query =
- "SELECT COUNT(*), SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)";
+ $count_query = "SELECT COUNT(*), ";
+
+ if ( $use_usage eq 'recurring' ) {
+ $count_query .= "SUM(setup + recur - usage)";
+ } elsif ( $use_usage eq 'usage' ) {
+ $count_query .= "SUM(usage)";
+ } else {
+ $count_query .= "SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)";
+ }
}
@@ -282,7 +414,9 @@ my $join_pkg;
if ( $cgi->param('nottax') ) {
$join_pkg = ' LEFT JOIN cust_pkg USING ( pkgnum )
- LEFT JOIN part_pkg USING ( pkgpart ) ';
+ LEFT JOIN part_pkg USING ( pkgpart )
+ LEFT JOIN part_pkg AS override
+ ON pkgpart_override = override.pkgpart ';
$join_pkg .= ' LEFT JOIN cust_location USING ( locationnum ) '
if $conf->exists('tax-pkg_address');
@@ -295,6 +429,10 @@ if ( $cgi->param('nottax') ) {
#quelle kludge, false laziness w/report_tax.cgi
$where =~ s/cust_pkg\.locationnum/cust_bill_pkg_tax_location.locationnum/g;
+ } elsif ( scalar( grep( /locationtaxid/, $cgi->param ) ) ) {
+ $join_pkg .=
+ ' LEFT JOIN cust_bill_pkg_tax_rate_location USING ( billpkgnum ) '.
+ ' LEFT JOIN tax_rate_location USING ( taxratelocationnum ) ';
}
} else {
@@ -307,7 +445,17 @@ if ( $cgi->param('nottax') ) {
}
-$count_query .= " FROM cust_bill_pkg $join_cust $join_pkg $where";
+if ($use_usage) {
+ $count_query .=
+ " FROM (SELECT cust_bill_pkg.setup, cust_bill_pkg.recur,
+ ( SELECT COALESCE( SUM(amount), 0 ) FROM cust_bill_pkg_detail
+ WHERE cust_bill_pkg.billpkgnum = cust_bill_pkg_detail.billpkgnum
+ ) AS usage FROM cust_bill_pkg $join_cust $join_pkg $where
+ ) AS countquery";
+} else {
+ $count_query .= " FROM cust_bill_pkg $join_cust $join_pkg $where";
+}
+warn "count_query is $count_query\n";
my @select = (
'cust_bill_pkg.*',
diff --git a/httemplate/search/cust_event.html b/httemplate/search/cust_event.html
index d55b5c6..f8cf6b2 100644
--- a/httemplate/search/cust_event.html
+++ b/httemplate/search/cust_event.html
@@ -75,29 +75,34 @@ my $status_sub = sub {
my $part_event = $cust_event->part_event;
- if ( $part_event->eventtable eq 'cust_bill' && $part_event->templatename ) {
- my $alt_templatename = $part_event->templatename;
- my $alt_link = "$alt_templatename-". $cust_event->tablenum;
+ if ( $part_event->eventtable eq 'cust_bill'
+ && ( $part_event->templatename || $part_event->option('notice_name') )
+ )
+ {
+ my $link = 'invnum='. $cust_event->tablenum;
+ $link .= ';template='. uri_escape($part_event->templatename)
+ if $part_event->templatename;
+ $link .= ';notice_name='. uri_escape($part_event->option('notice_name'))
+ if $part_event->option('notice_name');
my $conf = new FS::Conf;
my $cust_bill = $cust_event->cust_X;
$status .= qq{
- ( <A HREF="${p}view/cust_bill.cgi?$alt_link">view</A>
- | <A HREF="${p}view/cust_bill-pdf.cgi?$alt_link.pdf">view
- typeset</A>
- | <A HREF="${p}misc/print-invoice.cgi?$alt_link">re-print</A>
+ ( <A HREF="${p}view/cust_bill.cgi?$link">view</A>
+ | <A HREF="${p}view/cust_bill-pdf.cgi?$link">view&nbsp;typeset</A>
+ | <A HREF="${p}misc/send-invoice.cgi?method=print;$link">re-print</A>
};
if ( grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ) {
$status .= qq{
- | <A HREF="${p}misc/email-invoice.cgi?$alt_link">re-email</A>
+ | <A HREF="${p}misc/send-invoice.cgi?method=email;$link">re-email</A>
};
}
if ( $conf->exists('hylafax') && length($cust_bill->cust_main->fax) ) {
$status .= qq{
- | <A HREF="${p}misc/fax-invoice.cgi?$alt_link">re-fax</A>
+ | <A HREF="${p}misc/send-invoice.cgi?method=fax;$link">re-fax</A>
}
}
@@ -124,7 +129,12 @@ my $trigger_link = sub {
my $eventtable = $cust_event->eventtable;
if ( $eventtable eq 'cust_pkg' ) {
my $custnum = $cust_event->cust_main_custnum;
- [ "${p}view/cust_main.cgi?$custnum#cust_pkg", 'tablenum' ];
+ my $show = $FS::CurrentUser::CurrentUser->default_customer_view =~ /^(jumbo|packages)$/
+ ? ''
+ : ';show=packages';
+ my $pkgnum = $cust_event->tablenum;
+ my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment
+ [ "${p}view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#cust_pkg", 'tablenum' ];
} else {
[ "${p}view/$eventtable.cgi?", 'tablenum' ];
}
@@ -142,61 +152,24 @@ die "access denied"
|| $cgi->param('invnum') =~ /^(\d+)$/
|| $cgi->param('pkgnum') =~ /^(\d+)$/
);
-
-my $title = $cgi->param('failed')
- ? 'Failed billing events'
- : 'Billing events';
+my $title = $cgi->param('failed') ? 'Failed billing events' : 'Billing events';
-my @search = ();
+my %search = ();
-if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
- push @search, "cust_main.agentnum = $1";
- #my $agent = qsearchs('agent', { 'agentnum' => $1 } );
- #die "unknown agentnum $1" unless $agent;
+my @scalars = qw ( agentnum custnum invnum pkgnum failed );
+for my $param ( @scalars ) {
+ $search{$param} = scalar( $cgi->param($param) )
+ if $cgi->param($param);
}
my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
-push @search, "cust_event._date >= $beginning",
- "cust_event._date <= $ending";
+$search{'beginning'} = $beginning;
+$search{'ending'} = $ending;
-if ( $cgi->param('failed') ) {
- push @search, "statustext != ''",
- "statustext IS NOT NULL",
- "statustext != 'N/A'";
-}
-
-#if ( $cgi->param('part_event.payby') =~ /^(\w+)$/ ) {
-# push @search, "part_event.payby = '$1'";
-#}
-
-if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
- push @search, "cust_main.custnum = '$1'";
-}
-if ( $cgi->param('invnum') =~ /^(\d+)$/ ) {
- push @search, "part_event.eventtable = 'cust_bill'",
- "tablenum = '$1'";
-}
-if ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
- push @search, "part_event.eventtable = 'cust_pkg'",
- "tablenum = '$1'";
-}
-
-#here is the agent virtualization
-push @search, $curuser->agentnums_sql( 'table' => 'cust_main' );
-
-my $where = 'WHERE '. join(' AND ', @search );
+my $where = ' WHERE '. FS::cust_event->search_sql( \%search );
-my $join = "
- JOIN part_event USING ( eventpart )
- LEFT JOIN cust_bill ON ( eventtable = 'cust_bill' AND tablenum = invnum )
- LEFT JOIN cust_pkg ON ( eventtable = 'cust_pkg' AND tablenum = pkgnum )
- LEFT JOIN cust_main ON ( ( eventtable = 'cust_main' AND tablenum = cust_main.custnum )
- OR ( eventtable = 'cust_bill' AND cust_bill.custnum = cust_main.custnum )
- OR ( eventtable = 'cust_pkg' AND cust_pkg.custnum = cust_main.custnum )
- )
-";
- #'LEFT JOIN cust_main USING ( custnum ) ';
+my $join = FS::cust_event->join_sql();
my $sql_query = {
'table' => 'cust_event',
@@ -217,22 +190,24 @@ my $count_sql = "SELECT COUNT(*) FROM cust_event $join $where";
my $conf = new FS::Conf;
-my $failed = $cgi->param('failed');
+my @params = ( @scalars, qw( beginning ending ) );
my $html_init = join("\n", map {
( my $action = $_ ) =~ s/_$//;
include('/elements/progress-init.html',
$_.'form',
- [ 'action', 'beginning', 'ending', 'failed' ],
+ [ 'action', @params ],
"../misc/${_}events.cgi",
{ 'message' => "Invoices re-${action}ed" }, #would be nice to show the number of them, but...
$_, #key
),
qq!<FORM NAME="${_}form">!,
qq!<INPUT TYPE="hidden" NAME="action" VALUE="$_">!, #not used though
- qq!<INPUT TYPE="hidden" NAME="beginning" VALUE="$beginning">!,
- qq!<INPUT TYPE="hidden" NAME="ending" VALUE="$ending">!,
- qq!<INPUT TYPE="hidden" NAME="failed" VALUE="$failed">!,
+ ( map { my $value = encode_entities( $search{$_} );
+ qq(<INPUT TYPE="hidden" NAME="$_" VALUE="$value">);
+ }
+ @params #keys %search
+ ),
qq!</FORM>!
} qw( print_ email_ fax_ ) ).
diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi
index 36e4374..e65dc71 100755
--- a/httemplate/search/cust_main.cgi
+++ b/httemplate/search/cust_main.cgi
@@ -1,5 +1,7 @@
+%my $curuser = $FS::CurrentUser::CurrentUser;
+%
%die "access denied"
-% unless $FS::CurrentUser::CurrentUser->access_right('List customers');
+% unless $curuser->access_right('List customers');
%
%my $conf = new FS::Conf;
%my $maxrecords = $conf->config('maxsearchrecordsperpage');
@@ -483,14 +485,17 @@
%# my $part_pkg = qsearchs( 'part_pkg', { pkgpart => $_->pkgpart } );
% my $part_pkg = $_->part_pkg;
%
-% my $pkg = $part_pkg->pkg;
-% my $comment = $part_pkg->comment;
-% my $pkgview = "${p}view/cust_main.cgi?$custnum#cust_pkg$pkgnum";
+% my $pkg_comment = $part_pkg->pkg_comment(nopkgpart => 1);
+% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+% ? ''
+% : ';show=packages';
+% my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment
+% my $pkgview = "${p}view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag";
% my @cust_svc = @{shift @lol_cust_svc};
% #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
% my $rowspan = scalar(@cust_svc) || 1;
%
-% print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!;
+% print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg_comment</FONT></A></TD>!;
%
% my($n2)='';
% foreach my $cust_svc ( @cust_svc ) {
diff --git a/httemplate/search/cust_main.html b/httemplate/search/cust_main.html
index 3282f0f..f098fd3 100755
--- a/httemplate/search/cust_main.html
+++ b/httemplate/search/cust_main.html
@@ -43,9 +43,12 @@ my %search_hash = ();
#$search_hash{'query'} = $cgi->keywords;
#scalars
-for my $param (qw(
+my @scalars = qw (
agentnum status cancelled_pkgs cust_fields flattened_pkgs custbatch
-)) {
+ no_censustract
+);
+
+for my $param ( @scalars ) {
$search_hash{$param} = scalar( $cgi->param($param) )
if $cgi->param($param);
}
@@ -97,7 +100,7 @@ my $menubar = [];
if ( $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices') ) {
- my $uri = new URI::URL;
+ my $uri = new URI;
$uri->query_form( \%search_hash );
my $query = $uri->query;
diff --git a/httemplate/search/cust_pay_batch.cgi b/httemplate/search/cust_pay_batch.cgi
index 1576963..2056876 100755
--- a/httemplate/search/cust_pay_batch.cgi
+++ b/httemplate/search/cust_pay_batch.cgi
@@ -132,6 +132,9 @@ if ( $pay_batch ) {
|| ( $pay_batch->status eq 'I'
&& $FS::CurrentUser::CurrentUser->access_right('Reprocess batches')
)
+ || ( $pay_batch->status eq 'R'
+ && $FS::CurrentUser::CurrentUser->access_right('Redownload resolved batches')
+ )
) {
$html_init .= qq!<FORM ACTION="$p/misc/download-batch.cgi" METHOD="POST">!;
if ( $fixed ) {
@@ -144,6 +147,7 @@ if ( $pay_batch ) {
qq!<OPTION VALUE="PAP">80 byte file for TD Canada Trust PAP Batch</OPTION>!.
qq!<OPTION VALUE="BoM">Bank of Montreal ECA batch</OPTION>!.
qq!<OPTION VALUE="ach-spiritone">Spiritone ACH batch</OPTION>!.
+ qq!<OPTION VALUE="paymentech">Chase Paymentech</OPTION>!.
qq!</SELECT>!;
}
$html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum"><INPUT TYPE="submit" VALUE="Download"></FORM><BR>!;
@@ -168,6 +172,7 @@ if ( $pay_batch ) {
qq!<OPTION VALUE="PAP">264 byte results for TD Canada Trust PAP Batch</OPTION>!.
qq!<OPTION VALUE="BoM">Bank of Montreal ECA results</OPTION>!.
qq!<OPTION VALUE="ach-spiritone">Spiritone ACH batch</OPTION>!.
+ qq!<OPTION VALUE="paymentech">Chase Paymentech</OPTION>!.
qq!</SELECT><BR>!;
}
$html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum">!;
diff --git a/httemplate/search/cust_pay_void.html b/httemplate/search/cust_pay_void.html
new file mode 100755
index 0000000..431bb2c
--- /dev/null
+++ b/httemplate/search/cust_pay_void.html
@@ -0,0 +1,13 @@
+<% include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay_void',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'voided payment',
+ 'name_verb' => 'voided', # 'paid',
+ 'disable_by' => 1, #showing original not voiding otaker
+ 'addl_header' => [ 'Void Date', ], # 'Void Reason' ],
+ 'addl_fields' => [
+ sub { time2str('%b %d %Y', shift->void_date ) },
+ #'reason',
+ ],
+ )
+%>
diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi
index bd4a946..f03bbc2 100755
--- a/httemplate/search/cust_pkg.cgi
+++ b/httemplate/search/cust_pkg.cgi
@@ -10,6 +10,8 @@
'Package',
'Class',
'Status',
+ 'Setup',
+ 'Base Recur',
'Freq.',
'Setup',
'Last bill',
@@ -33,6 +35,15 @@
},
'classname',
sub { ucfirst(shift->status); },
+ sub { sprintf( $money_char.'%.2f',
+ shift->part_pkg->option('setup_fee'),
+ );
+ },
+ sub { my $c = shift;
+ sprintf( $money_char.'%.2f',
+ $c->part_pkg->base_recur($c)
+ );
+ },
sub { #shift->part_pkg->freq_pretty;
#my $part_pkg = $part_pkg{shift->pkgpart};
@@ -99,13 +110,15 @@
'',
'',
'',
+ '',
+ '',
FS::UI::Web::cust_colors(),
'',
],
- 'style' => [ '', '', '', '', 'b', '', '', '', '', '', '', '', '', '',
+ 'style' => [ '', '', '', '', 'b', '', '', '', '', '', '', '', '', '', '', '',
FS::UI::Web::cust_styles() ],
'size' => [ '', '', '', '', '-1' ],
- 'align' => 'rrlcclrrrrrrrl'. FS::UI::Web::cust_aligns(). 'r',
+ 'align' => 'rrlccrrlrrrrrrrl'. FS::UI::Web::cust_aligns(). 'r',
'links' => [
$link,
$link,
@@ -121,6 +134,8 @@
'',
'',
'',
+ '',
+ '',
( map { $_ ne 'Cust. Status' ? $clink : '' }
FS::UI::Web::cust_header(
$cgi->param('cust_fields')
@@ -133,19 +148,36 @@
%>
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('List packages');
+ unless $curuser->access_right('List packages');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
# my %part_pkg = map { $_->pkgpart => $_ } qsearch('part_pkg', {});
- my %search_hash = ();
+my %search_hash = ();
+
+#some false laziness w/misc/bulk_change_pkg.cgi
- $search_hash{'query'} = $cgi->keywords;
+$search_hash{'query'} = $cgi->keywords;
- for my $param (qw(agentnum magic status classnum pkgpart)) {
- $search_hash{$param} = $cgi->param($param)
- if $cgi->param($param);
- }
+for (qw( agentnum magic status classnum custom )) {
+ $search_hash{$_} = $cgi->param($_) if $cgi->param($_);
+}
+
+$search_hash{'pkgpart'} = [ $cgi->param('pkgpart') ];
+
+for my $param ( qw(censustract) ) {
+ $search_hash{$param} = $cgi->param($param) || ''
+ if ( grep { /$param/ } $cgi->param );
+}
+
+my @report_option = $cgi->param('report_option')
+ if $cgi->param('report_option');
+$search_hash{report_option} = join(',', @report_option) if @report_option;
###
# parse dates
@@ -175,8 +207,17 @@ foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
my $sql_query = FS::cust_pkg->search_sql(\%search_hash);
my $count_query = delete($sql_query->{'count_query'});
+my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
+ ? ''
+ : ';show=packages';
+
my $link = sub {
- [ "${p}view/cust_main.cgi?".shift->custnum.'#cust_pkg', 'pkgnum' ];
+ my $self = shift;
+ my $frag = 'cust_pkg'. $self->pkgnum; #hack for IE ignoring real #fragment
+ [ "${p}view/cust_main.cgi?custnum=".$self->custnum.
+ "$show;fragment=$frag#cust_pkg",
+ 'pkgnum'
+ ];
};
my $clink = sub {
diff --git a/httemplate/search/cust_tax_adjustment.html b/httemplate/search/cust_tax_adjustment.html
new file mode 100644
index 0000000..9254765
--- /dev/null
+++ b/httemplate/search/cust_tax_adjustment.html
@@ -0,0 +1,54 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name_singular' => 'tax adjustment',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'header' => [ 'Tax', 'Amount', 'Comment', 'Invoice' ],
+ 'fields' => [ 'taxname',
+ sub { $money_char. shift->amount },
+ 'comment',
+ sub { my $l = shift->cust_bill_pkg;
+ $l ? '#'.$l->invnum : '';
+ },
+ ],
+ 'links' => [ '', '', '', $ilink ],
+ )
+%>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Add customer tax adjustment');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $count_query = 'SELECT COUNT(*) FROM cust_tax_adjustment';
+
+my $hashref = {};
+
+my $custnum = '';
+my $cust_main = '';
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $custnum = $1;
+ $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+ $hashref->{'custnum'} = $custnum;
+ $count_query .= " WHERE custnum = $custnum ";
+}
+
+my $title = 'Tax adjustments';
+$title .= ' for '. $cust_main->name if $cust_main;
+
+my $query = { 'table' => 'cust_tax_adjustment',
+ 'hashref' => $hashref,
+ };
+
+my $ilink = [ $p.'view/cust_bill.cgi?', sub { my $l = shift->cust_bill_pkg;
+ $l ? $l->invnum : 'EXCEPTION';
+ }
+ ];
+
+#XXX would be nice to list customer fields on the report too, if we ever need
+# to link to here without a custnum (i'm sure we will, eventually...)
+
+</%init>
diff --git a/httemplate/search/elements/cust_main_dayranges.html b/httemplate/search/elements/cust_main_dayranges.html
new file mode 100644
index 0000000..cc01492
--- /dev/null
+++ b/httemplate/search/elements/cust_main_dayranges.html
@@ -0,0 +1,219 @@
+<%doc>
+
+Example:
+
+ include( 'elements/cust_main_dayranges.html',
+ 'title' => 'Accounts Receivable Aging Summary',
+ 'range_sub' => $mysub,
+ )
+
+ my $mysub = sub {
+ my( $start, $end ) = @_;
+
+ "SQL EXPRESSION BASED ON $start AND $end";
+ };
+
+</%doc>
+<% include( 'search.html',
+ 'name' => 'customers',
+ 'query' => $sql_query,
+ 'count_query' => $count_sql,
+ 'header' => [
+ FS::UI::Web::cust_header(),
+ '0-30',
+ '30-60',
+ '60-90',
+ '90+',
+ 'Total',
+ ],
+ 'footer' => [
+ 'Total',
+ ( map '',
+ ( 1 ..
+ scalar(FS::UI::Web::cust_header()-1)
+ )
+ ),
+ sprintf( $money_char.'%.2f',
+ $row->{'rangecol_0_30'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'rangecol_30_60'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'rangecol_60_90'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'rangecol_90_0'} ),
+ sprintf( '<b>'. $money_char.'%.2f'. '</b>',
+ $row->{'rangecol_0_0'} ),
+ ],
+ 'fields' => [
+ \&FS::UI::Web::cust_fields,
+ format_rangecol('0_30'),
+ format_rangecol('30_60'),
+ format_rangecol('60_90'),
+ format_rangecol('90_0'),
+ format_rangecol('0_0'),
+ ],
+ 'links' => [
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ '',
+ '',
+ '',
+ '',
+ '',
+ ],
+ #'align' => 'rlccrrrrr',
+ 'align' => FS::UI::Web::cust_aligns(). 'rrrrr',
+ #'size' => [ '', '', '-1', '-1', '', '', '', '', '', ],
+ #'style' => [ '', '', 'b', 'b', '', '', '', '', 'b', ],
+ 'size' => [ ( map '', FS::UI::Web::cust_header() ),
+ #'-1', '', '', '', '', '', ],
+ '', '', '', '', '', ],
+ 'style' => [ FS::UI::Web::cust_styles(),
+ #'b', '', '', '', '', 'b', ],
+ '', '', '', '', 'b', ],
+ 'color' => [
+ FS::UI::Web::cust_colors(),
+ '',
+ '',
+ '',
+ '',
+ '',
+ ],
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+
+#actually need to auto-generate other things too for a passed-in ranges to work
+my $ranges = $opt{'ranges'} ? delete($opt{'ranges'}) : [
+ [ 0, 30 ],
+ [ 30, 60 ],
+ [ 60, 90 ],
+ [ 90, 0 ],
+ [ 0, 0 ],
+];
+
+my $range_sub = delete($opt{'range_sub'}); #or die
+
+#my $range_cols = join(',', map &{$range_sub}( @$_ ), @ranges );
+my $range_cols = join(',', map call_range_sub($range_sub, @$_ ), @$ranges );
+
+my $select_count_pkgs = FS::cust_main->select_count_pkgs_sql;
+
+my $active_sql = FS::cust_pkg->active_sql;
+my $inactive_sql = FS::cust_pkg->inactive_sql;
+my $suspended_sql = FS::cust_pkg->suspended_sql;
+my $cancelled_sql = FS::cust_pkg->cancelled_sql;
+
+my $packages_cols = <<END;
+ ( $select_count_pkgs ) AS num_pkgs_sql,
+ ( $select_count_pkgs AND $active_sql ) AS active_pkgs,
+ ( $select_count_pkgs AND $inactive_sql ) AS inactive_pkgs,
+ ( $select_count_pkgs AND $suspended_sql ) AS suspended_pkgs,
+ ( $select_count_pkgs AND $cancelled_sql ) AS cancelled_pkgs
+END
+
+my @where = ();
+
+unless ( $cgi->param('all_customers') ) {
+
+ my $days = 0;
+ if ( $cgi->param('days') =~ /^\s*(\d+)\s*$/ ) {
+ $days = $1;
+ }
+
+ push @where,
+ call_range_sub($range_sub, $days, 0, 'no_as'=>1). ' > 0'; # != 0';
+}
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ my $agentnum = $1;
+ push @where, "agentnum = $agentnum";
+}
+
+#status (false laziness w/cust_main::search_sql
+
+#prospect active inactive suspended cancelled
+if ( grep { $cgi->param('status') eq $_ } FS::cust_main->statuses() ) {
+ my $method = $cgi->param('status'). '_sql';
+ #push @where, $class->$method();
+ push @where, FS::cust_main->$method();
+}
+
+#here is the agent virtualization
+push @where, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = join(' AND ', @where);
+$where = "WHERE $where" if $where;
+
+my $count_sql = "select count(*) from cust_main $where";
+
+my $sql_query = {
+ 'table' => 'cust_main',
+ 'hashref' => {},
+ 'select' => join(',',
+ #'cust_main.*',
+ 'custnum',
+ $range_cols,
+ $packages_cols,
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $where,
+ 'order_by' => "order by coalesce(lower(company), ''), lower(last)",
+};
+
+my $total_sql =
+ "SELECT ".
+ join(',', map call_range_sub( $range_sub, @$_, 'sum'=>1 ), @$ranges).
+ " FROM cust_main $where";
+
+my $total_sth = dbh->prepare($total_sql) or die dbh->errstr;
+$total_sth->execute or die "error executing $total_sql: ". $total_sth->errstr;
+my $row = $total_sth->fetchrow_hashref();
+
+my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+</%init>
+<%once>
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+#Example:
+#
+# my $balance = balance(
+# $start, $end,
+# 'no_as' => 1, #set to true when using in a WHERE clause (supress AS clause)
+# #or 0 / omit when using in a SELECT clause as a column
+# # ("AS balance_$start_$end")
+# 'sum' => 1, #set to true to get a SUM() of the values, for totals
+#
+# #obsolete? options for totals (passed to cust_main::balance_date_sql)
+# 'total' => 1, #set to true to remove all customer comparison clauses
+# 'join' => $join, #JOIN clause
+# 'where' => \@where, #WHERE clause hashref (elements "AND"ed together)
+# )
+
+sub call_range_sub {
+ my($range_sub, $start, $end, %opt) = @_;
+
+ my $as = $opt{'no_as'} ? '' : " AS rangecol_${start}_$end";
+
+ my $sql = &{$range_sub}( $start, $end ); #%opt?
+
+ $sql = "SUM($sql)" if $opt{'sum'};
+
+ $sql.$as;
+
+}
+
+sub format_rangecol { #closures help alot
+ my $range = shift;
+ sub { sprintf( $money_char.'%.2f', shift->get("rangecol_$range") ) };
+}
+
+</%once>
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index add8427..874bd8a 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -117,7 +117,6 @@ if ( $cgi->param('magic') ) {
my $orderby;
if ( $cgi->param('magic') eq '_date' ) {
-
if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
push @search, "agentnum = $1"; # $search{'agentnum'} = $1;
my $agent = qsearchs('agent', { 'agentnum' => $1 } );
@@ -219,6 +218,13 @@ if ( $cgi->param('magic') ) {
push @search, "_date >= $beginning ",
"_date <= $ending";
+ if ( $thing eq 'pay_void' ) {
+ my($v_beginning, $v_ending) =
+ FS::UI::Web::parse_beginning_ending($cgi, 'void');
+ push @search, "void_date >= $v_beginning ",
+ "void_date <= $v_ending";
+ }
+
push @search, FS::UI::Web::parse_lt_gt($cgi, $amount_field );
$orderby = '_date';
@@ -288,7 +294,9 @@ if ( ( $curuser->access_right('View invoices') #XXX for now
&& ! $opt{'disable_link'}
)
{
- $link = [ "${p}view/cust_$thing.html?${thing}num=", $thing.'num' ]
+ my $key = $thing eq 'pay_void' ? 'paynum' : $thing.'num';
+ my $q = ( $thing eq 'pay_void' ? 'void=1;' : '' ). "$key=";
+ $link = [ "${p}view/cust_$thing.html?$q", $key ]
}
my $cust_link = sub {
diff --git a/httemplate/search/elements/search-csv.html b/httemplate/search/elements/search-csv.html
new file mode 100644
index 0000000..cd4ea63
--- /dev/null
+++ b/httemplate/search/elements/search-csv.html
@@ -0,0 +1,48 @@
+% $csv->combine(@$header); #or die $csv->status;
+%
+<% $csv->string %>\
+%
+% foreach my $row ( @$rows ) {
+%
+% if ( $opt{'fields'} ) {
+%
+% my @line = ();
+%
+% foreach my $field ( @{$opt{'fields'}} ) {
+% if ( ref($field) eq 'CODE' ) {
+% push @line, map {
+% ref($_) eq 'ARRAY'
+% ? '(N/A)' #unimplemented
+% : $_;
+% }
+% &{$field}($row);
+% } else {
+% push @line, $row->$field();
+% }
+% }
+%
+% $csv->combine(@line); #or die $csv->status;
+%
+% } else {
+% $csv->combine(@$row); #or die $csv->status;
+% }
+%
+%
+<% $csv->string %>\
+%
+% }
+<%init>
+
+my %args = @_;
+my $header = $args{'header'};
+my $rows = $args{'rows'};
+my %opt = %{ $args{'opt'} };
+
+#http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+http_header('Content-Type' => 'text/plain' );
+
+my $csv = new Text::CSV_XS { 'always_quote' => 1,
+ 'eol' => "\n", #"\015\012", #"\012"
+ };
+
+</%init>
diff --git a/httemplate/search/elements/search-html.html b/httemplate/search/elements/search-html.html
new file mode 100644
index 0000000..297774d
--- /dev/null
+++ b/httemplate/search/elements/search-html.html
@@ -0,0 +1,454 @@
+%
+% if ( exists($opt{'redirect'}) && $opt{'redirect'}
+% && scalar(@$rows) == 1 && $total == 1
+% && $type ne 'html-print'
+% ) {
+% my $redirect = $opt{'redirect'};
+% $redirect = &{$redirect}($rows->[0], $cgi) if ref($redirect) eq 'CODE';
+% my( $url, $method ) = @$redirect;
+% redirect( $url. $rows->[0]->$method() );
+% } elsif ( exists($opt{'redirect_empty'}) && ! scalar(@$rows) && $total == 0
+% && $type ne 'html-print'
+% && $opt{'redirect_empty'}
+% && ( ref($opt{'redirect_empty'}) ne 'CODE'
+% || &{$opt{'redirect_empty'}}($cgi) )
+% ) {
+% my $redirect = $opt{'redirect_empty'};
+% $redirect = &{$redirect}($cgi) if ref($redirect) eq 'CODE';
+% redirect( $redirect );
+% } else {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = PL($opt{'name_singular'});
+% }
+% ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
+% if ( $total == 1 ) {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = $opt{'name_singular'}
+% } else {
+% #$opt{'name'} =~ s/s$// if $total == 1;
+% $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1;
+% }
+% }
+%
+% if ( $type eq 'html-print' ) {
+
+ <% include( '/elements/header-popup.html', $opt{'title'} ) %>
+
+% } elsif ( $type eq 'select' ) {
+
+ <% include( '/elements/header-popup.html', $opt{'title'} ) %>
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
+
+% } else {
+%
+% my @menubar = ();
+% if ( $opt{'menubar'} ) {
+% @menubar = @{ $opt{'menubar'} };
+% #} else {
+% # @menubar = ( 'Main menu' => $p );
+% }
+
+ <% include( '/elements/header.html', $opt{'title'},
+ include( '/elements/menubar.html', @menubar )
+ )
+ %>
+
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
+
+% }
+
+% unless ( $total ) {
+% unless ( $opt{'disable_nonefound'} ) {
+ No matching <% $opt{'name'} %> found.<BR>
+% }
+% }
+%
+% if ( $total || $opt{'disableable'} ) { #hmm... and there *are* ones to show??
+
+ <TABLE>
+ <TR>
+
+ <TD VALIGN="bottom">
+
+ <FORM>
+
+% if (! $opt{'disable_total'}) {
+ <% $total %> total <% $opt{'name'} %>
+% }
+
+% if ( $confmax && $total > $confmax
+% && ! $opt{'disable_maxselect'}
+% && $type ne 'html-print' )
+% {
+% $cgi->delete('maxrecords');
+% $cgi->param('_dummy', 1);
+
+ ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $cgi->self_url %>;maxrecords=' + this.options[this.selectedIndex].value;">
+
+% foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
+ <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
+% }
+
+ </SELECT> per page )
+
+% $cgi->param('maxrecords', $maxrecords);
+% }
+
+% if ( defined($opt{'html_posttotal'}) && $type ne 'html-print' ) {
+ <% ref($opt{'html_posttotal'})
+ ? &{$opt{'html_posttotal'}}()
+ : $opt{'html_posttotal'}
+ %>
+% }
+ <BR>
+
+% if ( $opt{'count_addl'} ) {
+% my $n=0;
+% foreach my $count ( @{$opt{'count_addl'}} ) {
+% my $data = $count_arrayref->[++$n];
+% if ( ref($count) ) {
+ <% &{ $count }( $data ) %>
+% } else {
+ <% sprintf( $count, $data ) %><BR>
+% }
+% }
+% }
+ </FORM>
+
+ </TD>
+
+% unless ( $opt{'disable_download'} || $type eq 'html-print' ) {
+
+ <TD ALIGN="right">
+
+ Download full results<BR>
+
+% $cgi->param('_type', "$xlsname.xls" );
+ as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
+
+% $cgi->param('_type', 'csv');
+ as <A HREF="<% $cgi->self_url %>">CSV file</A><BR>
+
+% $cgi->param('_type', 'html-print');
+ as <A HREF="<% $cgi->self_url %>">printable copy</A>
+
+ <% $opt{'extra_choices_callback'}
+ ? &{$opt{'extra_choices_callback'}}($cgi->query_string)
+ : ''
+ %>
+
+ </TD>
+% $cgi->param('_type', "html" );
+% }
+
+ </TR>
+ <TR>
+ <TD COLSPAN=2>
+
+% my $pager = '';
+% unless ( $type eq 'html_print' ) {
+
+ <% $pager = include( '/elements/pager.html',
+ 'offset' => $offset,
+ 'num_rows' => scalar(@$rows),
+ 'total' => $total,
+ 'maxrecords' => $maxrecords,
+ )
+ %>
+
+ <% defined($opt{'html_form'})
+ ? ( ref($opt{'html_form'})
+ ? &{$opt{'html_form'}}()
+ : $opt{'html_form'}
+ )
+ : ''
+ %>
+
+% }
+
+ <% include('/elements/table-grid.html') %>
+
+ <TR>
+% my $h2 = 0;
+% foreach my $header ( @{ $opt{header} } ) {
+% my $label = ref($header) ? $header->{label} : $header;
+% my $rowspan = 1;
+% my $style = '';
+% if ( $opt{header2} ) {
+% if ( !length($opt{header2}->[$h2]) ) {
+% $rowspan = 2;
+% splice @{ $opt{header2} }, $h2, 1;
+% } else {
+% $h2++;
+% $style = 'STYLE="border-bottom: none"'
+% }
+% }
+ <TH CLASS = "grid"
+ BGCOLOR = "#cccccc"
+ ROWSPAN = "<% $rowspan %>"
+ <% $style %>
+
+ >
+ <% $label %>
+ </TH>
+% }
+ </TR>
+
+% if ( $opt{header2} ) {
+ <TR>
+% foreach my $header ( @{ $opt{header2} } ) {
+% my $label = ref($header) ? $header->{label} : $header;
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE="-1"><% $label %></FONT>
+ </TH>
+% }
+ </TR>
+% }
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% foreach my $row ( @$rows ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+% if ( $opt{'fields'} ) {
+%
+% my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+% my $onclicks = $opt{'link_onclicks'} ? [ @{$opt{'link_onclicks'}} ] : [];
+% my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+% my $colors = $opt{'color'} ? [ @{$opt{'color'}} ] : [];
+% my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
+% my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : [];
+% my $cstyles = $opt{'cell_style'} ? [ @{$opt{'cell_style'}} ] : [];
+%
+% foreach my $field (
+%
+% map {
+% if ( ref($_) eq 'ARRAY' ) {
+%
+% my $tableref = $_;
+%
+% '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0 WIDTH="100%">'.
+%
+% join('', map {
+%
+% my $rowref = $_;
+%
+% '<tr>'.
+%
+% join('', map {
+%
+% my $e = $_;
+%
+% '<TD '.
+% join(' ', map {
+% uc($_).'="'. $e->{$_}. '"';
+% }
+% grep exists($e->{$_}),
+% qw( align bgcolor colspan rowspan
+% style valign width )
+% ).
+% '>'.
+%
+% ( $e->{'link'}
+% ? '<A HREF="'. $e->{'link'}. '">'
+% : ''
+% ).
+% ( $e->{'size'}
+% ? '<FONT SIZE="'.uc($e->{'size'}).'">'
+% : ''
+% ).
+% ( $e->{'data_style'}
+% ? '<'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% $e->{'data'}.
+% ( $e->{'data_style'}
+% ? '</'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% ( $e->{'size'} ? '</FONT>' : '' ).
+% ( $e->{'link'} ? '</A>' : '' ).
+% '</td>';
+%
+% } @$rowref ).
+%
+% '</tr>';
+% } @$tableref ).
+%
+% '</table>';
+%
+% } else {
+% $_;
+% }
+% }
+%
+% map {
+% if ( ref($_) eq 'CODE' ) {
+% &{$_}($row);
+% } else {
+% $row->$_();
+% }
+% }
+% @{$opt{'fields'}}
+%
+% ) {
+%
+% my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid';
+%
+% my $align = $aligns ? shift @$aligns : '';
+% $align = " ALIGN=$align" if $align;
+%
+% my $a = '';
+% if ( $links ) {
+% my $link = shift @$links;
+% my $onclick = shift @$onclicks;
+%
+% if ( ! $opt{'agent_virt'}
+% || ( $null_link && ! $row->agentnum )
+% || grep { $row->agentnum == $_ }
+% @link_agentnums
+% ) {
+%
+% $link = &{$link}($row)
+% if ref($link) eq 'CODE';
+%
+% $onclick = &{$onclick}($row)
+% if ref($onclick) eq 'CODE';
+% $onclick = qq( onClick="$onclick") if $onclick;
+%
+% if ( $link ) {
+% my( $url, $method ) = @{$link};
+% if ( ref($method) eq 'CODE' ) {
+% $a = $url. &{$method}($row);
+% } else {
+% $a = $url. $row->$method();
+% }
+% $a = qq(<A HREF="$a"$onclick>);
+% }
+%
+% }
+%
+% }
+%
+% my $font = '';
+% my $color = shift @$colors;
+% $color = &{$color}($row) if ref($color) eq 'CODE';
+% my $size = shift @$sizes;
+% $size = &{$size}($row) if ref($size) eq 'CODE';
+% if ( $color || $size ) {
+% $font = '<FONT '.
+% ( $color ? "COLOR=#$color " : '' ).
+% ( $size ? qq(SIZE="$size" ) : '' ).
+% '>';
+% }
+%
+% my($s, $es) = ( '', '' );
+% my $style = shift @$styles;
+% $style = &{$style}($row) if ref($style) eq 'CODE';
+% if ( $style ) {
+% $s = join( '', map "<$_>", split('', $style) );
+% $es = join( '', map "</$_>", split('', $style) );
+% }
+%
+% my $cstyle = shift @$cstyles;
+% $cstyle = &{$cstyle}($row) if ref($cstyle) eq 'CODE';
+% $cstyle = qq(STYLE="$cstyle")
+% if $cstyle;
+
+ <TD CLASS="<% $class %>" BGCOLOR="<% $bgcolor %>" <% $align %> <% $cstyle %>><% $font %><% $a %><% $s %><% $field %><% $es %><% $a ? '</A>' : '' %><% $font ? '</FONT>' : '' %></TD>
+
+% }
+%
+% } else {
+%
+% foreach ( @$row ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $_ %></TD>
+% }
+%
+% }
+
+ </TR>
+
+% }
+
+% if ( $opt{'footer'} ) {
+
+ <TR>
+
+% foreach my $footer ( @{ $opt{'footer'} } ) {
+ <TD CLASS="grid" BGCOLOR="#dddddd" STYLE="border-top: dashed 1px black;"><i><% $footer %></i></TD>
+% }
+
+ </TR>
+% }
+
+ </TABLE>
+
+ <% $pager %>
+
+ </TD>
+ </TR>
+ </TABLE>
+% }
+
+% if ( $type eq 'html-print' ) {
+
+ </BODY></HTML>
+
+% } else {
+
+ <% defined($opt{'html_foot'})
+ ? ( ref($opt{'html_foot'})
+ ? &{$opt{'html_foot'}}()
+ : $opt{'html_foot'}
+ )
+ : ''
+ %>
+
+ <% include( '/elements/footer.html' ) %>
+
+% }
+
+% }
+<%init>
+
+my %args = @_;
+my $type = $args{'type'};
+my $header = $args{'header'};
+my $rows = $args{'rows'};
+my @link_agentnums = @{ $args{'link_agentnums'} };
+my $null_link = $args{'null_link'};
+my $confmax = $args{'confmax'};
+my $maxrecords = $args{'maxrecords'};
+my $offset = $args{'offset'};
+my %opt = %{ $args{'opt'} };
+
+my $count_sth = dbh->prepare($opt{'count_query'})
+ or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
+$count_sth->execute
+ or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
+my $count_arrayref = $count_sth->fetchrow_arrayref;
+my $total = $count_arrayref->[0];
+
+</%init>
diff --git a/httemplate/search/elements/search-xls.html b/httemplate/search/elements/search-xls.html
new file mode 100644
index 0000000..8a05e47
--- /dev/null
+++ b/httemplate/search/elements/search-xls.html
@@ -0,0 +1,83 @@
+<% $data %>
+<%init>
+
+my %args = @_;
+my $type = $args{'type'};
+my $header = $args{'header'};
+my $rows = $args{'rows'};
+my %opt = %{ $args{'opt'} };
+
+#http_header('Content-Type' => 'application/excel' ); #eww
+#http_header('Content-Type' => 'application/msexcel' ); #alas
+#http_header('Content-Type' => 'application/x-msexcel' ); #?
+
+#http://support.microsoft.com/kb/199841
+http_header('Content-Type' => 'application/vnd.ms-excel' );
+
+#http://support.microsoft.com/kb/812935
+#http://support.microsoft.com/kb/323308
+$HTML::Mason::Commands::r->headers_out->{'Cache-control'} = 'max-age=0';
+
+my $data = '';
+my $XLS = new IO::Scalar \$data;
+my $workbook = Spreadsheet::WriteExcel->new($XLS)
+ or die "Error opening .xls file: $!";
+
+my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
+
+$worksheet->protect();
+
+my($r,$c) = (0,0);
+
+my $header_format = $workbook->add_format(
+ bold => 1,
+ locked => 1,
+ bg_color => 55, #22,
+ bottom => 3,
+);
+
+$worksheet->write($r, $c++, $_, $header_format ) foreach @$header;
+
+foreach my $row ( @$rows ) {
+ $r++;
+ $c = 0;
+
+ if ( $opt{'fields'} ) {
+
+ #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+ #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+ #could also translate color, size, style into xls equivalents?
+ my $formats = $opt{'xls_format'} ? [ @{$opt{'xls_format'}} ] : [];
+
+ foreach my $field ( @{$opt{'fields'}} ) {
+
+ my $format = shift @$formats;
+ $format = &{$format}($row) if ref($format) eq 'CODE';
+ $format ||= {};
+ my $xls_format = $workbook->add_format(locked=>0, %$format);
+
+ if ( ref($field) eq 'CODE' ) {
+ foreach my $value ( &{$field}($row) ) {
+ if ( ref($value) eq 'ARRAY' ) {
+ $worksheet->write($r, $c++, '(N/A)' ); #unimplemented
+ } else {
+ $worksheet->write($r, $c++, $value, $xls_format );
+ }
+ }
+ } else {
+ $worksheet->write($r, $c++, $row->$field(), $xls_format );
+ }
+ }
+
+ } else {
+ my $xls_format = $workbook->add_format(locked=>0);
+ $worksheet->write($r, $c++, $_, $xls_format ) foreach @$row;
+ }
+
+}
+
+$workbook->close();# or die "Error creating .xls file: $!";
+
+http_header('Content-Length' => length($data) );
+
+</%init>
diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html
index 8835f8c..4bfe8b0 100644
--- a/httemplate/search/elements/search.html
+++ b/httemplate/search/elements/search.html
@@ -16,7 +16,8 @@ Example:
# (deprecated, will be singularlized
# simplisticly)
- #literal SQL query string (deprecated?) or qsearch hashref
+ #literal SQL query string (deprecated?) or qsearch hashref or arrayref
+ #of qsearch hashrefs for a union of qsearches
'query' => {
'table' => 'tablename',
#everything else is optional...
@@ -148,570 +149,42 @@ Example:
'align' => 'lrc.',
#listrefs of ( scalars or coderefs )
- #currently only HTML, maybe eventually Excel too
+ # currently only HTML, maybe eventually Excel too
'color' => [],
'size' => [],
'style' => [], #<B> or <I>, etc.
'cell_style' => [], #STYLE= attribute of TR, very HTML-specific...
+
+ # Excel-specific listref of ( hashrefs or coderefs )
+ # each hashref: http://search.cpan.org/dist/Spreadsheet-WriteExcel/lib/Spreadsheet/WriteExcel.pm#Format_methods_and_Format_properties
+ 'xls_format' => => [],
);
</%doc>
% if ( $type eq 'csv' ) {
%
-% #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
-% http_header('Content-Type' => 'text/plain' );
-%
-% my $csv = new Text::CSV_XS { 'always_quote' => 1,
-% 'eol' => "\n", #"\015\012", #"\012"
-% };
-%
-% $csv->combine(@$header); #or die $csv->status;
-%
-<% $csv->string %>
-%
-%
-% foreach my $row ( @$rows ) {
-%
-% if ( $opt{'fields'} ) {
-%
-% my @line = ();
-%
-% foreach my $field ( @{$opt{'fields'}} ) {
-% if ( ref($field) eq 'CODE' ) {
-% push @line, map {
-% ref($_) eq 'ARRAY'
-% ? '(N/A)' #unimplemented
-% : $_;
-% }
-% &{$field}($row);
-% } else {
-% push @line, $row->$field();
-% }
-% }
-%
-% $csv->combine(@line); #or die $csv->status;
-%
-% } else {
-% $csv->combine(@$row); #or die $csv->status;
-% }
-%
-%
-<% $csv->string %>
-%
-%
-% }
+<% include('search-csv.html', header=>$header, rows=>$rows, opt=>\%opt ) %>
%
% #} elsif ( $type eq 'excel' ) {
% } elsif ( $type =~ /\.xls$/ ) {
%
-% #http_header('Content-Type' => 'application/excel' ); #eww
-% #http_header('Content-Type' => 'application/msexcel' ); #alas
-% #http_header('Content-Type' => 'application/x-msexcel' ); #?
-%
-% #http://support.microsoft.com/kb/199841
-% http_header('Content-Type' => 'application/vnd.ms-excel' );
-%
-% #http://support.microsoft.com/kb/812935
-% #http://support.microsoft.com/kb/323308
-% $HTML::Mason::Commands::r->headers_out->{'Cache-control'} = 'max-age=0';
-%
-% my $data = '';
-% my $XLS = new IO::Scalar \$data;
-% my $workbook = Spreadsheet::WriteExcel->new($XLS)
-% or die "Error opening .xls file: $!";
-%
-% my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
-%
-% my($r,$c) = (0,0);
-%
-% $worksheet->write($r, $c++, $_) foreach @$header;
-%
-% foreach my $row ( @$rows ) {
-% $r++;
-% $c = 0;
-%
-% if ( $opt{'fields'} ) {
-%
-% #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
-% #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
-%
-% foreach my $field ( @{$opt{'fields'}} ) {
-% #my $align = $aligns ? shift @$aligns : '';
-% #$align = " ALIGN=$align" if $align;
-% #my $a = '';
-% #if ( $links ) {
-% # my $link = shift @$links;
-% # $link = &{$link}($row) if ref($link) eq 'CODE';
-% # if ( $link ) {
-% # my( $url, $method ) = @{$link};
-% # if ( ref($method) eq 'CODE' ) {
-% # $a = $url. &{$method}($row);
-% # } else {
-% # $a = $url. $row->$method();
-% # }
-% # $a = qq(<A HREF="$a">);
-% # }
-% #}
-% if ( ref($field) eq 'CODE' ) {
-% foreach my $value ( &{$field}($row) ) {
-% if ( ref($value) eq 'ARRAY' ) {
-% $worksheet->write($r, $c++, '(N/A)' ); #unimplemented
-% } else {
-% $worksheet->write($r, $c++, $value );
-% }
-% }
-% } else {
-% $worksheet->write($r, $c++, $row->$field() );
-% }
-% }
-%
-% } else {
-% $worksheet->write($r, $c++, $_) foreach @$row;
-% }
-%
-% }
-%
-% $workbook->close();# or die "Error creating .xls file: $!";
-%
-% http_header('Content-Length' => length($data) );
-%
-<% $data %>
-%
+<% include('search-xls.html', header=>$header, rows=>$rows, opt=>\%opt ) %>
%
% } else { # regular HTML
%
-% if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1
-% && $type ne 'html-print'
-% ) {
-% my $redirect = $opt{'redirect'};
-% $redirect = &{$redirect}($rows->[0], $cgi) if ref($redirect) eq 'CODE';
-% my( $url, $method ) = @$redirect;
-% redirect( $url. $rows->[0]->$method() );
-% } elsif ( exists($opt{'redirect_empty'}) && ! scalar(@$rows) && $total == 0
-% && $type ne 'html-print'
-% && $opt{'redirect_empty'}
-% && ( ref($opt{'redirect_empty'}) ne 'CODE'
-% || &{$opt{'redirect_empty'}}($cgi) )
-% ) {
-% my $redirect = $opt{'redirect_empty'};
-% $redirect = &{$redirect}($cgi) if ref($redirect) eq 'CODE';
-% redirect( $redirect );
-% } else {
-% if ( $opt{'name_singular'} ) {
-% $opt{'name'} = PL($opt{'name_singular'});
-% }
-% ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
-% if ( $total == 1 ) {
-% if ( $opt{'name_singular'} ) {
-% $opt{'name'} = $opt{'name_singular'}
-% } else {
-% #$opt{'name'} =~ s/s$// if $total == 1;
-% $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1;
-% }
-% }
-%
-% if ( $type eq 'html-print' ) {
-
- <% include( '/elements/header-popup.html', $opt{'title'} ) %>
-
-% } elsif ( $type eq 'select' ) {
-
- <% include( '/elements/header-popup.html', $opt{'title'} ) %>
- <% defined($opt{'html_init'})
- ? ( ref($opt{'html_init'})
- ? &{$opt{'html_init'}}()
- : $opt{'html_init'}
- )
- : ''
- %>
-
-% } else {
-%
-% my @menubar = ();
-% if ( $opt{'menubar'} ) {
-% @menubar = @{ $opt{'menubar'} };
-% #} else {
-% # @menubar = ( 'Main menu' => $p );
-% }
-
- <% include( '/elements/header.html', $opt{'title'},
- include( '/elements/menubar.html', @menubar )
- )
- %>
-
- <% defined($opt{'html_init'})
- ? ( ref($opt{'html_init'})
- ? &{$opt{'html_init'}}()
- : $opt{'html_init'}
- )
- : ''
- %>
-
-% }
-
-% unless ( $total ) {
-% unless ( $opt{'disable_nonefound'} ) {
- No matching <% $opt{'name'} %> found.<BR>
-% }
-% }
-%
-% if ( $total || $opt{'disableable'} ) { #hmm... and there *are* ones to show??
-
- <TABLE>
- <TR>
-
- <TD VALIGN="bottom">
-
- <FORM>
-
-% if (! $opt{'disable_total'}) {
- <% $total %> total <% $opt{'name'} %>
-% }
-
-% if ( $confmax && $total > $confmax
-% && ! $opt{'disable_maxselect'}
-% && $type ne 'html-print' )
-% {
-% $cgi->delete('maxrecords');
-% $cgi->param('_dummy', 1);
-
- ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $cgi->self_url %>;maxrecords=' + this.options[this.selectedIndex].value;">
-
-% foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
- <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
-% }
-
- </SELECT> per page )
-
-% $cgi->param('maxrecords', $maxrecords);
-% }
-
-% if ( defined($opt{'html_posttotal'}) && $type ne 'html-print' ) {
- <% ref($opt{'html_posttotal'})
- ? &{$opt{'html_posttotal'}}()
- : $opt{'html_posttotal'}
- %>
-% }
- <BR>
-
-% if ( $opt{'count_addl'} ) {
-% my $n=0;
-% foreach my $count ( @{$opt{'count_addl'}} ) {
-% my $data = $count_arrayref->[++$n];
-% if ( ref($count) ) {
- <% &{ $count }( $data ) %>
-% } else {
- <% sprintf( $count, $data ) %><BR>
-% }
-% }
-% }
- </FORM>
-
- </TD>
-
-% unless ( $opt{'disable_download'} || $type eq 'html-print' ) {
-
- <TD ALIGN="right">
-
- Download full results<BR>
-
-% $cgi->param('_type', "$xlsname.xls" );
- as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
-
-% $cgi->param('_type', 'csv');
- as <A HREF="<% $cgi->self_url %>">CSV file</A><BR>
-
-% $cgi->param('_type', 'html-print');
- as <A HREF="<% $cgi->self_url %>">printable copy</A>
-
- <% $opt{'extra_choices_callback'}
- ? &{$opt{'extra_choices_callback'}}($cgi->query_string)
- : ''
- %>
-
- </TD>
-% $cgi->param('_type', "html" );
-% }
-
- </TR>
- <TR>
- <TD COLSPAN=2>
-
-% my $pager = '';
-% unless ( $type eq 'html_print' ) {
-
- <% $pager = include( '/elements/pager.html',
- 'offset' => $offset,
- 'num_rows' => scalar(@$rows),
- 'total' => $total,
- 'maxrecords' => $maxrecords,
- )
- %>
-
- <% defined($opt{'html_form'})
- ? ( ref($opt{'html_form'})
- ? &{$opt{'html_form'}}()
- : $opt{'html_form'}
- )
- : ''
- %>
-
-% }
-
- <% include('/elements/table-grid.html') %>
-
- <TR>
-% my $h2 = 0;
-% foreach my $header ( @{ $opt{header} } ) {
-% my $label = ref($header) ? $header->{label} : $header;
-% my $rowspan = 1;
-% my $style = '';
-% if ( $opt{header2} ) {
-% if ( !length($opt{header2}->[$h2]) ) {
-% $rowspan = 2;
-% splice @{ $opt{header2} }, $h2, 1;
-% } else {
-% $h2++;
-% $style = 'STYLE="border-bottom: none"'
-% }
-% }
- <TH CLASS = "grid"
- BGCOLOR = "#cccccc"
- ROWSPAN = "<% $rowspan %>"
- <% $style %>
-
- >
- <% $label %>
- </TH>
-% }
- </TR>
-
-% if ( $opt{header2} ) {
- <TR>
-% foreach my $header ( @{ $opt{header2} } ) {
-% my $label = ref($header) ? $header->{label} : $header;
- <TH CLASS="grid" BGCOLOR="#cccccc">
- <FONT SIZE="-1"><% $label %></FONT>
- </TH>
-% }
- </TR>
-% }
-
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor;
-%
-% foreach my $row ( @$rows ) {
-%
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-
- <TR>
-
-% if ( $opt{'fields'} ) {
-%
-% my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
-% my $onclicks = $opt{'link_onclicks'} ? [ @{$opt{'link_onclicks'}} ] : [];
-% my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
-% my $colors = $opt{'color'} ? [ @{$opt{'color'}} ] : [];
-% my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
-% my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : [];
-% my $cstyles = $opt{'cell_style'} ? [ @{$opt{'cell_style'}} ] : [];
-%
-% foreach my $field (
-%
-% map {
-% if ( ref($_) eq 'ARRAY' ) {
-%
-% my $tableref = $_;
-%
-% '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0 WIDTH="100%">'.
-%
-% join('', map {
-%
-% my $rowref = $_;
-%
-% '<tr>'.
-%
-% join('', map {
-%
-% my $e = $_;
-%
-% '<TD '.
-% join(' ', map {
-% uc($_).'="'. $e->{$_}. '"';
-% }
-% grep exists($e->{$_}),
-% qw( align bgcolor colspan rowspan
-% style valign width )
-% ).
-% '>'.
-%
-% ( $e->{'link'}
-% ? '<A HREF="'. $e->{'link'}. '">'
-% : ''
-% ).
-% ( $e->{'size'}
-% ? '<FONT SIZE="'.uc($e->{'size'}).'">'
-% : ''
-% ).
-% ( $e->{'data_style'}
-% ? '<'. uc($e->{'data_style'}). '>'
-% : ''
-% ).
-% $e->{'data'}.
-% ( $e->{'data_style'}
-% ? '</'. uc($e->{'data_style'}). '>'
-% : ''
-% ).
-% ( $e->{'size'} ? '</FONT>' : '' ).
-% ( $e->{'link'} ? '</A>' : '' ).
-% '</td>';
-%
-% } @$rowref ).
-%
-% '</tr>';
-% } @$tableref ).
-%
-% '</table>';
-%
-% } else {
-% $_;
-% }
-% }
-%
-% map {
-% if ( ref($_) eq 'CODE' ) {
-% &{$_}($row);
-% } else {
-% $row->$_();
-% }
-% }
-% @{$opt{'fields'}}
-%
-% ) {
-%
-% my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid';
-%
-% my $align = $aligns ? shift @$aligns : '';
-% $align = " ALIGN=$align" if $align;
-%
-% my $a = '';
-% if ( $links ) {
-% my $link = shift @$links;
-% my $onclick = shift @$onclicks;
-%
-% if ( ! $opt{'agent_virt'}
-% || ( $null_link && ! $row->agentnum )
-% || grep { $row->agentnum == $_ }
-% @link_agentnums
-% ) {
-%
-% $link = &{$link}($row)
-% if ref($link) eq 'CODE';
-%
-% $onclick = &{$onclick}($row)
-% if ref($onclick) eq 'CODE';
-% $onclick = qq( onClick="$onclick") if $onclick;
-%
-% if ( $link ) {
-% my( $url, $method ) = @{$link};
-% if ( ref($method) eq 'CODE' ) {
-% $a = $url. &{$method}($row);
-% } else {
-% $a = $url. $row->$method();
-% }
-% $a = qq(<A HREF="$a"$onclick>);
-% }
-%
-% }
-%
-% }
-%
-% my $font = '';
-% my $color = shift @$colors;
-% $color = &{$color}($row) if ref($color) eq 'CODE';
-% my $size = shift @$sizes;
-% $size = &{$size}($row) if ref($size) eq 'CODE';
-% if ( $color || $size ) {
-% $font = '<FONT '.
-% ( $color ? "COLOR=#$color " : '' ).
-% ( $size ? qq(SIZE="$size" ) : '' ).
-% '>';
-% }
-%
-% my($s, $es) = ( '', '' );
-% my $style = shift @$styles;
-% $style = &{$style}($row) if ref($style) eq 'CODE';
-% if ( $style ) {
-% $s = join( '', map "<$_>", split('', $style) );
-% $es = join( '', map "</$_>", split('', $style) );
-% }
-%
-% my $cstyle = shift @$cstyles;
-% $cstyle = &{$cstyle}($row) if ref($cstyle) eq 'CODE';
-% $cstyle = qq(STYLE="$cstyle")
-% if $cstyle;
-
- <TD CLASS="<% $class %>" BGCOLOR="<% $bgcolor %>" <% $align %> <% $cstyle %>><% $font %><% $a %><% $s %><% $field %><% $es %><% $a ? '</A>' : '' %><% $font ? '</FONT>' : '' %></TD>
-
-% }
-%
-% } else {
-%
-% foreach ( @$row ) {
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $_ %></TD>
-% }
-%
-% }
-
- </TR>
-
-% }
-
-% if ( $opt{'footer'} ) {
-
- <TR>
-
-% foreach my $footer ( @{ $opt{'footer'} } ) {
- <TD CLASS="grid" BGCOLOR="#dddddd" STYLE="border-top: dashed 1px black;"><i><% $footer %></i></TD>
-% }
-
- </TR>
-% }
-
- </TABLE>
-
- <% $pager %>
-
- </TD>
- </TR>
- </TABLE>
-% }
-
-% if ( $type eq 'html-print' ) {
-
- </BODY></HTML>
-
-% } else {
-
- <% defined($opt{'html_foot'})
- ? ( ref($opt{'html_foot'})
- ? &{$opt{'html_foot'}}()
- : $opt{'html_foot'}
- )
- : ''
- %>
-
- <% include( '/elements/footer.html' ) %>
-
-% }
-
-% }
+<% include('search-html.html',
+ type => $type,
+ header => $header,
+ rows => $rows,
+ link_agentnums => \@link_agentnums,
+ null_link => $null_link,
+ confmax => $confmax,
+ maxrecords => $maxrecords,
+ offset => $offset,
+ opt => \%opt
+ )
+%>
%
% }
<%init>
@@ -759,7 +232,7 @@ if ( $opt{'agent_virt'} ) {
#false laziness w/statuspos above
my $pos = $opt{'agent_pos'};
- foreach my $att (qw( align style color size )) {
+ foreach my $att (qw( align color size style cell_style xls_format )) {
$opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
}
@@ -833,7 +306,7 @@ my $type = $cgi->param('_type') =~ /^(csv|\w*\.xls|select|html(-print)?)$/
? $1 : 'html';
my $limit = '';
-my($confmax, $maxrecords, $total, $offset, $count_arrayref);
+my($confmax, $maxrecords, $offset );
unless ( $type =~ /^(csv|\w*\.xls)$/ ) {
@@ -867,13 +340,6 @@ unless ( $type =~ /^(csv|\w*\.xls)$/ ) {
}
- my $count_sth = dbh->prepare($opt{'count_query'})
- or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
- $count_sth->execute
- or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
- $count_arrayref = $count_sth->fetchrow_arrayref;
- $total = $count_arrayref->[0];
-
}
# run the query
@@ -882,6 +348,15 @@ my $header = [ map { ref($_) ? $_->{'label'} : $_ } @{$opt{header}} ];
my $rows;
if ( ref($opt{query}) ) {
+ my @query;
+ if (ref($opt{query}) eq 'HASH') {
+ @query = ( $opt{query} );
+ } elsif (ref($opt{query}) eq 'ARRAY') {
+ @query = @{ $opt{query} };
+ } else {
+ die "invalid query reference";
+ }
+
if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
#%search = ( 'disabled' => '' );
$opt{'query'}->{'hashref'}->{'disabled'} = '';
@@ -889,14 +364,15 @@ if ( ref($opt{query}) ) {
}
#eval "use FS::$opt{'query'};";
- $rows = [ qsearch({
- 'select' => $opt{'query'}->{'select'},
- 'table' => $opt{'query'}->{'table'},
- 'addl_from' => (exists($opt{'query'}->{'addl_from'}) ? $opt{'query'}->{'addl_from'} : ''),
- 'hashref' => $opt{'query'}->{'hashref'} || {},
- 'extra_sql' => $opt{'query'}->{'extra_sql'},
- 'order_by' => $opt{'query'}->{'order_by'}. " $limit",
- }) ];
+ my @param = qw( select table addl_from hashref extra_sql order_by );
+ $rows = [ qsearch( [ map { my $query = $_;
+ ({ map { $_ => $query->{$_} } @param });
+ }
+ @query
+ ],
+ 'order_by' => $opt{order_by}. " ". $limit,
+ )
+ ];
} else {
my $sth = dbh->prepare("$opt{'query'} $limit")
or die "Error preparing $opt{'query'}: ". dbh->errstr;
diff --git a/httemplate/search/reg_code.html b/httemplate/search/reg_code.html
index f65b00d..f7d6d20 100644
--- a/httemplate/search/reg_code.html
+++ b/httemplate/search/reg_code.html
@@ -13,7 +13,7 @@
sub {
map {
qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
- $_->pkg. ' - '. $_->comment.
+ $_->pkg_comment(nopkgpart => 1).
'</A><BR>'
} $_[0]->part_pkg
},
diff --git a/httemplate/search/report_477.html b/httemplate/search/report_477.html
new file mode 100755
index 0000000..7b85c13
--- /dev/null
+++ b/httemplate/search/report_477.html
@@ -0,0 +1,64 @@
+<% include('/elements/header.html', 'FCC Form 477 Report' ) %>
+
+<FORM ACTION="477.html" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="active">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-select-pkg_class.html',
+ 'pre_options' => [ '0' => 'all' ],
+ 'empty_label' => '(empty class)',
+ )
+ %>
+
+% if ( scalar( qsearch( 'part_pkg_report_option', { 'disabled' => '' } ) ) ) {
+% # the m2 javascript magic in edit/elements/edit.html would be better here
+
+ <% include( '/elements/tr-select-table.html',
+ 'label' => 'Column report classes',
+ 'table' => 'part_pkg_report_option',
+ 'name_col' => 'name',
+ 'hashref' => { 'disabled' => '' },
+ 'element_name' => 'column_option',
+ 'multiple' => 'multiple',
+ )
+ %>
+
+ <% include( '/elements/tr-select-table.html',
+ 'label' => 'Row report classes',
+ 'table' => 'part_pkg_report_option',
+ 'name_col' => 'name',
+ 'hashref' => { 'disabled' => '' },
+ 'element_name' => 'row_option',
+ 'multiple' => 'multiple',
+ )
+ %>
+
+% }
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages');
+
+</%init>
diff --git a/httemplate/search/report_cdr.html b/httemplate/search/report_cdr.html
index 2851631..c685198 100644
--- a/httemplate/search/report_cdr.html
+++ b/httemplate/search/report_cdr.html
@@ -3,6 +3,13 @@
<FORM ACTION="cdr.html" METHOD="GET">
<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
<TR>
<TD ALIGN="right">Status: </TD>
<TD>
@@ -14,6 +21,23 @@
</TD>
</TR>
+% #if ( ) { # disable for everyone not using termination billing...
+% foreach my $termpart ( 1..1 ) { #qsearch('part_termination
+
+ <TR>
+ <TD ALIGN="right">Termination Status: </TD>
+ <TD>
+ <SELECT NAME="termpart<%$termpart%>status">
+ <OPTION VALUE="">(all)
+ <OPTION VALUE="NULL">unprocessed
+ <OPTION VALUE="done">processed
+ </SELECT>
+ </TD>
+ </TR>
+
+% }
+% #}
+
<% include ( '/elements/tr-input-beginning_ending.html' ) %>
<TR>
@@ -30,6 +54,21 @@
</TD>
</TR>
+ <TR>
+ <TD ALIGN="right">Destination Context: </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="dcontext">
+ </TD>
+ </TR>
+
+
+ <TR>
+ <TD ALIGN="right">Charged Party #: </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="charged_party">
+ </TD>
+ </TR>
+
<% include( '/elements/tr-input-lessthan_greaterthan.html',
'label' => 'Duration (sec)',
'field' => 'duration',
@@ -44,15 +83,66 @@
<% include( '/elements/tr-select-cdrbatch.html' ) %>
+ <TR>
+ <TD ALIGN="right">Acct ID (one per-line):</TD>
+ <TD><TEXTAREA NAME="acctid"></TEXTAREA></TD>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TH>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Display options</FONT></TH>
+ </TR>
+
+ <INPUT TYPE="hidden" NAME="show" VALUE="1">
+
+ <TR>
+ <TD COLSPAN=2>
+ <% include('/elements/checkboxes.html',
+ 'names_list' => $names_list,
+ 'element_name_prefix' => 'show_',
+ 'checked_callback' => sub { $show_default{$_[1]} },
+ # my($cgi, $name) = @_;
+ )
+ %>
+ </TD>
+ </TR>
+
</TABLE>
<BR>
<INPUT TYPE="submit" VALUE="Search Call Detail Records">
+</FORM>
+
<% include('/elements/footer.html') %>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+my @fields = fields('cdr');
+my $labels = FS::cdr->table_info->{'fields'};
+
+#XXX config
+my @show_default = qw(
+ calldate clid src dst dcontext charged_party
+ startdate answerdate enddate duration billsec
+ disposition amaflags accountcode userfield
+ rated_price upstream_price carrierid
+ svcnum freesidestatus freesiderewritestatus cdrbatch
+);
+my %show_default = map { $_=>1 } @show_default;
+
+my $names_list = [ map {
+ [ $_ => {
+ 'label' => 'Show '. ( $labels->{$_} || $_ )
+ }
+ ]
+ }
+ @fields
+ ];
+
</%init>
diff --git a/httemplate/search/report_cust_main.html b/httemplate/search/report_cust_main.html
index b0c5fde..f139d4b 100755
--- a/httemplate/search/report_cust_main.html
+++ b/httemplate/search/report_cust_main.html
@@ -56,6 +56,15 @@
<TD><INPUT TYPE="checkbox" NAME="cancelled_pkgs"></TD>
</TR>
+% if ( $conf->exists('cust_main-require_censustract') ) {
+
+ <TR>
+ <TD ALIGN="right" VALIGN="center">Without census tract</TD>
+ <TD><INPUT TYPE="checkbox" NAME="no_censustract"></TD>
+ </TR>
+
+% }
+
<TR>
<TH BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TH>
</TR>
@@ -84,6 +93,8 @@ die "access denied"
$FS::CurrentUser::CurrentUser->access_right('List packages')
);;
+my $conf = new FS::Conf;
+
</%init>
<%once>
diff --git a/httemplate/search/report_cust_pay.html b/httemplate/search/report_cust_pay.html
index 0627131..dd2358a 100644
--- a/httemplate/search/report_cust_pay.html
+++ b/httemplate/search/report_cust_pay.html
@@ -1,9 +1,15 @@
-<% include('/elements/header.html', 'Payment report' ) %>
+<% include('/elements/header.html', $title ) %>
-<FORM ACTION="cust_pay.cgi" METHOD="GET">
+<FORM ACTION="<% $void ? 'cust_pay_void.html' : 'cust_pay.cgi' %>" METHOD="GET">
<INPUT TYPE="hidden" NAME="magic" VALUE="_date">
-<TABLE>
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
<TR>
<TD ALIGN="right">Payments of type: </TD>
@@ -55,7 +61,32 @@
)
%>
- <% include( '/elements/tr-input-beginning_ending.html' ) %>
+ <TR>
+ <TD ALIGN="right" VALIGN="center">Payment</TD>
+ <TD>
+ <TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html',
+ layout => 'horiz',
+ )
+ %>
+ </TABLE>
+ </TD>
+ </TR>
+
+% if ( $void ) {
+ <TR>
+ <TD ALIGN="right" VALIGN="center">Voided</TD>
+ <TD>
+ <TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html',
+ prefix => 'void',
+ layout => 'horiz',
+ )
+ %>
+ </TABLE>
+ </TD>
+ </TR>
+% }
<% include( '/elements/tr-input-lessthan_greaterthan.html',
'label' => 'Amount',
@@ -76,4 +107,8 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+my $void = $cgi->param('void') ? 1 : 0;
+
+my $title = $void ? 'Voided payment report' : 'Payment report';
+
</%init>
diff --git a/httemplate/search/report_cust_pkg.html b/httemplate/search/report_cust_pkg.html
index aef1c24..66dd7d1 100755
--- a/httemplate/search/report_cust_pkg.html
+++ b/httemplate/search/report_cust_pkg.html
@@ -72,6 +72,20 @@
)
%>
+% if ( scalar( qsearch( 'part_pkg_report_option', { 'disabled' => '' } ) ) ) {
+
+ <% include( '/elements/tr-select-table.html',
+ 'label' => 'Report classes',
+ 'table' => 'part_pkg_report_option',
+ 'name_col' => 'name',
+ 'hashref' => { 'disabled' => '' },
+ 'element_name' => 'report_option',
+ 'multiple' => 'multiple',
+ )
+ %>
+
+% }
+
% foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
<TR>
@@ -89,6 +103,34 @@
% }
+ <SCRIPT TYPE="text/javascript">
+
+ function custom_changed(what) {
+
+ if ( what.checked ) {
+
+ what.form.pkgpart.disabled = true;
+ what.form.pkgpart.style.backgroundColor = '#dddddd';
+
+ } else {
+
+ what.form.pkgpart.disabled = false;
+ what.form.pkgpart.style.backgroundColor = '#ffffff';
+
+ }
+
+ }
+
+ </SCRIPT>
+
+ <% include( '/elements/tr-checkbox.html',
+ 'label' => 'Custom packages',
+ 'field' => 'custom',
+ 'value' => 1,
+ 'onchange' => 'custom_changed(this);',
+ )
+ %>
+
<% include( '/elements/tr-selectmultiple-part_pkg.html' ) %>
<TR>
@@ -129,6 +171,7 @@ my %label = (
#false laziness w/cust_pkg.cgi
my %disable = (
'all' => {},
+ 'not yet billed' => { 'setup'=>1, 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, },
'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, },
'active' => { 'susp'=>1, 'cancel'=>1 },
'suspended' => { 'cancel' => 1 },
diff --git a/httemplate/search/report_newtax.cgi b/httemplate/search/report_newtax.cgi
index 586fddd..0fb5483 100755
--- a/httemplate/search/report_newtax.cgi
+++ b/httemplate/search/report_newtax.cgi
@@ -15,6 +15,7 @@
<TR>
<TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
<TH CLASS="grid" BGCOLOR="#cccccc">Tax collected</TH>
</TR>
% my $bgcolor1 = '#eeeeee';
@@ -37,9 +38,11 @@
<TR>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $tax->{'label'} %></TD>
+ <% $tax->{base} ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
<A HREF="<% $baselink. $link %>;istax=1"><% $money_char %><% sprintf('%.2f', $tax->{'tax'} ) %></A>
</TD>
+ <% !($tax->{base}) ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %>
</TR>
% }
@@ -61,10 +64,11 @@ my $join_cust = "
JOIN cust_bill USING ( invnum )
LEFT JOIN cust_main USING ( custnum )
";
-my $from_join_cust = "
- FROM cust_bill_pkg
- $join_cust
-";
+
+my $join_loc = "LEFT JOIN cust_bill_pkg_tax_rate_location USING ( billpkgnum )";
+my $join_tax_loc = "LEFT JOIN tax_rate_location USING ( taxratelocationnum )";
+
+my $addl_from = " $join_cust $join_loc $join_tax_loc ";
my $where = "WHERE _date >= $beginning AND _date <= $ending ";
@@ -76,65 +80,87 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
$where .= ' AND cust_main.agentnum = '. $agent->agentnum;
}
+# my ( $location_sql, @location_param ) = FS::cust_pkg->location_sql;
+# $where .= " AND $location_sql";
+#my @taxparam = ( 'itemdesc', @location_param );
+# now something along the lines of geocode matching ?
+#$where .= FS::cust_pkg->_location_sql_where('cust_tax_location');;
+my @taxparam = ( 'itemdesc', 'tax_rate_location.state', 'tax_rate_location.county', 'tax_rate_location.city', 'cust_bill_pkg_tax_rate_location.locationtaxid' );
+
+my $select = 'DISTINCT itemdesc,locationtaxid,tax_rate_location.state,tax_rate_location.county,tax_rate_location.city';
+
my $tax = 0;
my %taxes = ();
+my %basetaxes = ();
foreach my $t (qsearch({ table => 'cust_bill_pkg',
+ select => $select,
hashref => { pkgpart => 0 },
- addl_from => $join_cust,
+ addl_from => $addl_from,
extra_sql => $where,
})
)
{
- #warn $t->itemdesc. "\n";
+ my @params = map { my $f = $_; $f =~ s/.*\.//; $f } @taxparam;
+ my $label = join('~', map { $t->$_ } @params);
+ $label = 'Tax'. $label if $label =~ /^~/;
+ unless ( exists( $taxes{$label} ) ) {
+ my ($baselabel, @trash) = split /~/, $label;
- my $label = $t->itemdesc;
- $label ||= 'Tax';
- $taxes{$label}->{'label'} = $label;
- $taxes{$label}->{'url_param'} = "itemdesc=$label";
+ $taxes{$label}->{'label'} = join(', ', split(/~/, $label) );
+ $taxes{$label}->{'url_param'} =
+ join(';', map { "$_=". uri_escape($t->$_) } @params);
- # calculate total for this tax
- # calculate customer-exemption for this tax
- # calculate package-exemption for this tax
- # calculate monthly exemption (texas tax) for this tax
- # count up all the cust_tax_exempt_pkg records associated with
- # the actual line items.
-}
+ my $taxwhere = "FROM cust_bill_pkg $addl_from $where AND payby != 'COMP' ".
+ "AND ". join( ' AND ', map { "( $_ = ? OR ? = '' AND $_ IS NULL)" } @taxparam );
+ my $sql = "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) ".
+ " $taxwhere AND cust_bill_pkg.pkgnum = 0";
-foreach my $t (qsearch({ table => 'cust_bill_pkg',
- select => 'DISTINCT itemdesc',
- hashref => { pkgpart => 0 },
- addl_from => $join_cust,
- extra_sql => $where,
- })
- )
-{
+ my $x = scalar_sql($t, [ map { $_, $_ } @params ], $sql );
+ $tax += $x;
+ $taxes{$label}->{'tax'} += $x;
+
+ unless ( exists( $taxes{$baselabel} ) ) {
- my $label = $t->itemdesc;
- $label ||= 'Tax';
- my @taxparam = ( 'itemdesc' );
- my $taxwhere = "$from_join_cust $where AND payby != 'COMP' ".
- "AND itemdesc = ?" ;
+ $basetaxes{$baselabel}->{'label'} = $baselabel;
+ $basetaxes{$baselabel}->{'url_param'} = "itemdesc=$baselabel";
+ $basetaxes{$baselabel}->{'base'} = 1;
- my $sql = "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) ".
- " $taxwhere AND pkgnum = 0";
+ }
- my $x = scalar_sql($t, \@taxparam, $sql );
- $tax += $x;
- $taxes{$label}->{'tax'} += $x;
+ $basetaxes{$baselabel}->{'tax'} += $x;
+
+ }
+ # calculate customer-exemption for this tax
+ # calculate package-exemption for this tax
+ # calculate monthly exemption (texas tax) for this tax
+ # count up all the cust_tax_exempt_pkg records associated with
+ # the actual line items.
}
+
#ordering
-my @taxes =
- map $taxes{$_},
- sort { ($b cmp $a) }
- keys %taxes;
+my @taxes = ();
+
+foreach my $tax ( sort { $a cmp $b } keys %taxes ) {
+ my ($base, @trash) = split '~', $tax;
+ my $basetax = delete( $basetaxes{$base} );
+ if ($basetax) {
+ if ( $basetax->{tax} == $taxes{$tax}->{tax} ) {
+ $taxes{$tax}->{base} = 1;
+ } else {
+ push @taxes, $basetax;
+ }
+ }
+ push @taxes, $taxes{$tax};
+}
push @taxes, {
'label' => 'Total',
'url_param' => '',
'tax' => $tax,
+ 'base' => 1,
};
#--
@@ -143,7 +169,6 @@ push @taxes, {
#to FS::Report or FS::Record or who the fuck knows where)
sub scalar_sql {
my( $r, $param, $sql ) = @_;
- #warn "$sql\n";
my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute( map $r->$_(), @$param )
or die "Unexpected error executing statement $sql: ". $sth->errstr;
diff --git a/httemplate/search/report_prepaid_income.cgi b/httemplate/search/report_prepaid_income.cgi
index 27dbcbf..ce928b8 100644
--- a/httemplate/search/report_prepaid_income.cgi
+++ b/httemplate/search/report_prepaid_income.cgi
@@ -38,22 +38,46 @@ my $now = $cgi->param('date') && str2time($cgi->param('date')) || $time;
$now =~ /^(\d+)$/ or die "unparsable date?";
$now = $1;
+my @where = ();
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ my $agentnum = $1;
+ push @where, "agentnum = $agentnum";
+}
+
+#here is the agent virtualization
+push @where, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = join(' AND ', @where);
+$where = "AND $where" if $where;
+
my( $total, $total_legacy ) = ( 0, 0 );
my @cust_bill_pkg =
grep { $_->cust_pkg && $_->cust_pkg->part_pkg->freq !~ /^([01]|\d+[dw])$/ }
- qsearch( 'cust_bill_pkg', {
- 'recur' => { op=>'!=', value=>0 },
- 'edate' => { op=>'>', value=>$now },
- }, );
+ qsearch({
+ 'select' => 'cust_bill_pkg.*',
+ 'table' => 'cust_bill_pkg',
+ 'addl_from' => ' LEFT JOIN cust_bill USING ( invnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => {
+ 'recur' => { op=>'!=', value=>0 },
+ 'edate' => { op=>'>', value=>$now },
+ },
+ 'extra_sql' => $where,
+ });
my @cust_pkg =
grep { $_->part_pkg->recur != 0
&& $_->part_pkg->freq !~ /^([01]|\d+[dw])$/
}
- qsearch ( 'cust_pkg', {
- 'bill' => { op=>'>', value=>$now }
- } );
+ qsearch({
+ 'select' => 'cust_pkg.*',
+ 'table' => 'cust_pkg',
+ 'addl_from' => ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'bill' => { op=>'>', value=>$now } },
+ 'extra_sql' => $where,
+ });
foreach my $cust_bill_pkg ( @cust_bill_pkg) {
my $period = $cust_bill_pkg->edate - $cust_bill_pkg->sdate;
diff --git a/httemplate/search/report_prepaid_income.html b/httemplate/search/report_prepaid_income.html
index 81adb64..d707bd8 100644
--- a/httemplate/search/report_prepaid_income.html
+++ b/httemplate/search/report_prepaid_income.html
@@ -1,28 +1,46 @@
-<% include('/elements/header.html', 'Prepaid Income (Unearned Revenue) Report',
- '',
- '',
- '<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
- <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
- <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
- <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
- '
-) %>
-
- <FORM ACTION="report_prepaid_income.cgi" METHOD="GET">
- <TABLE>
- <TR>
- <TD>Prepaid income (unearned revenue) as of </TD>
- <TD>
- <INPUT TYPE="text" NAME="date" ID="date_text" VALUE="now">
- <IMG SRC="../images/calendar.png" ID="date_button" STYLE="cursor: pointer" TITLE="Select date">
- </TD>
- </TR>
- <TR>
- <TD>
- </TD>
- <TD><i>m/d/y</i></TD>
- </TR>
- </TABLE>
+<% include('/elements/header.html','Prepaid Income (Unearned Revenue) Report')%>
+
+<% include('/elements/init_calendar.html') %>
+
+<FORM ACTION="report_prepaid_income.cgi" METHOD="GET">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
+ <TR>
+ <TD>As of </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="date" ID="date_text" VALUE="now">
+ <IMG SRC="../images/calendar.png" ID="date_button" STYLE="cursor: pointer" TITLE="Select date">
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ </TD>
+ <TD><FONT SIZE="-1"><i>m/d/y</i></FONT></TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2>&nbsp;</TD>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <TR>
+ <TD COLSPAN=2>&nbsp;</TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center"><INPUT TYPE="submit" VALUE="Generate report"></TD>
+ </TR>
+
+</TABLE>
+
<SCRIPT TYPE="text/javascript">
Calendar.setup({
inputField: "date_text",
@@ -32,7 +50,7 @@
});
</SCRIPT>
-<INPUT TYPE="submit" VALUE="Generate report">
+</FORM>
<% include('/elements/footer.html') %>
<%init>
diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi
index 58d87fa..6df0161 100755
--- a/httemplate/search/report_receivables.cgi
+++ b/httemplate/search/report_receivables.cgi
@@ -1,159 +1,17 @@
-<% include( 'elements/search.html',
+<% include( 'elements/cust_main_dayranges.html',
'title' => 'Accounts Receivable Aging Summary',
- 'name' => 'customers',
- 'query' => $sql_query,
- 'count_query' => $count_sql,
- 'header' => [
- FS::UI::Web::cust_header(),
- '0-30',
- '30-60',
- '60-90',
- '90+',
- 'Total',
- ],
- 'footer' => [
- 'Total',
- ( map '',
- ( 1 ..
- scalar(FS::UI::Web::cust_header()-1)
- )
- ),
- sprintf( $money_char.'%.2f',
- $row->{'balance_0_30'} ),
- sprintf( $money_char.'%.2f',
- $row->{'balance_30_60'} ),
- sprintf( $money_char.'%.2f',
- $row->{'balance_60_90'} ),
- sprintf( $money_char.'%.2f',
- $row->{'balance_90_0'} ),
- sprintf( '<b>'. $money_char.'%.2f'. '</b>',
- $row->{'balance_0_0'} ),
- ],
- 'fields' => [
- \&FS::UI::Web::cust_fields,
- format_balance('0_30'),
- format_balance('30_60'),
- format_balance('60_90'),
- format_balance('90_0'),
- format_balance('0_0'),
- ],
- 'links' => [
- ( map { $_ ne 'Cust. Status' ? $clink : '' }
- FS::UI::Web::cust_header()
- ),
- '',
- '',
- '',
- '',
- '',
- ],
- #'align' => 'rlccrrrrr',
- 'align' => FS::UI::Web::cust_aligns(). 'rrrrr',
- #'size' => [ '', '', '-1', '-1', '', '', '', '', '', ],
- #'style' => [ '', '', 'b', 'b', '', '', '', '', 'b', ],
- 'size' => [ ( map '', FS::UI::Web::cust_header() ),
- #'-1', '', '', '', '', '', ],
- '', '', '', '', '', ],
- 'style' => [ FS::UI::Web::cust_styles(),
- #'b', '', '', '', '', 'b', ],
- '', '', '', '', 'b', ],
- 'color' => [
- FS::UI::Web::cust_colors(),
- '',
- '',
- '',
- '',
- '',
- ],
-
- )
+ 'range_sub' => \&balance,
+ )
%>
<%init>
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
-
-my @ranges = (
- [ 0, 30 ],
- [ 30, 60 ],
- [ 60, 90 ],
- [ 90, 0 ],
- [ 0, 0 ],
-);
-
-my $owed_cols = join(',', map balance( @$_ ), @ranges );
-
-my $select_count_pkgs = FS::cust_main->select_count_pkgs_sql;
-
-my $active_sql = FS::cust_pkg->active_sql;
-my $inactive_sql = FS::cust_pkg->inactive_sql;
-my $suspended_sql = FS::cust_pkg->suspended_sql;
-my $cancelled_sql = FS::cust_pkg->cancelled_sql;
-
-my $packages_cols = <<END;
- ( $select_count_pkgs ) AS num_pkgs_sql,
- ( $select_count_pkgs AND $active_sql ) AS active_pkgs,
- ( $select_count_pkgs AND $inactive_sql ) AS inactive_pkgs,
- ( $select_count_pkgs AND $suspended_sql ) AS suspended_pkgs,
- ( $select_count_pkgs AND $cancelled_sql ) AS cancelled_pkgs
-END
-
-my @where = ();
-
-unless ( $cgi->param('all_customers') ) {
-
- my $days = 0;
- if ( $cgi->param('days') =~ /^\s*(\d+)\s*$/ ) {
- $days = $1;
- }
-
- push @where, balance($days, 0, 'no_as'=>1). ' > 0'; # != 0';
-
-}
-
-if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
- my $agentnum = $1;
- push @where, "agentnum = $agentnum";
-}
-
-#here is the agent virtualization
-push @where, $FS::CurrentUser::CurrentUser->agentnums_sql;
-
-my $where = join(' AND ', @where);
-$where = "WHERE $where" if $where;
-
-my $count_sql = "select count(*) from cust_main $where";
-
-my $sql_query = {
- 'table' => 'cust_main',
- 'hashref' => {},
- 'select' => join(',',
- #'cust_main.*',
- 'custnum',
- $owed_cols,
- $packages_cols,
- FS::UI::Web::cust_sql_fields(),
- ),
- 'extra_sql' => $where,
- 'order_by' => "order by coalesce(lower(company), ''), lower(last)",
-};
-
-my $total_sql = "SELECT ". join(',', map balance( @$_, 'sum'=>1 ), @ranges).
- " FROM cust_main $where";
-
-my $total_sth = dbh->prepare($total_sql) or die dbh->errstr;
-$total_sth->execute or die "error executing $total_sql: ". $total_sth->errstr;
-my $row = $total_sth->fetchrow_hashref();
-
-my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+ unless $FS::CurrentUser::CurrentUser->access_right('Receivables report')
+ or $FS::CurrentUser::CurrentUser->access_right('Financial reports');
</%init>
<%once>
-my $conf = new FS::Conf;
-
-my $money_char = $conf->config('money_char') || '$';
-
#Example:
#
# my $balance = balance(
@@ -170,9 +28,7 @@ my $money_char = $conf->config('money_char') || '$';
# )
sub balance {
- my($start, $end, %opt) = @_;
-
- my $as = $opt{'no_as'} ? '' : " AS balance_${start}_$end";
+ my($start, $end) = @_; #, %opt ?
#handle start and end ranges (86400 = 24h * 60m * 60s)
my $str2time = str2time_sql;
@@ -180,18 +36,10 @@ sub balance {
$start = $start ? "( $str2time now() $closing - ".($start * 86400). ' )' : '';
$end = $end ? "( $str2time now() $closing - ".($end * 86400). ' )' : '';
- $opt{'unapplied_date'} = 1;
-
- ( $opt{sum} ? 'SUM( ' : '' ).
- FS::cust_main->balance_date_sql( $start, $end, %opt ).
- ( $opt{sum} ? ' )' : '' ).
- $as;
+ #$opt{'unapplied_date'} = 1;
-}
+ FS::cust_main->balance_date_sql( $start, $end, 'unapplied_date'=>1,);
-sub format_balance { #closures help alot
- my $range = shift;
- sub { sprintf( $money_char.'%.2f', shift->get("balance_$range") ) };
}
</%once>
diff --git a/httemplate/search/report_receivables.html b/httemplate/search/report_receivables.html
index 19b1ee7..bfb0169 100755
--- a/httemplate/search/report_receivables.html
+++ b/httemplate/search/report_receivables.html
@@ -11,6 +11,11 @@
</TR>
<% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <% include( '/elements/tr-select-cust_main-status.html',
+ 'label' => 'Customer Status'
+ )
+ %>
<TR>
<TD ALIGN="right">Customers</TD>
@@ -30,6 +35,7 @@
<%init>
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+ unless $FS::CurrentUser::CurrentUser->access_right('Receivables report')
+ or $FS::CurrentUser::CurrentUser->access_right('Financial reports');
</%init>
diff --git a/httemplate/search/report_svc_phone.html b/httemplate/search/report_svc_phone.html
new file mode 100644
index 0000000..2d64340
--- /dev/null
+++ b/httemplate/search/report_svc_phone.html
@@ -0,0 +1,32 @@
+<% include('/elements/header.html', 'Phone number total usage' ) %>
+
+<FORM ACTION="svc_phone.cgi" METHOD="GET">
+
+<INPUT TYPE="hidden" NAME="magic" VALUE="all">
+<INPUT TYPE="hidden" NAME="usage_total" VALUE="1">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+%# <TR>
+%# <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+%# <FONT SIZE="+1">Search options</FONT>
+%# </TH>
+%# </TR>
+
+ <% include ( '/elements/tr-input-beginning_ending.html', prefix=>'usage' ) %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Search phone numbers">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+#? 'List services' ? something new?
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+</%init>
diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi
index a7630dd..e89c665 100755
--- a/httemplate/search/report_tax.cgi
+++ b/httemplate/search/report_tax.cgi
@@ -1,4 +1,4 @@
-<% include("/elements/header.html", "$agentname Sales Tax Report - ".
+<% include("/elements/header.html", "$agentname Tax Report - ".
( $beginning
? time2str('%h %o %Y ', $beginning )
: ''
@@ -44,12 +44,11 @@
% foreach my $region ( @regions ) {
%
% my $link = '';
-% if ( $region->{'label'} ne 'Total' ) {
-% if ( $region->{'label'} eq $out ) {
-% $link = ';out=1';
-% } else {
-% $link = ';'. $region->{'url_param'};
-% }
+% if ( $region->{'label'} eq $out ) {
+% $link = ';out=1';
+% } else {
+% $link = ';'. $region->{'url_param'}
+% if $region->{'url_param'};
% }
%
% if ( $bgcolor eq $bgcolor1 ) {
@@ -111,8 +110,12 @@
</TD>
% unless ( $cgi->param('show_taxclasses') ) {
+% my $invlink = $region->{'url_param_inv'}
+% ? ';'. $region->{'url_param_inv'}
+% : $link;
+
<<%$tdh%> ALIGN="right">
- <A HREF="<% $baselink. $link %>;istax=1"
+ <A HREF="<% $baselink. $invlink %>;istax=1"
><% &$money_sprintf( $region->{'tax'} ) %></A>
</TD>
% }
@@ -138,13 +141,12 @@
% foreach my $region ( @base_regions ) {
%
% my $link = '';
-% #if ( $region->{'label'} ne 'Total' ) {
-% if ( $region->{'label'} eq $out ) {
-% $link = ';out=1';
-% } else {
-% $link = ';'. $region->{'url_param'};
-% }
-% #}
+% if ( $region->{'label'} eq $out ) {
+% $link = ';out=1';
+% } else {
+% $link = ';'. $region->{'url_param'}
+% if $region->{'url_param'};
+% }
%
% if ( $bgcolor eq $bgcolor1 ) {
% $bgcolor = $bgcolor2;
@@ -174,7 +176,7 @@
<<%$td%>>Total</TD>
<<%$td%> ALIGN="right">
<A HREF="<% $baselink %>;istax=1"
- ><% &$money_sprintf( $tax ) %></A>
+ ><% &$money_sprintf( $tot_tax ) %></A>
</TD>
</TR>
@@ -275,8 +277,6 @@ if ( $conf->exists('tax-pkg_address') ) {
"WHERE 0 < ( SELECT COUNT(*) FROM cust_main WHERE $gotcust LIMIT 1 )";
}
-my($total, $tot_taxable, $owed, $tax) = ( 0, 0, 0, 0 );
-my( $exempt_cust, $exempt_pkg, $exempt_monthly ) = ( 0, 0, 0 );
my $out = 'Out of taxable region(s)';
my %regions = ();
@@ -289,6 +289,9 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
my $label = getlabel($r);
$regions{$label}->{'label'} = $label;
+
+ $regions{$label}->{$_} = $r->$_() for (qw( county state country )); #taxname?
+
$regions{$label}->{'url_param'} =
join(';', map "$_=".uri_escape($r->$_()),
qw( county state country taxname )
@@ -304,6 +307,8 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
$regions{$label}->{'url_param'} .= ';taxclass='. uri_escape($r->taxclass);
#no, always# if $cgi->param('show_taxclasses');
+ $regions{$label}->{'taxclass'} = $r->taxclass;
+
} else {
$regions{$label}->{'url_param'} .= ';taxclassNULL=1'
@@ -326,10 +331,9 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
my $t_sql =
"SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) $fromwhere AND $nottax";
my $t = scalar_sql($r, \@param, $t_sql);
- $total += $t;
$regions{$label}->{'total'} += $t;
- #if ( $label eq $out ) {# && $t ) {
+ #if ( $label eq $out ) # && $t ) {
# warn "adding $t for ".
# join('/', map $r->$_, qw( taxclass county state country ) ). "\n";
# #warn $t_sql if $r->state eq 'FL';
@@ -351,12 +355,27 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
# );
# }
+ #false laziness -ish w/report_tax.cgi
+ my $cust_exempt;
+ if ( $r->taxname ) {
+ my $q_taxname = dbh->quote($r->taxname);
+ $cust_exempt =
+ "( tax = 'Y'
+ OR EXISTS ( SELECT 1 FROM cust_main_exemption
+ WHERE cust_main_exemption.custnum = cust_main.custnum
+ AND cust_main_exemption.taxname = $q_taxname
+ )
+ )
+ ";
+ } else {
+ $cust_exempt = " tax = 'Y' ";
+ }
+
my $x_cust = scalar_sql($r, \@param,
"SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur)
- $fromwhere AND $nottax AND tax = 'Y' "
+ $fromwhere AND $nottax AND $cust_exempt "
);
- $exempt_cust += $x_cust;
$regions{$label}->{'exempt_cust'} += $x_cust;
## calculate package-exemption for this region
@@ -384,7 +403,6 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
AND ( tax != 'Y' OR tax IS NULL )
"
);
- $exempt_pkg += $x_pkg;
$regions{$label}->{'exempt_pkg'} += $x_pkg;
## calculate monthly exemption (texas tax) for this region
@@ -399,20 +417,11 @@ foreach my $r ( qsearch({ 'table' => 'cust_main_county',
$join_cust_pkg
$mywhere"
);
-# if ( $x_monthly ) {
-# #warn $r->taxnum(). ": $x_monthly\n";
-# $taxable -= $x_monthly;
-# }
-
- $exempt_monthly += $x_monthly;
$regions{$label}->{'exempt_monthly'} += $x_monthly;
my $taxable = $t - $x_cust - $x_pkg - $x_monthly;
-
- $tot_taxable += $taxable;
$regions{$label}->{'taxable'} += $taxable;
- $owed += $taxable * ($r->tax/100);
$regions{$label}->{'owed'} += $taxable * ($r->tax/100);
if ( defined($regions{$label}->{'rate'})
@@ -474,20 +483,43 @@ my $_taxamount_sub = sub {
scalar_sql($r, \@taxparam, $sql );
};
+#tax-report_groups filtering
+my($group_op, $group_value) = ( '', '' );
+if ( $cgi->param('report_group') =~ /^(=|!=) (.*)$/ ) {
+ ( $group_op, $group_value ) = ( $1, $2 );
+}
+my $group_test = sub {
+ my $label = shift;
+ return 1 unless $group_op; #in case we get called inadvertantly
+ if ( $label eq $out ) { #don't display "out of taxable region" in this case
+ 0;
+ } elsif ( $group_op eq '=' ) {
+ $label =~ /^$group_value/;
+ } elsif ( $group_op eq '!=' ) {
+ $label !~ /^$group_value/;
+ } else {
+ die "guru meditation #00de: group_op $group_op\n";
+ }
+};
+
+my $tot_tax = 0;
#foreach my $label ( keys %regions ) {
foreach my $r ( qsearch(\%qsearch) ) {
#warn join('-', map { $r->$_() } qw( country state county taxname ) )."\n";
my $label = getlabel($r);
+ if ( $group_op ) {
+ next unless &{$group_test}($label);
+ }
#my $fromwhere = $join_pkg. $where. " AND payby != 'COMP' ";
#my @param = @base_param;
my $x = &{$_taxamount_sub}($r);
- $tax += $x unless $cgi->param('show_taxclasses');
$regions{$label}->{'tax'} += $x;
+ $tot_tax += $x unless $cgi->param('show_taxclasses');
}
@@ -508,34 +540,86 @@ if ( $cgi->param('show_taxclasses') ) {
);
$base_regions{$base_label}->{'tax'} += $x;
- $tax += $x;
+ $tot_tax += $x;
}
}
+my @regions = keys %regions;
+
+#tax-report_groups filtering
+@regions = grep &{$group_test}($_), @regions
+ if $group_op;
+
+#calculate totals
+my( $total, $tot_taxable, $tot_owed ) = ( 0, 0, 0 );
+my( $exempt_cust, $exempt_pkg, $exempt_monthly ) = ( 0, 0, 0 );
+my %taxclasses = ();
+my %county = ();
+my %state = ();
+my %country = ();
+foreach (@regions) {
+ $total += $regions{$_}->{'total'};
+ $tot_taxable += $regions{$_}->{'taxable'};
+ $tot_owed += $regions{$_}->{'owed'};
+ $exempt_cust += $regions{$_}->{'exempt_cust'};
+ $exempt_pkg += $regions{$_}->{'exempt_pkg'};
+ $exempt_monthly += $regions{$_}->{'exempt_monthly'};
+ $taxclasses{$regions{$_}->{'taxclass'}} = 1
+ if $regions{$_}->{'taxclass'};
+ $county{$regions{$_}->{'county'}} = 1;
+ $state{$regions{$_}->{'state'}} = 1;
+ $country{$regions{$_}->{'country'}} = 1;
+}
+
+my $total_url_param = '';
+my $total_url_param_invoiced = '';
+if ( $group_op ) {
+
+ my @country = keys %country;
+ warn "WARNING: multiple countries on this grouped report; total links broken"
+ if scalar(@country) > 1;
+ my $country = $country[0];
+
+ my @state = keys %state;
+ warn "WARNING: multiple countries on this grouped report; total links broken"
+ if scalar(@state) > 1;
+ my $state = $state[0];
+
+ $total_url_param_invoiced =
+ $total_url_param =
+ 'report_group='.uri_escape("$group_op $group_value").';'.
+ join(';', map 'taxclass='.uri_escape($_), keys %taxclasses );
+ $total_url_param .= ';'.
+ "country=$country;state=".uri_escape($state).';'.
+ join(';', map 'county='.uri_escape($_), keys %county ) ;
+
+}
#ordering
-my @regions =
+@regions =
map $regions{$_},
sort { ( ($a eq $out) cmp ($b eq $out) ) || ($b cmp $a) }
- keys %regions;
+ @regions;
my @base_regions =
map $base_regions{$_},
sort { ( ($a eq $out) cmp ($b eq $out) ) || ($b cmp $a) }
keys %base_regions;
+#add total line
push @regions, {
'label' => 'Total',
- 'url_param' => '',
+ 'url_param' => $total_url_param,
+ 'url_param_inv' => $total_url_param_invoiced,
'total' => $total,
'exempt_cust' => $exempt_cust,
'exempt_pkg' => $exempt_pkg,
'exempt_monthly' => $exempt_monthly,
'taxable' => $tot_taxable,
'rate' => '',
- 'owed' => $owed,
- 'tax' => $tax,
+ 'owed' => $tot_owed,
+ 'tax' => $tot_tax,
};
#--
diff --git a/httemplate/search/report_tax.html b/httemplate/search/report_tax.html
index e5ffa9a..217f481 100755
--- a/httemplate/search/report_tax.html
+++ b/httemplate/search/report_tax.html
@@ -4,29 +4,49 @@
<TABLE>
+% if ( $conf->config('tax-report_groups') ) {
+% my @lines = $conf->config('tax-report_groups');
+
+ <TR>
+ <TD ALIGN="right">Tax group</TD>
+ <TD>
+ <SELECT NAME="report_group">
+
+ <OPTION VALUE="">all</OPTION>
+
+% foreach my $line ( @lines ) {
+% $line =~ /^\s*(.+)\s+(=|!=)\s+(.*)\s*$/ #or next;
+% or do { warn "bad report_group line: $line\n"; next; };
+% my($label, $op, $value) = ($1, $2, $3);
+
+ <OPTION VALUE="<% "$op $value" %>"><% $label %></OPTION>
+% }
+
+ </SELECT>
+ </TD>
+ </TR>
+
+% }
+
<% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
<% include( '/elements/tr-input-beginning_ending.html' ) %>
-% my $conf = new FS::Conf;
-% if ( $conf->exists('enable_taxclasses') ) {
-%
+% if ( $conf->exists('enable_taxclasses') ) {
<TR>
<TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_taxclasses" VALUE="1"></TD>
<TD>Show tax classes</TD>
</TR>
% }
-% my @pkg_class = qsearch('pkg_class', {});
-% if ( @pkg_class ) {
-%
+% my @pkg_class = qsearch('pkg_class', {});
+% if ( @pkg_class ) {
<TR>
<TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_pkgclasses" VALUE="1"></TD>
<TD>Show package classes</TD>
</TR>
% }
-
</TABLE>
<BR><INPUT TYPE="submit" VALUE="Get Report">
@@ -39,4 +59,6 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+my $conf = new FS::Conf;
+
</%init>
diff --git a/httemplate/search/report_unapplied_cust_pay.html b/httemplate/search/report_unapplied_cust_pay.html
new file mode 100755
index 0000000..10093e5
--- /dev/null
+++ b/httemplate/search/report_unapplied_cust_pay.html
@@ -0,0 +1,41 @@
+<% include('/elements/header.html', 'Unapplied Payments Aging Summary' ) %>
+%# 'Prepaid Balance Aging Summary', #???
+
+<FORM NAME="OneTrueForm" ACTION="unapplied_cust_pay.html" METHOD="GET">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <% include( '/elements/tr-select-cust_main-status.html',
+ 'label' => 'Customer Status'
+ )
+ %>
+
+ <TR>
+ <TD ALIGN="right">Customers</TD>
+ <TD>
+ <INPUT TYPE="radio" NAME="all_customers" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.days.disabled=true; document.OneTrueForm.days.style.backgroundColor = '#dddddd'; } else { document.OneTrueForm.days.disabled=false; document.OneTrueForm.days.style.backgroundColor = '#ffffff'; }">All customers (even those without unapplied payments)<BR>
+ <INPUT TYPE="radio" NAME="all_customers" VALUE="0" CHECKED onClick="if ( ! this.checked ) { document.OneTrueForm.days.disabled=true; document.OneTrueForm.days.style.backgroundColor = '#dddddd'; } else { document.OneTrueForm.days.disabled=false; document.OneTrueForm.days.style.backgroundColor = '#ffffff'; }">Customers with unapplied payments over <INPUT NAME="days" TYPE="text" SIZE=4 MAXLENGTH=3 VALUE="0"> days old
+ </TD>
+ </TR>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Get Report">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/svc_broadband.cgi b/httemplate/search/svc_broadband.cgi
index 2cb0c1e..d0b1029 100755
--- a/httemplate/search/svc_broadband.cgi
+++ b/httemplate/search/svc_broadband.cgi
@@ -111,13 +111,13 @@ foreach my $router (qsearch('router', {})) {
}
}
-my $link = [ $p.'view/svc_broadband.cgi', 'svcnum' ];
+my $link = [ $p.'view/svc_broadband.cgi?', 'svcnum' ];
#XXX get the router link working
my $link_router = sub { my $routernum = $routerbyblock{shift->blocknum}->routernum;
[ $p.'view/router.cgi?'.$routernum, 'routernum' ];
};
-my $link_cust = [ $p.'view/cust_main.cgi', 'custnum' ];
+my $link_cust = [ $p.'view/cust_main.cgi?', 'custnum' ];
</%init>
diff --git a/httemplate/search/svc_external.cgi b/httemplate/search/svc_external.cgi
index 2710d75..f061754 100755
--- a/httemplate/search/svc_external.cgi
+++ b/httemplate/search/svc_external.cgi
@@ -1,153 +1,135 @@
-%die "access denied"
-% unless $FS::CurrentUser::CurrentUser->access_right('List services');
-%
-%my $conf = new FS::Conf;
-%
-%my @svc_external = ();
-%my @h_svc_external = ();
-%my $sortby=\*svcnum_sort;
-%if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
-%
-% @svc_external=qsearch('svc_external',{});
-%
-% if ( $cgi->param('magic') eq 'unlinked' ) {
-% @svc_external = grep { qsearchs('cust_svc', {
-% 'svcnum' => $_->svcnum,
-% 'pkgnum' => '',
-% }
-% )
-% }
-% @svc_external;
-% }
-%
-% if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
-% my $sortby = $1;
-% if ( $sortby eq 'id' ) {
-% $sortby = \*id_sort;
-% }
-% }
-%
-%} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
-%
-% @svc_external =
-% qsearch( 'svc_external', {}, '',
-% " WHERE $1 = ( SELECT svcpart FROM cust_svc ".
-% " WHERE cust_svc.svcnum = svc_external.svcnum ) "
-% );
-%
-%} elsif ( $cgi->param('title') =~ /^(.*)$/ ) {
-% $sortby=\*id_sort;
-% @svc_external=qsearch('svc_external',{ title => $1 });
-% if( $cgi->param('history') == 1 ) {
-% @h_svc_external=qsearch('h_svc_external',{ title => $1 });
-% }
-%} elsif ( $cgi->param('id') =~ /^([\w\-\.]+)$/ ) {
-% my $id = $1;
-% @svc_external = qsearchs('svc_external',{'id'=>$id});
-%}
-%
-%if ( scalar(@svc_external) == 1 ) {
-%
-%
-<% $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum) %>
-%
-%
-%} elsif ( scalar(@svc_external) == 0 ) {
-%
-%
-<% include('/elements/header.html', 'External Search Results' ) %>
-
- No matching external services found
-% } else {
-%
-%
-<% include('/elements/header.html', 'External Search Results', '') %>
-
- <% scalar(@svc_external) %> matching external services found
- <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
- <TR>
- <TH>Service #</TH>
- <TH><% FS::Msgcat::_gettext('svc_external-id') || 'External&nbsp;ID' %></TH>
- <TH><% FS::Msgcat::_gettext('svc_external-title') || 'Title' %></TH>
- </TR>
-%
-% foreach my $svc_external (
-% sort $sortby (@svc_external)
-% ) {
-% my($svcnum, $id, $title)=(
-% $svc_external->svcnum,
-% $svc_external->id,
-% $svc_external->title,
-% );
-%
-% my $rowspan = 1;
-%
-% print <<END;
-% <TR>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$svcnum</A></TD>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$id</A></TD>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$title</A></TD>
-%END
-%
-% #print @rows;
-% print "</TR>";
-%
-% }
-% if( scalar(@h_svc_external) > 0 ) {
-% print <<HTML;
-% </TABLE>
-% <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
-% <TR>
-% <TH>Freeside ID</TH>
-% <TH>Service #</TH>
-% <TH>Title</TH>
-% <TH>Date</TH>
-% </TR>
-%HTML
-%
-% foreach my $h_svc ( @h_svc_external ) {
-% my($svcnum, $id, $title, $user, $date)=(
-% $h_svc->svcnum,
-% $h_svc->id,
-% $h_svc->title,
-% $h_svc->history_user,
-% $h_svc->history_date,
-% );
-% my $rowspan = 1;
-% my ($h_cust_svc) = qsearchs( 'h_cust_svc', {
-% svcnum => $svcnum,
-% });
-% my $cust_pkg = qsearchs( 'cust_pkg', {
-% pkgnum => $h_cust_svc->pkgnum,
-% });
-% my $custnum = $cust_pkg->custnum;
-%
-% print <<END;
-% <TR>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$custnum</A></TD>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$svcnum</A></TD>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$title</A></TD>
-% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$date</A></TD>
-% </TR>
-%END
-% }
-% }
-%
-% print <<END;
-% </TABLE>
-% </BODY>
-%</HTML>
-%END
-%
-%}
-%
-%sub svcnum_sort {
-% $a->getfield('svcnum') <=> $b->getfield('svcnum');
-%}
-%
-%sub id_sort {
-% $a->getfield('id') <=> $b->getfield('id');
-%}
-%
-%
+<% include( 'elements/search.html',
+ 'title' => 'External service search results',
+ 'name' => 'external services',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $redirect,
+ 'header' => [ '#',
+ 'Service',
+ ( FS::Msgcat::_gettext('svc_external-id') || 'External ID' ),
+ ( FS::Msgcat::_gettext('svc_external-title') || 'Title' ),
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ 'id',
+ 'title',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rlrr'.
+ FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $conf = new FS::Conf;
+
+my %svc_external;
+my @extra_sql = ();
+my $orderby = 'ORDER BY svcnum';
+
+my $link = [ "${p}view/svc_external.cgi?", 'svcnum' ];
+my $redirect = $link;
+
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+
+ push @extra_sql, "svcpart = $1";
+
+} elsif ( $cgi->param('title') =~ /^(.*)$/ ) {
+
+ $svc_external{'title'} = $1;
+ $orderby = 'ORDER BY id';
+
+ # is this linked from anywhere???
+ # if( $cgi->param('history') == 1 ) {
+ # @h_svc_external=qsearch('h_svc_external',{ title => $1 });
+ # }
+
+} elsif ( $cgi->param('id') =~ /^([\w\-\.]+)$/ ) {
+
+ $svc_external{'id'} = $1;
+
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql = '';
+if ( @extra_sql ) {
+ $extra_sql = ( keys(%svc_external) ? ' AND ' : ' WHERE ' ).
+ join(' AND ', @extra_sql );
+}
+
+my $count_query = "SELECT COUNT(*) FROM svc_external $addl_from ";
+if ( keys %svc_external ) {
+ $count_query .= ' WHERE '.
+ join(' AND ', map "$_ = ". dbh->quote($svc_external{$_}),
+ keys %svc_external
+ );
+}
+$count_query .= $extra_sql;
+
+my $sql_query = {
+ 'table' => 'svc_external',
+ 'hashref' => \%svc_external,
+ 'select' => join(', ',
+ 'svc_external.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+#smaller false laziness w/svc_*.cgi here
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+
+</%init>
diff --git a/httemplate/search/svc_phone.cgi b/httemplate/search/svc_phone.cgi
index 49340c6..21e1a92 100644
--- a/httemplate/search/svc_phone.cgi
+++ b/httemplate/search/svc_phone.cgi
@@ -3,33 +3,39 @@
'name' => 'phone numbers',
'query' => $sql_query,
'count_query' => $count_query,
- 'redirect' => $link,
+ 'redirect' => $redirect,
'header' => [ '#',
'Service',
'Country code',
'Phone number',
+ @header,
FS::UI::Web::cust_header(),
],
'fields' => [ 'svcnum',
'svc',
'countrycode',
'phonenum',
+ @fields,
\&FS::UI::Web::cust_fields,
],
'links' => [ $link,
$link,
$link,
$link,
+ ( map '', @header ),
( map { $_ ne 'Cust. Status' ? $link_cust : '' }
FS::UI::Web::cust_header()
),
],
- 'align' => 'rlrr'. FS::UI::Web::cust_aligns(),
+ 'align' => 'rlrr'.
+ join('', map 'r', @header).
+ FS::UI::Web::cust_aligns(),
'color' => [
'',
'',
'',
'',
+ ( map '', @header ),
FS::UI::Web::cust_colors(),
],
'style' => [
@@ -37,6 +43,7 @@
'',
'',
'',
+ ( map '', @header ),
FS::UI::Web::cust_styles(),
],
)
@@ -48,9 +55,16 @@ die "access denied"
my $conf = new FS::Conf;
-my $orderby = 'ORDER BY svcnum';
+my @select = ();
my %svc_phone = ();
my @extra_sql = ();
+my $orderby = 'ORDER BY svcnum';
+
+my @header = ();
+my @fields = ();
+my $link = [ "${p}view/svc_phone.cgi?", 'svcnum' ];
+my $redirect = $link;
+
if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
push @extra_sql, 'pkgnum IS NULL'
@@ -61,6 +75,50 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
$orderby = "ORDER BY $sortby";
}
+ if ( $cgi->param('usage_total') ) {
+
+ my($beginning,$ending) = FS::UI::Web::parse_beginning_ending($cgi, 'usage');
+
+ $redirect = '';
+
+ #my $and_date = " AND startdate >= $beginning AND startdate <= $ending ";
+ my $and_date = " AND enddate >= $beginning AND enddate <= $ending ";
+
+ my $fromwhere = " FROM cdr WHERE cdr.svcnum = svc_phone.svcnum $and_date";
+
+ #more efficient to join against cdr just once... this will do for now
+ push @select, map { " ( SELECT SUM($_) $fromwhere ) AS $_ " }
+ qw( billsec rated_price );
+
+ my $money_char = $conf->config('money_char') || '$';
+
+ push @header, 'Minutes', 'Billed';
+ push @fields,
+ sub { sprintf('%.3f', shift->get('billsec') / 60 ); },
+ sub { $money_char. sprintf('%.2f', shift->get('rated_price') ); };
+
+ #XXX and termination... (this needs a config to turn on, not by default)
+ if ( 1 ) { # $conf->exists('cdr-termination_hack') { #}
+
+ my $f_w =
+ " FROM cdr_termination LEFT JOIN cdr USING ( acctid ) ".
+ " WHERE cdr.acctid = svc_phone.phonenum ". # XXX connectone-specific
+ $and_date;
+
+ push @select,
+ " ( SELECT SUM(billsec) $f_w ) AS term_billsec ",
+ " ( SELECT SUM(cdr_termination.rated_price) $f_w ) AS term_rated_price";
+
+ push @header, 'Term Min', 'Term Billed';
+ push @fields,
+ sub { sprintf('%.3f', shift->get('term_billsec') / 60 ); },
+ sub { $money_char. sprintf('%.2f', shift->get('rated_price') ); };
+
+ }
+
+
+ }
+
} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
push @extra_sql, "svcpart = $1";
} else {
@@ -99,15 +157,14 @@ my $sql_query = {
'select' => join(', ',
'svc_phone.*',
'part_svc.svc',
- 'cust_main.custnum',
- FS::UI::Web::cust_sql_fields(),
+ @select,
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
),
'extra_sql' => "$extra_sql $orderby",
'addl_from' => $addl_from,
};
-my $link = [ "${p}view/svc_phone.cgi?", 'svcnum' ];
-
#smaller false laziness w/svc_*.cgi here
my $link_cust = sub {
my $svc_x = shift;
diff --git a/httemplate/search/unapplied_cust_pay.html b/httemplate/search/unapplied_cust_pay.html
new file mode 100755
index 0000000..8d064d1
--- /dev/null
+++ b/httemplate/search/unapplied_cust_pay.html
@@ -0,0 +1,28 @@
+<% include( 'elements/cust_main_dayranges.html',
+ #'title' => 'Prepaid Balance Aging Summary', #???
+ 'title' => 'Unapplied Payments Aging Summary',
+ 'range_sub' => \&unapplied_payments,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
+<%once>
+
+sub unapplied_payments {
+ my($start, $end, %opt) = @_;
+
+ #handle start and end ranges (86400 = 24h * 60m * 60s)
+ my $str2time = str2time_sql;
+ my $closing = str2time_sql_closing;
+ $start = $start ? "( $str2time now() $closing - ".($start * 86400). ' )' : '';
+ $end = $end ? "( $str2time now() $closing - ".($end * 86400). ' )' : '';
+
+ FS::cust_main->unapplied_payments_date_sql( $start, $end );
+
+}
+
+</%once>
diff --git a/httemplate/view/attachment.html b/httemplate/view/attachment.html
new file mode 100644
index 0000000..5fc0539
--- /dev/null
+++ b/httemplate/view/attachment.html
@@ -0,0 +1,16 @@
+<% $attach->body %>
+<%init>
+my ($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $attachnum = $1 or die 'Invalid attachment number';
+$FS::CurrentUser::CurrentUser->access_right('Download attachment') or die 'access denied';
+
+my $attach = qsearchs('cust_attachment', { attachnum => $attachnum }) or die "Attachment not found: $attachnum";
+die 'access denied' if $attach->disabled;
+
+$m->clear_buffer;
+$r->content_type($attach->mime_type || 'text/plain');
+$r->headers_out->add('Content-Disposition' => 'attachment;filename=' . $attach->filename);
+
+
+</%init>
diff --git a/httemplate/view/cust_bill-logo.cgi b/httemplate/view/cust_bill-logo.cgi
index 09ac9a7..ad2ff54 100755
--- a/httemplate/view/cust_bill-logo.cgi
+++ b/httemplate/view/cust_bill-logo.cgi
@@ -10,7 +10,7 @@ my $conf = new FS::Conf;
my $templatename;
my $agentnum = '';
if ( $cgi->param('invnum') ) {
- $templatename = $cgi->param('templatename');
+ $templatename = $cgi->param('template') || $cgi->param('templatename');
my $cust_bill = qsearchs('cust_bill', { 'invnum' => $cgi->param('invnum') } )
or die 'unknown invnum';
$agentnum = $cust_bill->cust_main->agentnum;
diff --git a/httemplate/view/cust_bill-pdf.cgi b/httemplate/view/cust_bill-pdf.cgi
index f09e1b7..51e47e0 100755
--- a/httemplate/view/cust_bill-pdf.cgi
+++ b/httemplate/view/cust_bill-pdf.cgi
@@ -4,11 +4,23 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
-#untaint invnum
+my( $invnum, $template, $notice_name );
my($query) = $cgi->keywords;
-$query =~ /^((.+)-)?(\d+)(.pdf)?$/;
-my $templatename = $2;
-my $invnum = $3;
+if ( $query =~ /^((.+)-)?(\d+)(.pdf)?$/ ) {
+ $template = $2;
+ $invnum = $3;
+ $notice_name = 'Invoice';
+} else {
+ $invnum = $cgi->param('invnum');
+ $invnum =~ s/\.pdf//i;
+ $template = $cgi->param('template');
+ $notice_name = ( $cgi->param('notice_name') || 'Invoice' );
+}
+
+my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+);
my $cust_bill = qsearchs({
'select' => 'cust_bill.*',
@@ -19,7 +31,7 @@ my $cust_bill = qsearchs({
});
die "Invoice #$invnum not found!" unless $cust_bill;
-my $pdf = $cust_bill->print_pdf( '', $templatename);
+my $pdf = $cust_bill->print_pdf(\%opt);
http_header('Content-Type' => 'application/pdf' );
http_header('Content-Length' => length($pdf) );
diff --git a/httemplate/view/cust_bill-ps.cgi b/httemplate/view/cust_bill-ps.cgi
index 5313dbf..881491f 100755
--- a/httemplate/view/cust_bill-ps.cgi
+++ b/httemplate/view/cust_bill-ps.cgi
@@ -1,14 +1,25 @@
-<% $cust_bill->print_ps( '', $templatename) %>
+<% $cust_bill->print_ps(\%opt) %>
<%init>
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
-#untaint invnum
+my( $invnum, $template, $notice_name );
my($query) = $cgi->keywords;
-$query =~ /^((.+)-)?(\d+)$/;
-my $templatename = $2;
-my $invnum = $3;
+if ( $query =~ /^((.+)-)?(\d+)(.pdf)?$/ ) {
+ $template = $2;
+ $invnum = $3;
+ $notice_name = 'Invoice';
+} else {
+ $invnum = $cgi->param('invnum');
+ $template = $cgi->param('template');
+ $notice_name = ( $cgi->param('notice_name') || 'Invoice' );
+}
+
+my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+);
my $cust_bill = qsearchs({
'select' => 'cust_bill.*',
diff --git a/httemplate/view/cust_bill.cgi b/httemplate/view/cust_bill.cgi
index 450c74e..ce8d96a 100755
--- a/httemplate/view/cust_bill.cgi
+++ b/httemplate/view/cust_bill.cgi
@@ -2,10 +2,32 @@
"View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
)) %>
+% if ( $conf->exists('deleteinvoices')
+% && $curuser->access_right('Delete invoices' )
+% )
+% {
+
+ <SCRIPT TYPE="text/javascript">
+ function areyousure(href, message) {
+ if (confirm(message) == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+ <A HREF = "javascript:areyousure(
+ '<%$p%>misc/delete-cust_bill.html?<% $invnum %>',
+ 'Are you sure you want to delete this invoice?'
+ )"
+ TITLE = "Delete this invoice from the database completely"
+ >Delete this invoice</A>
+ <BR><BR>
+
+% }
% if ( $cust_bill->owed > 0
% && scalar( grep $payby{$_}, qw(BILL CASH WEST MCRD) )
-% && $FS::CurrentUser::CurrentUser->access_right('Post payment')
+% && $curuser->access_right('Post payment')
+% && ! $conf->exists('pkg-balances')
% )
% {
% my $s = 0;
@@ -36,27 +58,25 @@
% }
+% if ( $curuser->access_right('Resend invoices') ) {
-% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
-
- <A HREF="<% $p %>misc/print-invoice.cgi?<% $link %>">Re-print this invoice</A>
+ <A HREF="<% $p %>misc/send-invoice.cgi?method=print;<% $link %>">Re-print this invoice</A>
% if ( grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ) {
- | <A HREF="<% $p %>misc/email-invoice.cgi?<% $link %>">Re-email this invoice</A>
+ | <A HREF="<% $p %>misc/send-invoice.cgi?method=email;<% $link %>">Re-email this invoice</A>
% }
% if ( $conf->exists('hylafax') && length($cust_bill->cust_main->fax) ) {
- | <A HREF="<% $p %>misc/fax-invoice.cgi?<% $link %>">Re-fax this invoice</A>
+ | <A HREF="<% $p %>misc/send-invoice.cgi?method=fax;<% $link %>">Re-fax this invoice</A>
% }
<BR><BR>
% }
-
% if ( $conf->exists('invoice_latex') ) {
- <A HREF="<% $p %>view/cust_bill-pdf.cgi?<% $link %>.pdf">View typeset invoice</A>
+ <A HREF="<% $p %>view/cust_bill-pdf.cgi?<% $link %>">View typeset invoice PDF</A>
<BR><BR>
% }
@@ -72,24 +92,35 @@
<% $br ? '<BR><BR>' : '' %>
% if ( $conf->exists('invoice_html') ) {
-
- <% join('', $cust_bill->print_html('', $templatename) ) %>
+ <% join('', $cust_bill->print_html(\%opt) ) %>
% } else {
-
- <PRE><% join('', $cust_bill->print_text('', $templatename) ) %></PRE>
+ <PRE><% join('', $cust_bill->print_text(\%opt) ) %></PRE>
% }
<% include('/elements/footer.html') %>
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+ unless $curuser->access_right('View invoices');
-#untaint invnum
+my( $invnum, $template, $notice_name );
my($query) = $cgi->keywords;
-$query =~ /^((.+)-)?(\d+)$/;
-my $templatename = $2;
-my $invnum = $3;
+if ( $query =~ /^((.+)-)?(\d+)$/ ) {
+ $template = $2;
+ $invnum = $3;
+ $notice_name = 'Invoice';
+} else {
+ $invnum = $cgi->param('invnum');
+ $template = $cgi->param('template');
+ $notice_name = $cgi->param('notice_name');
+}
+
+my %opt = (
+ 'template' => $template,
+ 'notice_name' => $notice_name,
+);
my $conf = new FS::Conf;
@@ -104,7 +135,7 @@ my $cust_bill = qsearchs({
'table' => 'cust_bill',
'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
'hashref' => { 'invnum' => $invnum },
- 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
});
die "Invoice #$invnum not found!" unless $cust_bill;
@@ -113,8 +144,8 @@ my $display_custnum = $cust_bill->cust_main->display_custnum;
#my $printed = $cust_bill->printed;
-my $link = $templatename ? "$templatename-$invnum" : $invnum;
+my $link = "invnum=$invnum";
+$link .= ';template='. uri_escape($template) if $template;
+$link .= ';notice_name='. $notice_name if $notice_name;
</%init>
-
-
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index 2231d41..314207b 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -1,8 +1,19 @@
-<% include("/elements/header.html","Customer View: ". $cust_main->name ) %>
+<% include('/elements/header.html', {
+ 'title' => "Customer View: ". $cust_main->name,
+ 'nobr' => 1,
+ })
+%>
+<BR>
-% if ( $curuser->access_right('Edit customer') ) {
- <A HREF="<% $p %>edit/cust_main.cgi?<% $custnum %>">Edit this customer</A> |
-% }
+<% include('/elements/menubar.html',
+ { 'newstyle' => 1,
+ 'selected' => $viewname{$view},
+ 'url_base' => $cgi->url. "?custnum=$custnum;show=",
+ },
+ %views,
+ )
+%>
+<BR>
<% include('/elements/init_overlib.html') %>
@@ -13,6 +24,12 @@ function areyousure(href, message) {
}
</SCRIPT>
+% if ( $view eq 'basics' || $view eq 'jumbo' ) {
+
+% if ( $curuser->access_right('Edit customer') ) {
+ <A HREF="<% $p %>edit/cust_main.cgi?<% $custnum %>">Edit this customer</A> |
+% }
+
% if ( $curuser->access_right('Cancel customer')
% && $cust_main->ncancelled_pkgs
% ) {
@@ -23,6 +40,7 @@ function areyousure(href, message) {
'actionlabel' => 'Confirm Cancellation',
'color' => '#ff0000',
'cust_main' => $cust_main,
+ 'width' => 616, #make room for reasons
}
)
%> |
@@ -74,10 +92,12 @@ function areyousure(href, message) {
</TD>
</TR>
</TABLE>
-%
-%if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
-%
+% }
+
+% if ( $view eq 'notes' || $view eq 'jumbo' ) {
+
+%if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
<BR>
Comments
<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
@@ -87,12 +107,17 @@ Comments
</TD>
</TR>
</TABLE></TABLE>
-% }
<BR><BR>
+% }
+<A NAME="notes">
% my $notecount = scalar($cust_main->notes());
% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
-<A NAME="cust_main_note"><FONT SIZE="+2">Notes</FONT></A><BR>
+% unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) {
+ <BR>
+ <A NAME="cust_main_note"><FONT SIZE="+2">Notes</FONT></A><BR>
+% }
+
% if ( $curuser->access_right('Add customer note') &&
% ! $conf->exists('cust_main-disable_notes')
% ) {
@@ -114,25 +139,78 @@ Comments
<% include('cust_main/notes.html', 'custnum' => $cust_main->custnum ) %>
% }
+<BR>
+% if(! $conf->config('disable_cust_attachment')
+% and $curuser->access_right('Add attachment')) {
+<% include( '/elements/popup_link-cust_main.html',
+ 'label' => 'Attach file',
+ 'action' => $p.'edit/cust_main_attach.cgi',
+ 'actionlabel' => 'Upload file',
+ 'cust_main' => $cust_main,
+ 'width' => 616,
+ 'height' => 408,
+ )
+%>
+% }
+<% include('cust_main/attachments.html', 'custnum' => $cust_main->custnum ) %>
+% if($cgi->param('show_deleted')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+ ($view ? ";show=$view" : '') . '#notes'
+ %>"><I>(Show active attachments)</I></A>
+% }
+% elsif($curuser->access_right('View deleted attachments')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+ ($view ? ";show=$view" : '') . ';show_deleted=1#notes'
+ %>"><I>(Show deleted attachments)</I></A>
+% }
+<BR>
-% if ( $conf->config('ticket_system') ) {
+% }
- <BR><BR>
+% if ( $view eq 'jumbo' ) {
+ <BR><BR>
+ <A NAME="tickets"><FONT SIZE="+2">Tickets</FONT></A><BR>
+% }
+
+% if ( $view eq 'tickets' || $view eq 'jumbo' ) {
+
+% if ( $conf->config('ticket_system') ) {
<% include('cust_main/tickets.html', $cust_main ) %>
% }
+ <BR><BR>
+
+% }
+% if ( $view eq 'jumbo' ) { #XXX enable me && $curuser->access_right('View customer packages') {
-<BR><BR>
+ <A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A><BR>
+% }
+
+% if ( $view eq 'packages' || $view eq 'jumbo' ) {
% #XXX enable me# if ( $curuser->access_right('View customer packages') {
<% include('cust_main/packages.html', $cust_main ) %>
% #}
+% }
+
+% if ( $view eq 'jumbo' ) {
+ <BR><BR>
+ <A NAME="history"><FONT SIZE="+2">Payment History</FONT></A><BR>
+% }
+
+% if ( $view eq 'payment_history' || $view eq 'jumbo' ) {
+
% if ( $conf->config('payby-default') ne 'HIDE' ) {
<% include('cust_main/payment_history.html', $cust_main ) %>
% }
+% }
+
+% if ( $view eq 'change_history' ) { # || $view eq 'jumbo'
+<% include('cust_main/change_history.html', $cust_main ) %>
+% }
<% include('/elements/footer.html') %>
<%init>
@@ -144,10 +222,16 @@ die "access denied"
my $conf = new FS::Conf;
-die "No customer specified (bad URL)!" unless $cgi->keywords;
-my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array
-$query =~ /^(\d+)$/;
-my $custnum = $1;
+my $custnum;
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $custnum = $1;
+} else {
+ die "No customer specified (bad URL)!" unless $cgi->keywords;
+ my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array
+ $query =~ /^(\d+)$/;
+ $custnum = $1;
+}
+
my $cust_main = qsearchs( {
'table' => 'cust_main',
'hashref' => { 'custnum' => $custnum },
@@ -155,4 +239,22 @@ my $cust_main = qsearchs( {
});
die "Customer not found!" unless $cust_main;
+#false laziness w/pref/pref.html and Conf.pm (cust_main-default_view)
+tie my %views, 'Tie::IxHash',
+ 'Basics' => 'basics',
+ 'Notes' => 'notes', #notes and files?
+;
+$views{'Tickets'} = 'tickets'
+ if $conf->config('ticket_system');
+$views{'Packages'} = 'packages';
+$views{'Payment History'} = 'payment_history'
+ unless $conf->config('payby-default' eq 'HIDE');
+$views{'Change History'} = 'change_history'
+ if $curuser->access_right('View customer history');
+$views{'Jumbo'} = 'jumbo';
+
+my %viewname = reverse %views;
+
+my $view = $cgi->param('show') || $curuser->default_customer_view;
+
</%init>
diff --git a/httemplate/view/cust_main/attachments.html b/httemplate/view/cust_main/attachments.html
new file mode 100755
index 0000000..53635fd
--- /dev/null
+++ b/httemplate/view/cust_main/attachments.html
@@ -0,0 +1,151 @@
+% if ( scalar(@attachments) ) {
+
+ <% include('/elements/init_overlib.html') %>
+
+ <% include("/elements/table-grid.html") %>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH>
+% if ( $conf->exists('cust_main_note-display_times') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">Time</TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc">Person</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Filename</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Type</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Size</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ </TR>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+% if($cgi->param('show_deleted')) {
+% if ($curuser->access_right('View deleted attachments')) {
+% @attachments = grep { $_->disabled } @attachments;
+% }
+% else {
+% @attachments = ();
+% }
+% }
+% else {
+% @attachments = grep { not $_->disabled } @attachments;
+% }
+%
+% foreach my $attach (@attachments) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $pop = popurl(3);
+% my $attachnum = $attach->attachnum;
+% my $edit = '';
+% if($attach->disabled) { # then you can undelete it or purge it.
+% if ($curuser->access_right('Undelete attachment')) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;".
+% "undelete=1",
+% 'Undelete attachment');
+% $edit .= qq!&nbsp; <A HREF="javascript:void(0);" $clickjs>(undelete)</A>!;
+% }
+% if ($curuser->access_right('Purge attachment')) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;".
+% "purge=1",
+% 'Purge attachment');
+% $edit .= qq!&nbsp; <A HREF="javascript:void(0);" $clickjs>(purge)</A>!;
+% }
+% }
+% else { # you can download or edit it
+% if ($curuser->access_right('Edit attachment') ) {
+% my $clickjs = popup('edit/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum",
+% 'Edit attachment properties');
+% $edit .= qq!&nbsp; <A HREF="javascript:void(0);" $clickjs>(edit)</A>!;
+% }
+% if($curuser->access_right('Delete attachment') ) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;".
+% "delete=1",
+% 'Delete attachment');
+% $edit .= qq!&nbsp; <A HREF="javascript:void(0);" $clickjs>(delete)</A>!;
+% }
+% if ($curuser->access_right('Download attachment') ) {
+% $edit .= qq!&nbsp; <A HREF="!.popurl(1).'attachment.html?'.$attachnum.qq!">(download)</A>!;
+% }
+% }
+
+ <TR>
+ <% note_datestr($attach,$conf,$bgcolor) %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<% $attach->otaker%>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<% $attach->filename %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<% $attach->mime_type %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<% size_units( $attach->size ) %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $edit %>
+ </TD>
+ </TR>
+
+% } #end display notes
+
+</TABLE>
+
+% }
+<%init>
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my(%opt) = @_;
+
+my $custnum = $opt{'custnum'};
+
+my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
+die "Customer not found!" unless $cust_main;
+
+my (@attachments) = qsearch('cust_attachment', {'custnum' => $custnum});
+
+#subroutines
+
+sub note_datestr {
+ my($note, $conf, $bgcolor) = @_ or return '';
+ my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
+ my $format = "$td%b&nbsp;%o,&nbsp;%Y</TD>";
+ $format .= "$td%l:%M%P</TD>"
+ if $conf->exists('cust_main_note-display_times');
+ ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
+ $strip;
+}
+
+sub size_units {
+ my $bytes = shift;
+ return $bytes if $bytes < 1024;
+ return int($bytes / 1024)."K" if $bytes < 1048576;
+ return int($bytes / 1048576)."M";
+}
+
+sub popup {
+ my ($url, $label) = @_;
+ my $onclick =
+ include('/elements/popup_link_onclick.html',
+ 'action' => popurl(2).$url,
+ 'actionlabel' => $label,
+ 'width' => 616,
+ 'height' => 408,
+ 'frame' => 'top',
+ );
+ return qq!onclick="$onclick"!;
+}
+
+
+</%init>
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index aea90e8..c8d0c47 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -159,11 +159,24 @@ Billing information
</TR>
% }
-
+% my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
<TR>
- <TD ALIGN="right">Tax&nbsp;exempt</TD>
+ <TD ALIGN="right">Tax&nbsp;exempt<% @exempt_groups ? ' (all taxes)' : '' %></TD>
<TD BGCOLOR="#ffffff"><% $cust_main->tax ? 'yes' : 'no' %></TD>
</TR>
+% foreach my $exempt_group ( @exempt_groups ) {
+<TR>
+ <TD ALIGN="right">Tax&nbsp;exempt (<% $exempt_group %> taxes)</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->tax_exemption($exempt_group) ? 'yes' : 'no' %></TD>
+</TR>
+% }
+
+% if ( $conf->exists('enable_taxproducts') ) {
+<TR>
+ <TD ALIGN="right">Tax&nbsp;location</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->geocode('cch') %></TD>
+</TR>
+% }
<TR>
<TD ALIGN="right">Postal&nbsp;invoices</TD>
<TD BGCOLOR="#ffffff">
@@ -203,6 +216,20 @@ Billing information
</TR>
% }
+% if ( $conf->exists('voip-cust_email_csv_cdr') ) {
+ <TR>
+ <TD ALIGN="right">Email&nbsp;CDRs&nbsp;as&nbsp;CSV</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->email_csv_cdr ? 'yes' : 'no' %></TD>
+ </TR>
+% }
+
+% if ( $show_term || $cust_main->cdr_termination_percentage ) {
+ <TR>
+ <TD ALIGN="right">CDR termination settlement</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->cdr_termination_percentage %><% $cust_main->cdr_termination_percentage =~ /\d/ ? '%' : '' %></TD>
+ </TR>
+% }
+
</TABLE></TD></TR></TABLE>
<%once>
@@ -217,4 +244,10 @@ my @invoicing_list = $cust_main->invoicing_list;
my $conf = new FS::Conf;
my $money_char = $conf->config('money_char') || '$';
+#false laziness w/edit/cust_main/billing.html
+my $term_sql = "SELECT COUNT(*) FROM cust_pkg LEFT JOIN part_pkg USING ( pkgpart ) WHERE custnum = ? AND plan = 'cdr_termination' LIMIT 1";
+my $term_sth = dbh->prepare($term_sql) or die dbh->errstr;
+$term_sth->execute($cust_main->custnum) or die $term_sth->errstr;
+my $show_term = $term_sth->fetchrow_arrayref->[0];
+
</%init>
diff --git a/httemplate/view/cust_main/change_history.html b/httemplate/view/cust_main/change_history.html
new file mode 100644
index 0000000..53a79f4
--- /dev/null
+++ b/httemplate/view/cust_main/change_history.html
@@ -0,0 +1,302 @@
+% if ( int( time - (keys %years)[0] * 31556736 ) > $start ) {
+ Show:
+% my $chy = $cgi->param('change_history-years');
+% foreach my $y (keys %years) {
+% if ( $y == $years ) {
+ <FONT SIZE="+1"><% $years{$y} %></FONT>
+% } else {
+% $cgi->param('change_history-years', $y);
+ <A HREF="<% $cgi->self_url %>"><% $years{$y} %></A>
+% }
+% last if int( time - $y * 31556736 ) < $start;
+% }
+% $cgi->param('change_history-years', $chy);
+% }
+
+<% include("/elements/table-grid.html") %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">User</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Time</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Item</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Action</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Description</TH>
+</TR>
+
+% foreach my $item ( sort { $a->history_date <=> $b->history_date
+% #|| table order
+% || $a->historynum <=> $b->historynum
+% }
+% @history
+% )
+% {
+%
+% my $history_other = '';
+% my $act = $item->history_action;
+% if ( $act =~ /^replace/ ) {
+% my $pkey = $item->primary_key;
+% my $date = $item->history_date;
+% $history_other = qsearchs({
+% 'table' => $item->table,
+% 'hashref' => { $pkey => $item->$pkey(),
+% 'history_action' => $replace_other{$act},
+% 'historynum' => { 'op' => $replace_dir{$act},
+% 'value' => $item->historynum
+% },
+% },
+% 'extra_sql' => "
+% AND history_date $replace_direq{$act} $date
+% AND ($date $replace_op{$act} $fuzz) $replace_direq{$act} history_date
+% ORDER BY historynum $replace_ord{$act} LIMIT 1
+% ",
+% });
+% }
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+ <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% my $otaker = $item->history_user;
+% $otaker = '<i>auto billing</i>' if $otaker eq 'fs_daily';
+% $otaker = '<i>customer self-service</i>' if $otaker eq 'fs_selfservice';
+% $otaker = '<i>job queue</i>' if $otaker eq 'fs_queue';
+ <% $otaker %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% my $d = time2str('%b %o, %Y', $item->history_date );
+% $d =~ s/ /&nbsp;/g;
+ <% $d %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% my $t = time2str('%r', $item->history_date );
+% $t =~ s/ /&nbsp;/g;
+ <% $t %>
+ </TD>
+ <TD ALIGN="center" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% my $label = $h_tables{$item->table};
+% $label = &{ $h_table_labelsub{$item->table} }( $item, $label )
+% if $h_table_labelsub{$item->table};
+ <% $label %>
+ </TD>
+ <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $action{$item->history_action} %>
+ </TD>
+ <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% join(', ',
+ map { my $value = ( $_ =~ /(^pay(info|cvv)|^ss|_password)$/ )
+ ? 'N/A'
+ : $item->get($_);
+ $value = substr($value, 0, 77).'...' if length($value) > 80;
+ $value = encode_entities($value);
+ "<I>$_</I>:<B>$value</B>";
+ }
+ grep { $history_other
+ ? ( $item->get($_) ne $history_other->get($_) )
+ : ( $item->get($_) =~ /\S/ )
+ }
+ grep { ! /^(history|custnum$)/i }
+ $item->fields
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+</TABLE>
+<%once>
+
+# length-switching
+
+tie my %years, 'Tie::IxHash',
+ .5 => '6 months',
+ 1 => '1 year',
+ 2 => '2 years',
+ 5 => '5 years',
+ 39 => 'all history',
+;
+
+# labeling history rows
+
+my %action = (
+ 'insert' => 'Insert', #'Create',
+ 'replace_old' => 'Change&nbsp;from',
+ 'replace_new' => 'Change&nbsp;to',
+ 'delete' => 'Remove',
+);
+
+# finding the other replace row
+
+my %replace_other = (
+ 'replace_new' => 'replace_old',
+ 'replace_old' => 'replace_new',
+);
+my %replace_dir = (
+ 'replace_new' => '<',
+ 'replace_old' => '>',
+);
+my %replace_direq = (
+ 'replace_new' => '<=',
+ 'replace_old' => '>=',
+);
+my %replace_op = (
+ 'replace_new' => '-',
+ 'replace_old' => '+',
+);
+my %replace_ord = (
+ 'replace_new' => 'DESC',
+ 'replace_old' => 'ASC',
+);
+
+my $fuzz = 5; #seems like a lot
+
+# which tables to search and what to call them
+
+tie my %tables, 'Tie::IxHash',
+ 'cust_main' => 'Customer',
+ 'cust_main_invoice' => 'Invoice destination',
+ 'cust_pkg' => 'Package',
+ #? or just svc_* ? 'cust_svc' =>
+ 'svc_acct' => 'Account',
+ 'radius_usergroup' => 'RADIUS group',
+ 'svc_domain' => 'Domain',
+ 'svc_www' => 'Hosting',
+ 'svc_forward' => 'Mail forward',
+ 'svc_broadband' => 'Broadband',
+ 'svc_external' => 'External service',
+ 'svc_phone' => 'Phone',
+ 'phone_device' => 'Phone device',
+ #? it gets provisioned anyway 'phone_avail' => 'Phone',
+;
+
+my $svc_join = 'JOIN cust_svc USING ( svcnum ) JOIN cust_pkg USING ( pkgnum )';
+
+my %table_join = (
+ 'svc_acct' => $svc_join,
+ 'radius_usergroup' => $svc_join,
+ 'svc_domain' => $svc_join,
+ 'svc_www' => $svc_join,
+ 'svc_forward' => $svc_join,
+ 'svc_broadband' => $svc_join,
+ 'svc_external' => $svc_join,
+ 'svc_phone' => $svc_join,
+ 'phone_device' => $svc_join,
+);
+
+my %h_tables = map { ( "h_$_" => $tables{$_} ) } keys %tables;
+
+my %pkgpart = ();
+my $pkg_labelsub = sub {
+ my($item, $label) = @_;
+ $pkgpart{$item->pkgpart} ||= $item->part_pkg->pkg;
+ $label. ': <b>'. encode_entities($pkgpart{$item->pkgpart}). '</b>';
+};
+
+my $svc_labelsub = sub {
+ my($item, $label) = @_;
+ $label. ': <b>'. encode_entities($item->label($item->history_date)). '</b>';
+};
+
+my %h_table_labelsub = (
+ 'h_cust_pkg' => $pkg_labelsub,
+ 'h_svc_acct' => $svc_labelsub,
+ #'h_radius_usergroup' =>
+ 'h_svc_domain' => $svc_labelsub,
+ 'h_svc_www' => $svc_labelsub,
+ 'h_svc_forward' => $svc_labelsub,
+ 'h_svc_broadband' => $svc_labelsub,
+ 'h_svc_external' => $svc_labelsub,
+ 'h_svc_phone' => $svc_labelsub,
+ #'h_phone_device'
+);
+
+# cust_main
+# cust_main_invoice
+
+# cust_pkg
+# cust_pkg_option?
+# cust_pkg_detail
+# cust_pkg_reason? no
+
+#cust_svc
+#cust_svc_option?
+#svc_*
+# svc_acct
+# radius_usergroup
+# acct_snarf? is this even used?
+# svc_domain
+# domain_record
+# registrar
+# svc_forward
+# svc_www
+# svc_broadband
+# (virtual fields? eh... maybe when they're real)
+# svc_external
+# svc_phone
+# phone_device
+# phone_avail
+
+# future:
+
+# inventory_item (from services)
+# pkg_referral? (changed?)
+
+#random others:
+
+# cust_location?
+# cust_main-exemption?? (295.ca named tax exemptions)
+
+</%once>
+<%init>
+
+my( $cust_main ) = @_;
+
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access deined"
+ unless $curuser->access_right('View customer history');
+
+# find out the beginning of this customer history, if possible
+my $h_insert = qsearchs({
+ 'table' => 'h_cust_main',
+ 'hashref' => { 'custnum' => $cust_main->custnum,
+ 'history_action' => 'insert',
+ },
+ 'extra_sql' => 'ORDER BY historynum LIMIT 1',
+});
+my $start = $h_insert ? $h_insert->history_date : 0;
+
+# retreive the history
+
+my @history = ();
+
+my $years = $conf->config('change_history-years') || .5;
+if ( $cgi->param('change_history-years') =~ /^([\d\.]+)$/ ) {
+ $years = $1;
+}
+my $newer_than = int( time - $years * 31556736 ); #60*60*24*365.24
+
+local($FS::Record::nowarn_classload) = 1;
+
+foreach my $table ( keys %tables ) {
+ my @items = qsearch({
+ 'table' => "h_$table",
+ 'addl_from' => $table_join{$table},
+ 'hashref' => { 'history_date' => { op=>'>=', value=>$newer_than }, },
+ 'extra_sql' => ' AND custnum = '. $cust_main->custnum,
+ });
+ push @history, @items;
+
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html
index 060da87..71e8d69 100644
--- a/httemplate/view/cust_main/misc.html
+++ b/httemplate/view/cust_main/misc.html
@@ -85,13 +85,24 @@
</TR>
% if ( $conf->exists('cust_main-enable_birthdate') ) {
-% my $dt = DateTime->from_epoch(epoch => $cust_main->birthdate,
-% time_zone=>'floating',
-% );
+% my $dt = $cust_main->birthdate ne ''
+% ? DateTime->from_epoch( 'epoch' => $cust_main->birthdate,
+% 'time_zone' =>'floating',
+% )
+% : '';
<TR>
<TD ALIGN="right">Date of Birth</TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->birthdate ne '' ? $dt->strftime($date_format) : '' %></TD>
+ <TD BGCOLOR="#ffffff"><% $dt ? $dt->strftime($date_format) : '' %></TD>
+ </TR>
+
+% }
+
+% if ( $conf->exists('cust_main-require_censustract') ) {
+
+ <TR>
+ <TD ALIGN="right">Census tract</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->censustract %></TD>
</TR>
% }
diff --git a/httemplate/view/cust_main/one_time_charge_link.html b/httemplate/view/cust_main/one_time_charge_link.html
new file mode 100644
index 0000000..4ce8a28
--- /dev/null
+++ b/httemplate/view/cust_main/one_time_charge_link.html
@@ -0,0 +1,91 @@
+<SCRIPT TYPE="text/javascript">
+
+function taxproductmagic(which) {
+
+ var str = '';
+ var elements = which.form.elements;
+ for (var i = 0; i<elements.length; i++) {
+
+ if (elements[i].name == 'taxproductnum'){
+ document.getElementById('taxproductnum').value = elements[i].value;
+ continue;
+ }
+ if (elements[i].name == 'taxproductnum_description'){
+ continue;
+ }
+
+ if (str.length){str += ';';}
+
+ var value = '';
+ if ( elements[i].type == 'checkbox' || elements[i].type == 'radio' ) {
+ if ( elements[i].checked == true ) {
+ value = elements[i].value;
+ //} else {
+ // value = '';
+ }
+ } else {
+ value = elements[i].value;
+ }
+ str += elements[i].name + '=' + escape(value);
+
+ }
+ document.getElementById('charge_storage').value = str;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/browse/part_pkg_taxproduct.cgi?_type=select&id=taxproductnum&onclick=taxproductquickchargemagic&taxproductnum='+document.getElementById('taxproductnum').value, 1000, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
+}
+
+function taxproductquickchargemagic() {
+ var str = document.getElementById('charge_storage').value;
+ if (str.length){str += ';';}
+ str += 'magic=taxproductnum;taxproductnum=';
+ str += escape(document.getElementById('taxproductnum').value);
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
+
+}
+
+function taxoverridemagic(which) {
+ var str = '';
+ var elements = which.ownerDocument.QuickChargeForm.elements;
+ for (var i = 0; i<elements.length; i++) {
+ if (elements[i].name == 'tax_override'){
+ document.getElementById('tax_override').value = elements[i].value;
+ continue;
+ }
+ if (str.length){str += ';';}
+ str += elements[i].name + '=' + escape(elements[i].value);
+ }
+ document.getElementById('charge_storage').value = str;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/part_pkg_taxoverride.html?element_name=tax_override;onclick=taxoverridequickchargemagic;selected='+document.getElementById('tax_override').value, 1100, 600, 'tax_product_popup'), CAPTION, 'Edit product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
+}
+
+function taxoverridequickchargemagic() {
+ var str = document.getElementById('charge_storage').value;
+ if (str.length){str += ';';}
+ str += 'magic=taxoverride;tax_override=';
+ str += document.getElementById('tax_override').value;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
+
+}
+
+</SCRIPT>
+
+<FORM NAME='quickcharge' STYLE="margin:0; padding:0; display:inline"><INPUT NAME="taxproductnum" ID="taxproductnum" TYPE="hidden"><INPUT NAME="tax_override" ID="tax_override" TYPE="hidden"><INPUT NAME="charge_storage" ID="charge_storage" TYPE="hidden"><INPUT NAME="taxproductnum_description" ID="taxproductnum_description" TYPE="hidden"></FORM>
+
+<% include('/elements/popup_link.html', {
+ 'action' => $p.'edit/quick-charge.html?custnum='. $cust_main->custnum,
+ 'label' => 'One-time charge',
+ 'actionlabel' => 'One-time charge',
+ 'color' => '#333399',
+ 'width' => 763,
+ 'height' => 408,
+ })
+%>
+
+<%init>
+
+my($cust_main) = @_;
+
+</%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 2c25888..17a0691 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -1,94 +1,24 @@
-<A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A><BR>
-
-% if ( $curuser->access_right('One-time charge') ) {
-
-<SCRIPT TYPE="text/javascript">
-
-function taxproductmagic(which) {
- var str = '';
- var elements = which.form.elements;
- for (var i = 0; i<elements.length; i++) {
- if (elements[i].name == 'taxproductnum'){
- document.getElementById('taxproductnum').value = elements[i].value;
- continue;
- }
- if (elements[i].name == 'taxproductnum_description'){
- continue;
- }
- if (str.length){str += ';';}
- str += elements[i].name + '=' + escape(elements[i].value);
- }
- document.getElementById('charge_storage').value = str;
- cClick();
- overlib( OLiframeContent('<% $p %>/browse/part_pkg_taxproduct.cgi?_type=select&id=taxproductnum&onclick=taxproductquickchargemagic&taxproductnum='+document.getElementById('taxproductnum').value, 1000, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
-}
-
-function taxproductquickchargemagic() {
- var str = document.getElementById('charge_storage').value;
- if (str.length){str += ';';}
- str += 'magic=taxproductnum;taxproductnum=';
- str += escape(document.getElementById('taxproductnum').value);
- cClick();
- overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
-
-}
-
-function taxoverridemagic(which) {
- var str = '';
- var elements = which.ownerDocument.QuickChargeForm.elements;
- for (var i = 0; i<elements.length; i++) {
- if (elements[i].name == 'tax_override'){
- document.getElementById('tax_override').value = elements[i].value;
- continue;
- }
- if (str.length){str += ';';}
- str += elements[i].name + '=' + escape(elements[i].value);
- }
- document.getElementById('charge_storage').value = str;
- cClick();
- overlib( OLiframeContent('<% $p %>/edit/part_pkg_taxoverride.html?element_name=tax_override;onclick=taxoverridequickchargemagic;selected='+document.getElementById('tax_override').value, 1100, 600, 'tax_product_popup'), CAPTION, 'Edit product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
-}
-
-function taxoverridequickchargemagic() {
- var str = document.getElementById('charge_storage').value;
- if (str.length){str += ';';}
- str += 'magic=taxoverride;tax_override=';
- str += document.getElementById('tax_override').value;
- cClick();
- overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
-
-}
-
-</SCRIPT>
-<FORM NAME='quickcharge'>
- <INPUT NAME="taxproductnum" ID="taxproductnum" TYPE="hidden">
- <INPUT NAME="tax_override" ID="tax_override" TYPE="hidden">
- <INPUT NAME="charge_storage" ID="charge_storage" TYPE="hidden">
- <INPUT NAME="taxproductnum_description" ID="taxproductnum_description" TYPE="hidden">
-</FORM>
-% }
-
% my $s = 0;
% if ( $curuser->access_right('Order customer package') ) {
<% $s++ ? ' | ' : '' %>
- <% order_pkg_link($cust_main) %>
+ <% include( '/elements/popup_link-cust_main.html',
+ 'action' => $p. 'misc/order_pkg.html',
+ 'label' => 'Order&nbsp;new&nbsp;package',
+ 'actionlabel' => 'Order new package',
+ 'color' => '#333399',
+ 'cust_main' => $cust_main,
+ 'closetext' => 'Close',
+ 'width' => 763,
+ 'height' => 350,
+ )
+ %>
% }
% if ( $curuser->access_right('One-time charge')
% && $conf->config('payby-default') ne 'HIDE'
% ) {
-%
<% $s++ ? ' | ' : '' %>
- <% include('/elements/popup_link.html',
- {
- 'action' => $p. 'edit/quick-charge.html?custnum='. $cust_main->custnum,
- 'label' => 'One-time charge',
- 'actionlabel' => 'One-time charge',
- 'color' => '#333399',
- 'width' => 763,
- 'height' => 408,
- })
- %>
+ <% include('one_time_charge_link.html', $cust_main) %>
% }
% if ( $curuser->access_right('Bulk change customer packages') ) {
@@ -109,19 +39,25 @@ Current packages
% )
% )
% {
+% my $prev = $cgi->param('showcancelledpackages');
% $cgi->param('showcancelledpackages', 1);
-%
-
( <a href="<% $cgi->self_url %>">show
+% $cgi->param('showcancelledpackages', $prev);
% } else {
% $cgi->param('showcancelledpackages', 0);
-%
-
( <a href="<% $cgi->self_url %>">hide
+% $cgi->param('showcancelledpackages', 1);
% }
cancelled packages</a> )
% }
+% if ( $num_old_packages ) {
+% $cgi->param('showoldpackages', 1);
+ ( <a href="<% $cgi->self_url %>">show old packages</a> )
+% } elsif ( $cgi->param('showoldpackages') ) {
+% $cgi->param('showoldpackages', 0);
+ ( <a href="<% $cgi->self_url %>">hide old packages</a> )
+% }
% if ( @$packages ) {
<% include('/elements/table-grid.html') %>
@@ -138,6 +74,7 @@ Current packages
<TH CLASS="grid" BGCOLOR="#cccccc">Services</TH>
</TR>
+% #$FS::cust_pkg::DEBUG = 2;
% foreach my $cust_pkg (@$packages) {
%
% if ( $bgcolor eq $bgcolor1 ) {
@@ -146,25 +83,13 @@ Current packages
% $bgcolor = $bgcolor1;
% }
%
-% my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
% my %iopt = (
-% 'bgcolor' => $bgcolor,
-% 'cust_pkg' => $cust_pkg,
-% 'part_pkg' => $cust_pkg->part_pkg,
-%
-% #for services.html and status.html
-% 'cust_pkg-display_times' => $conf->exists('cust_pkg-display_times'),
-%
-% #for location.html
-% 'countrydefault' => $countrydefault,
-% 'statedefault' => ( scalar($conf->config('statedefault'))
-% || ($countrydefault eq 'US' ? 'CA' : '') ),
-%
-% #for services.html
-% 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'),
-% 'legacy_link' => $conf->exists('legacy_link'),
-%
+% 'bgcolor' => $bgcolor,
+% 'cust_pkg' => $cust_pkg,
+% 'part_pkg' => $cust_pkg->part_pkg,
+% %conf_opt,
% );
+%
<!--pkgnum: <% $cust_pkg->pkgnum %>-->
<TR>
@@ -193,6 +118,7 @@ Current packages
if ( el ) el.scrollIntoView(true);
</SCRIPT>
% }
+
<%init>
my( $cust_main ) = @_;
@@ -200,18 +126,38 @@ my $conf = new FS::Conf;
my $curuser = $FS::CurrentUser::CurrentUser;
-my $packages = get_packages($cust_main, $conf);
+my( $packages, $num_old_packages ) = get_packages($cust_main, $conf);
my $show_location = $conf->exists('cust_pkg-always_show_location')
|| ( grep $_->locationnum, @$packages ); # ? '1' : '0';
+my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
+my %conf_opt = (
+ #for services.html and status.html
+ 'cust_pkg-display_times' => $conf->exists('cust_pkg-display_times'),
+
+ #for status.html
+ 'cust_pkg-show_autosuspend' => $conf->exists('cust_pkg-show_autosuspend'),
+ #for status.html pkg-balances
+ 'pkg-balances' => $conf->exists('pkg-balances'),
+ 'money_char' => ( $conf->config('money_char') || '$' ),
+
+ #for location.html
+ 'countrydefault' => $countrydefault,
+ 'statedefault' => ( scalar($conf->config('statedefault'))
+ || ($countrydefault eq 'US' ? 'CA' : '') ),
+ #for services.html
+ 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'),
+ 'legacy_link' => $conf->exists('legacy_link'),
+ 'svc_broadband-manage_link' => $conf->config('svc_broadband-manage_link'),
+);
+
#subroutines
sub get_packages {
my $cust_main = shift or return undef;
my $conf = shift;
-
- my @packages = ();
+
my $method;
if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
|| ( $conf->exists('hidecancelledpackages')
@@ -223,19 +169,51 @@ sub get_packages {
$method = 'all_pkgs';
}
- [ $cust_main->$method() ];
-}
+ my $cust_pkg_fields =
+ join(', ', map { "cust_pkg.$_ AS $_" } fields('cust_pkg') );
+
+ my $part_pkg_fields =
+ join(', ', map { "part_pkg.$_ AS part_pkg_$_" } fields('part_pkg') );
+
+ my $group_by =
+ join(', ', map "cust_pkg.$_", fields('cust_pkg') ). ', '.
+ join(', ', map "part_pkg.$_", fields('part_pkg') );
+
+ my $num_svcs = '( SELECT COUNT(*) FROM cust_svc '.
+ ' WHERE cust_svc.pkgnum = cust_pkg.pkgnum ) AS num_svcs';
+
+ my @packages = $cust_main->$method( {
+ 'select' => "$cust_pkg_fields, $part_pkg_fields, $num_svcs",
+ 'addl_from' => 'LEFT JOIN part_pkg USING ( pkgpart )',
+ } );
+ my $num_old_packages = scalar(@packages);
+
+ foreach my $cust_pkg ( @packages ) {
+ my %hash = $cust_pkg->hash;
+ my %part_pkg = map { /^part_pkg_(.+)$/ or die; ( $1 => $hash{$_} ); }
+ grep { /^part_pkg_/ } keys %hash;
+ $cust_pkg->{'_pkgpart'} = new FS::part_pkg \%part_pkg;
+ }
+
+ unless ( $cgi->param('showoldpackages') ) {
+ my $years = $conf->config('cust_main-packages-years') || 2;
+ my $seconds = 31556926; #60*60*24*365.2422 is close enough
+ my $then = time - $seconds;
+
+ my %hide = ( 'cancelled' => 'cancel',
+ 'one-time charge' => 'setup',
+ );
+
+ @packages =
+ grep { !exists($hide{$_->status}) or $_->get($hide{$_->status}) > $then
+ or $_->num_svcs #don't hide packages w/services
+ }
+ @packages;
+ }
+
+ $num_old_packages -= scalar(@packages);
-sub order_pkg_link {
- include( '/elements/popup_link-cust_main.html',
- 'action' => $p. 'misc/order_pkg.html',
- 'label' => 'Order&nbsp;new&nbsp;package',
- 'actionlabel' => 'Order new package',
- 'color' => '#333399',
- 'cust_main' => shift,
- 'closetext' => 'Close',
- 'width' => 763,
- )
+ ( \@packages, $num_old_packages );
}
</%init>
diff --git a/httemplate/view/cust_main/packages/package.html b/httemplate/view/cust_main/packages/package.html
index b07e1af..280a016 100644
--- a/httemplate/view/cust_main/packages/package.html
+++ b/httemplate/view/cust_main/packages/package.html
@@ -6,7 +6,7 @@
ID ="cust_pkg<% $cust_pkg->pkgnum %>"
><% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B></A>
-
- <% $part_pkg->comment |h %>
+ <% $part_pkg->custom_comment |h %>
</TD>
</TR>
@@ -38,7 +38,7 @@
%
% if ( $curuser->access_right('Customize customer package') ) {
% $br=1;
- (&nbsp;<%pkg_customize_link($cust_pkg,$cust_pkg->custnum)%>&nbsp;)
+ (&nbsp;<%pkg_customize_link($cust_pkg,$part_pkg)%>&nbsp;)
% }
%
<% $br ? '<BR>' : '' %>
@@ -58,18 +58,18 @@
% my $editi = $curuser->access_right('Edit customer package invoice details');
% my $editc = $curuser->access_right('Edit customer package comments');
+% my @cust_pkg_detail = $cust_pkg->cust_pkg_detail;
+% my @invoice_detail = grep { $_->detailtype eq 'I' } @cust_pkg_detail;
+% my @comments = grep { $_->detailtype eq 'C' } @cust_pkg_detail;
%
-% if ( $cust_pkg->cust_pkg_detail('I')
-% || $cust_pkg->cust_pkg_detail('C')
-% || $editi
-% || $editc ) {
+% if ( scalar(@invoice_detail) || scalar(@comments) || $editi || $editc ) {
%
% my $editlink = $p. 'edit/cust_pkg_detail?pkgnum='. $cust_pkg->pkgnum.
% ';detailtype=';
<TR>
-% if ( $cust_pkg->cust_pkg_detail('I') ) {
+% if ( @invoice_detail ) {
<TD VALIGN="top">
<% include('/elements/table-grid.html') %>
<TR>
@@ -89,7 +89,7 @@
</FONT>
</TH>
</TR>
-% foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('I') ) {
+% foreach my $cust_pkg_detail ( @invoice_detail ) {
<TR>
<TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
</TR>
@@ -113,7 +113,7 @@
</TD>
% }
-% if ( $cust_pkg->cust_pkg_detail('C') ) {
+% if ( @comments ) {
<TD VALIGN="top">
<% include('/elements/table-grid.html') %>
<TR>
@@ -133,7 +133,7 @@
</FONT>
</TH>
</TR>
-% foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('C') ) {
+% foreach my $cust_pkg_detail ( @comments ) {
<TR>
<TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
</TR>
@@ -198,9 +198,10 @@ sub pkg_dates_link { pkg_link('edit/REAL_cust_pkg', 'Edit&nbsp;dates', @_ ); }
sub pkg_customize_link {
my $cust_pkg = shift or return '';
+ my $part_pkg = shift;
my $custnum = $cust_pkg->custnum;
qq!<A HREF="${p}edit/part_pkg.cgi?!.
- "clone=". $cust_pkg->part_pkg->pkgpart. ';'.
+ "clone=". $part_pkg->pkgpart. ';'.
"pkgnum=". $cust_pkg->pkgnum.
qq!">Customize</A>!;
}
diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html
index 1e47373..0fe7931 100644
--- a/httemplate/view/cust_main/packages/services.html
+++ b/httemplate/view/cust_main/packages/services.html
@@ -36,15 +36,29 @@
% )
% ) {
(&nbsp;<%svc_recharge_link($cust_svc)%>&nbsp;)
-% }
+% }
</FONT></TD>
- <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
+ <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px">
-% if ( $curuser->access_right('Unprovision customer service') ) {
- (&nbsp;<%svc_unprovision_link($cust_svc)%>&nbsp;)
-% }
- </FONT></TD>
+% my $ip_addr = $cust_svc->svc_x->ip_addr;
+
+% if ( $part_svc->svcdb eq 'svc_broadband' ) {
+ <FONT SIZE="-1" STYLE="float:left">(&nbsp;<% include('/elements/popup_link-ping.html', 'ip'=> $ip_addr ) %>&nbsp;)</FONT>
+
+% }
+
+% my $manage_link = $opt{'svc_broadband-manage_link'};
+% if ( $manage_link && $part_svc->svcdb eq 'svc_broadband' ) {
+% my $svc_manage_link = eval(qq("$manage_link"));
+ <FONT SIZE="-1" STYLE="float:left">(&nbsp;<A HREF="<% $svc_manage_link %>">Manage Device</A>&nbsp;)</FONT>
+
+% }
+
+% if ( $curuser->access_right('Unprovision customer service') ) {
+ <FONT SIZE="-2">(&nbsp;<%svc_unprovision_link($cust_svc)%>&nbsp;)</FONT>
+% }
+ </TD>
</TR>
% }
@@ -75,6 +89,8 @@ my $cust_pkg = $opt{'cust_pkg'};
my $part_pkg = $opt{'part_pkg'};
my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = new FS::Conf;
+
sub svc_provision_link {
my ($cust_pkg, $part_svc, $opt, $curuser) = @_;
( my $svc_nbsp = $part_svc->svc ) =~ s/\s+/&nbsp;/g;
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
index 106137b..6667a55 100644
--- a/httemplate/view/cust_main/packages/status.html
+++ b/httemplate/view/cust_main/packages/status.html
@@ -8,20 +8,21 @@
<% pkg_status_row($cust_pkg, 'Cancelled', 'cancel', 'color'=>'FF0000', %opt ) %>
- <% pkg_status_row_colspan(
+ <% pkg_status_row_colspan( $cust_pkg,
( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
- 'align' => 'right', 'color' => 'ff0000', 'size' => '-2',
+ 'align'=>'right', 'color'=>'ff0000', 'size'=>'-2', 'colspan'=>$colspan,
+ %opt
)
%>
% unless ( $cust_pkg->get('setup') ) {
- <% pkg_status_row_colspan('Never billed') %>
+ <% pkg_status_row_colspan( $cust_pkg, 'Never billed', '', 'colspan'=>$colspan, %opt, ) %>
% } else {
<% pkg_status_row( $cust_pkg, 'Setup', 'setup', %opt ) %>
- <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, 'Suspended', 'susp', %opt, curuser=>$curuser ) %>
@@ -34,19 +35,20 @@
<% pkg_status_row( $cust_pkg, 'Suspended', 'susp', 'color'=>'FF9900', %opt ) %>
- <% pkg_status_row_colspan(
+ <% pkg_status_row_colspan( $cust_pkg,
( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
- 'align' => 'right', 'color' => 'FF9900', 'size' => '-2',
+ 'align'=>'right', 'color'=>'FF9900', 'size'=>'-2', 'colspan'=>$colspan,
+ %opt,
)
%>
% unless ( $cust_pkg->get('setup') ) {
- <% pkg_status_row_colspan('Never billed') %>
+ <% pkg_status_row_colspan( $cust_pkg, 'Never billed', '', 'colspan'=>$colspan, %opt ) %>
% } else {
<% pkg_status_row($cust_pkg, 'Setup', 'setup', %opt ) %>
% }
- <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
% # pkg_status_row($cust_pkg, 'Next bill', 'bill', %opt)
<% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
@@ -70,7 +72,15 @@
%
% unless ( $part_pkg->freq ) {
- <% pkg_status_row_colspan('Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)') %>
+ <% pkg_status_row_colspan( $cust_pkg, 'Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)', '', 'colspan'=>$colspan, %opt ) %>
+
+ <% pkg_status_row_if(
+ $cust_pkg,
+ ( $part_pkg->freq ? 'Start billing' : 'Bill on' ),
+ 'start_date',
+ %opt
+ )
+ %>
<TR>
<TD COLSPAN=<%$colspan%>>
@@ -84,7 +94,9 @@
% } else {
- <% pkg_status_row_colspan("Not&nbsp;yet&nbsp;billed&nbsp;($billed_or_prepaid&nbsp;". myfreq($part_pkg). ')' ) %>
+ <% pkg_status_row_colspan($cust_pkg, "Not&nbsp;yet&nbsp;billed&nbsp;($billed_or_prepaid&nbsp;". myfreq($part_pkg). ')', '', 'colspan'=>$colspan, %opt ) %>
+
+ <% pkg_status_row_if($cust_pkg, 'Start billing', 'start_date', %opt) %>
% }
%
@@ -92,7 +104,7 @@
%
% unless ( $part_pkg->freq ) {
- <% pkg_status_row_colspan('One-time&nbsp;charge') %>
+ <% pkg_status_row_colspan($cust_pkg, 'One-time&nbsp;charge', '', 'colspan'=>$colspan, %opt ) %>
<% pkg_status_row($cust_pkg, 'Billed', 'setup', %opt) %>
@@ -100,18 +112,20 @@
%
% if (scalar($cust_pkg->overlimit)) {
- <% pkg_status_row_colspan(
+ <% pkg_status_row_colspan( $cust_pkg,
'Overlimit',
$billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
- 'color' => 'FFD000',
+ 'color'=>'FFD000', 'colspan'=>$colspan,
+ %opt
)
%>
% } else {
- <% pkg_status_row_colspan(
+ <% pkg_status_row_colspan( $cust_pkg,
'Active',
$billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
- 'color' => '00CC00',
+ 'color'=>'00CC00', 'colspan'=>$colspan,
+ %opt
)
%>
% }
@@ -122,12 +136,12 @@
%
% }
%
-% if ( $conf->exists('cust_pkg-show_autosuspend') ) {
+% if ( $opt{'cust_pkg-show_autosuspend'} ) {
% my $autosuspend = pkg_autosuspend_time( $cust_pkg );
% $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
% }
- <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if($cust_pkg, 'Will automatically suspend by', 'autosuspend', %opt) %>
@@ -165,13 +179,10 @@
</TABLE>
</TD>
-
<%init>
my %opt = @_;
-my $conf = new FS::Conf;
-
my $bgcolor = $opt{'bgcolor'};
my $cust_pkg = $opt{'cust_pkg'};
my $part_pkg = $opt{'part_pkg'};
@@ -216,8 +227,15 @@ sub pkg_status_row {
$html .= qq(<FONT COLOR="#$color"><B>) if length($color);
$html .= qq($title&nbsp;);
$html .= qq(</B></FONT>) if length($color);
+
+ if ( $opt{'pkg_balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
+ $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
+ $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
+ '</B>)';
+ }
+
$html .= qq(</TD>);
- $html .= pkg_datestr($cust_pkg, $field, %opt).'</TR>';
+ $html .= pkg_datestr($cust_pkg, $field, %opt). '</TR>';
$html;
}
@@ -240,20 +258,31 @@ sub pkg_status_row_if {
sub pkg_status_row_changed {
my( $cust_pkg, %opt ) = @_;
+
return '' unless $cust_pkg->change_date;
- my $html = pkg_status_row( $cust_pkg, 'Package&nbsp;changed', 'change_date', %opt );
+
+ my $html =
+ pkg_status_row( $cust_pkg, 'Package&nbsp;changed', 'change_date', %opt );
+
my $old = $cust_pkg->old_cust_pkg;
if ( $old ) {
my $part_pkg = $old->part_pkg;
my $label = 'Changed from '. $cust_pkg->change_pkgnum. ': '.
- $part_pkg->pkg. ' - '. $part_pkg->comment;
- $html .= pkg_status_row_colspan( $label, '', size=>'-1', align=>'right' );
+ $part_pkg->pkg_comment(nopartpkg => 1);
+ $html .= pkg_status_row_colspan( $cust_pkg, $label, '',
+ 'size' => '-1',
+ 'align' => 'right',
+ 'colspan' => $opt{'colspan'},
+ );
}
+
$html;
}
sub pkg_status_row_colspan {
- my($title, $addl, %opt) = @_;
+ my($cust_pkg, $title, $addl, %opt) = @_;
+
+ my $colspan = $opt{'colspan'};
my $align = $opt{'align'} ? 'ALIGN="'. $opt{'align'}.'"' : '';
my $color = $opt{'color'} ? 'COLOR="#'.$opt{'color'}.'"' : '';
@@ -266,6 +295,13 @@ sub pkg_status_row_colspan {
$html .= qq(</B>) if $color && !$size;
$html .= qq(</FONT>) if length($color) || $size;
$html .= ",&nbsp;$addl" if length($addl);
+
+ if ( $opt{'pkg-balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
+ $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
+ $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
+ '</B>)';
+ }
+
$html .= qq(</TD></TR>);
$html;
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
index 335ce24..2ac3f26 100644
--- a/httemplate/view/cust_main/payment_history.html
+++ b/httemplate/view/cust_main/payment_history.html
@@ -1,5 +1,3 @@
-<BR><BR><A NAME="history"><FONT SIZE="+2">Payment History</FONT></A><BR>
-
%# payment links
% my $s = 0;
@@ -129,10 +127,33 @@
%# tax exemption link
-% if ( $curuser->access_right('View customer tax exemptions') ) {
- <A HREF="<% $p %>search/cust_tax_exempt_pkg.cgi?custnum=<% $custnum %>">View tax exemptions</A>
+% my $view_exemptions = $curuser->access_right('View customer tax exemptions');
+% my $add_adjustment = ( $conf->exists('enable_tax_adjustments')
+% && $curuser->access_right('Add customer tax adjustment')
+% );
+% if ( $view_exemptions || $add_adjustment ) {
+
+% if ( $view_exemptions ) {
+ <A HREF="<% $p %>search/cust_tax_exempt_pkg.cgi?custnum=<% $custnum %>">View tax exemptions</A>
+ <% $add_adjustment ? '|' : '' %>
+% }
+
+% if ( $add_adjustment ) {
+ <% include('/elements/popup_link.html', {
+ 'action' => $p.'edit/cust_tax_adjustment.html?custnum='. $cust_main->custnum,
+ 'label' => 'Add tax adjustment',
+ 'actionlabel' => 'Add tax adjustment',
+ #'color' => '#333399',
+ #'width' => 763,
+ 'height' => 200,
+ })
+ %>
+ |
+ <A HREF="<% $p %>search/cust_tax_adjustment.html?custnum=<% $custnum %>">View tax adjustments</A>
+% }
+
<BR>
-% }
+% }
%# batched payment links
@@ -353,13 +374,14 @@ my %status = (
#get payment history
my @history = ();
-my %opt =
+my %opt = (
( map { $_ => scalar($conf->config($_)) }
qw( card_refund-days )
),
( map { $_ => $conf->exists($_) }
- qw( deletepayments deleterefunds )
- );
+ qw( deleteinvoices deletepayments deleterefunds pkg-balances )
+ )
+);
#invoices
foreach my $cust_bill ($cust_main->cust_bill) {
@@ -370,6 +392,15 @@ foreach my $cust_bill ($cust_main->cust_bill) {
};
}
+#statements
+foreach my $cust_statement ($cust_main->cust_statement) {
+ push @history, {
+ 'date' => $cust_statement->_date,
+ 'desc' => include('payment_history/statement.html', $cust_statement, %opt ),
+ #'charge' => $cust_bill->charged,
+ };
+}
+
#payments (some false laziness w/credits)
foreach my $cust_pay ($cust_main->cust_pay) {
push @history, {
@@ -384,7 +415,7 @@ foreach my $cust_pay ($cust_main->cust_pay) {
foreach my $cust_pay_void ($cust_main->cust_pay_void) {
push @history, {
'date' => $cust_pay_void->_date,
- 'desc' => include('payment_history/voided_payment.html', $cust_pay_void),
+ 'desc' => include('payment_history/voided_payment.html', $cust_pay_void, %opt ),
'void_payment' => $cust_pay_void->paid,
};
@@ -394,7 +425,7 @@ foreach my $cust_pay_void ($cust_main->cust_pay_void) {
foreach my $cust_credit ($cust_main->cust_credit) {
push @history, {
'date' => $cust_credit->_date,
- 'desc' => include('payment_history/credit.html', $cust_credit),
+ 'desc' => include('payment_history/credit.html', $cust_credit, %opt ),
'credit' => $cust_credit->amount,
};
diff --git a/httemplate/view/cust_main/payment_history/credit.html b/httemplate/view/cust_main/payment_history/credit.html
index 2deb275..058c6f5 100644
--- a/httemplate/view/cust_main/payment_history/credit.html
+++ b/httemplate/view/cust_main/payment_history/credit.html
@@ -9,7 +9,13 @@ my $curuser = $FS::CurrentUser::CurrentUser;
my @cust_credit_bill = $cust_credit->cust_credit_bill;
my @cust_credit_refund = $cust_credit->cust_credit_refund;
-my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+my $desc = '';
+if ( $opt{'pkg-balances'} && $cust_credit->pkgnum ) {
+ my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_credit->pkgnum } );
+ $desc .= ' for '. $cust_pkg->pkg_label_long;
+}
+
+my( $pre, $post, $apply, $ext ) = ( '', '', '', '' );
if ( scalar(@cust_credit_bill) == 0
&& scalar(@cust_credit_refund) == 0 ) {
#completely unapplied
@@ -45,15 +51,15 @@ if ( scalar(@cust_credit_bill) == 0
&& scalar(@cust_credit_refund) == 0
&& $cust_credit->credited == 0 ) {
#applied to one invoice, the usual situation
- $desc = ' '. $cust_credit_bill[0]->applied_to_invoice;
+ $desc .= ' '. $cust_credit_bill[0]->applied_to_invoice;
} elsif ( scalar(@cust_credit_bill) == 0
&& scalar(@cust_credit_refund) == 1
&& $cust_credit->credited == 0 ) {
#applied to one refund
- $desc = ' refunded on '. time2str("%D", $cust_credit_refund[0]->_date);
+ $desc .= ' refunded on '. time2str("%D", $cust_credit_refund[0]->_date);
} else {
#complicated
- $desc = '<BR>';
+ $desc .= '<BR>';
foreach my $app ( sort { $a->_date <=> $b->_date }
( @cust_credit_bill, @cust_credit_refund ) ) {
if ( $app->isa('FS::cust_credit_bill') ) {
diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html
index 39c6739..c0d32df 100644
--- a/httemplate/view/cust_main/payment_history/invoice.html
+++ b/httemplate/view/cust_main/payment_history/invoice.html
@@ -1,9 +1,11 @@
-<% $link %><% $pre %>Invoice #<% $invnum %>
-(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $events %>
+<% $link %><% $pre %>Invoice #<% $cust_bill->display_invnum %>
+(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $delete %><% $events %>
<%init>
my( $cust_bill, %opt ) = @_;
+my $conf = new FS::Conf;
+
my $curuser = $FS::CurrentUser::CurrentUser;
my($pre, $post) = ('', '');
@@ -18,6 +20,15 @@ my $link = $curuser->access_right('View invoices')
? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!
: '';
+my $delete = '';
+if ( $opt{'deleteinvoices'} && $curuser->access_right('Delete invoices') ) {
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_bill.html?$invnum',!.
+ qq!'Are you sure you want to delete this invoice?')"!.
+ qq! TITLE="Delete this invoice from the database completely"!.
+ qq!>delete</A>)!;
+}
+
my $events = '';
#1.9
if ( $cust_bill->num_cust_event
@@ -26,8 +37,8 @@ if ( $cust_bill->num_cust_event
)
) {
$events =
- qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?invnum=!.
- $cust_bill->invnum. '">(&nbsp;View invoice events&nbsp;)</A></FONT>';
+ qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?invnum=$invnum!.
+ '">(&nbsp;View invoice events&nbsp;)</A></FONT>';
}
#
diff --git a/httemplate/view/cust_main/payment_history/payment.html b/httemplate/view/cust_main/payment_history/payment.html
index 2e24b17..a4a349b 100644
--- a/httemplate/view/cust_main/payment_history/payment.html
+++ b/httemplate/view/cust_main/payment_history/payment.html
@@ -32,7 +32,13 @@ $payby =~ s/^MCRD$/Manual credit card/;
$payby =~ s/^BILL$//;
my $info = $payby ? "($payby$payinfo)" : '';
-my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+my $desc = '';
+if ( $opt{'pkg-balances'} && $cust_pay->pkgnum ) {
+ my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_pay->pkgnum } );
+ $desc .= ' for '. $cust_pkg->pkg_label_long;
+}
+
+my( $pre, $post, $apply, $ext ) = ( '', '', '', '' );
if ( scalar(@cust_bill_pay) == 0
&& scalar(@cust_pay_refund) == 0 ) {
#completely unapplied
@@ -68,15 +74,15 @@ if ( scalar(@cust_bill_pay) == 0
&& scalar(@cust_pay_refund) == 0
&& $cust_pay->unapplied == 0 ) {
#applied to one invoice, the usual situation
- $desc = ' '. $cust_bill_pay[0]->applied_to_invoice;
+ $desc .= ' '. $cust_bill_pay[0]->applied_to_invoice;
} elsif ( scalar(@cust_bill_pay) == 0
&& scalar(@cust_pay_refund) == 1
&& $cust_pay->unapplied == 0 ) {
#applied to one refund
- $desc = ' refunded on '. time2str("%D", $cust_pay_refund[0]->_date);
+ $desc .= ' refunded on '. time2str("%D", $cust_pay_refund[0]->_date);
} else {
#complicated
- $desc = '<BR>';
+ $desc .= '<BR>';
foreach my $app ( sort { $a->_date <=> $b->_date }
( @cust_bill_pay, @cust_pay_refund ) ) {
if ( $app->isa('FS::cust_bill_pay') ) {
diff --git a/httemplate/view/cust_main/payment_history/statement.html b/httemplate/view/cust_main/payment_history/statement.html
new file mode 100644
index 0000000..dedec9b
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/statement.html
@@ -0,0 +1,34 @@
+<% $link %><% $pre %>Statement #<% $statementnum %>
+%# (Balance $ <% $cust_statement->owed %>)
+<% $post %><% $link ? '</A>' : '' %><% $events %>
+<%init>
+
+my( $cust_statement, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my($pre, $post) = ('', '');
+#if ( $cust_statement->owed > 0 ) {
+# $pre = '<B><FONT SIZE="+1" COLOR="#FF0000">Open ';
+# $post = '</FONT></B>';
+#}
+
+my $statementnum = $cust_statement->statementnum;
+
+my $link = $curuser->access_right('View invoices')
+ ? qq!<A HREF="${p}view/cust_statement.html?$statementnum">!
+ : '';
+
+my $events = '';
+
+#if ( $cust_statement->num_cust_event
+# && ( $curuser->access_right('Billing event reports')
+# || $curuser->access_right('View customer billing events')
+# )
+# ) {
+# $events =
+# qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?statementnum=!.
+# $cust_statement->statementnum. '">(&nbsp;View statement events&nbsp;)</A></FONT>';
+#}
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/voided_payment.html b/httemplate/view/cust_main/payment_history/voided_payment.html
index 9cbc47b..6103727 100644
--- a/httemplate/view/cust_main/payment_history/voided_payment.html
+++ b/httemplate/view/cust_main/payment_history/voided_payment.html
@@ -8,15 +8,32 @@ my( $cust_pay_void, %opt ) = @_;
my $curuser = $FS::CurrentUser::CurrentUser;
my $payby = $cust_pay_void->payby;
-my $payinfo = $payby eq 'CARD'
- ? $cust_pay_void->paymask
- : $cust_pay_void->payinfo;
+
+my $payinfo;
+if ( $payby eq 'CARD' ) {
+ $payinfo = $cust_pay_void->paymask;
+} elsif ( $payby eq 'CHEK' ) {
+ my( $account, $aba ) = split('@', $cust_pay_void->paymask );
+ $payinfo = "ABA $aba, Acct #$account";
+} else {
+ $payinfo = $cust_pay_void->payinfo;
+}
$payby =~ s/^BILL$/Check #/ if $payinfo;
$payby =~ s/^CHEK$/Electronic check /;
+$payby =~ s/^PREP$/Prepaid card /;
+$payby =~ s/^CARD$/Credit card #/;
+$payby =~ s/^COMP$/Complimentary by /;
+$payby =~ s/^CASH$/Cash/;
+$payby =~ s/^WEST$/Western Union/;
+$payby =~ s/^MCRD$/Manual credit card/;
$payby =~ s/^BILL$//;
-$payby =~ s/^(CARD|COMP)$/$1 /;
-my $info = $payby ? " ($payby$payinfo)" : '';
+my $info = $payby ? "($payby$payinfo)" : '';
+
+if ( $opt{'pkg-balances'} && $cust_pay_void->pkgnum ) {
+ my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_pay_void->pkgnum } );
+ $info .= ' for '. $cust_pkg->pkg_label_long;
+}
my $unvoid = '';
if ( $cust_pay_void->closed !~ /^Y/i
diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html
index b5d581d..167849c 100644
--- a/httemplate/view/cust_main/tickets.html
+++ b/httemplate/view/cust_main/tickets.html
@@ -1,6 +1,3 @@
-<A NAME="tickets"><FONT SIZE="+2">Tickets</FONT></A>
-<BR>
-
(<A HREF="<% $open_link %>">View <% $openlabel %> tickets for this customer</A>)
(<A HREF="<% $res_link %>">View resolved tickets for this customer</A>)
<BR>
diff --git a/httemplate/view/cust_pay.html b/httemplate/view/cust_pay.html
index c36d769..2f23d9e 100644
--- a/httemplate/view/cust_pay.html
+++ b/httemplate/view/cust_pay.html
@@ -1,12 +1,12 @@
% if ( $link eq 'popup' ) {
- <% include('/elements/header-popup.html', "Payment Receipt" ) %>
+ <% include('/elements/header-popup.html', "$thing Receipt" ) %>
<CENTER><A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A></CENTER><BR>
% } elsif ( $link eq 'print' ) {
- <% include('/elements/header-popup.html', "Payment Receipt" ) %>
+ <% include('/elements/header-popup.html', "$thing Receipt" ) %>
% #it would be nice if the menubar could be hidden for print, but better to
% # have it available than not, otherwise the user winds up at a dead end
@@ -18,7 +18,7 @@
% } else {
- <% include('/elements/header.html', "Payment Receipt", menubar(
+ <% include('/elements/header.html', "$thing Receipt", menubar(
"View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
'Print receipt' => $pr_link,
))
@@ -48,6 +48,20 @@
<TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_pay->_date %></B></TD>
</TR>
+% if ( $void ) {
+
+ <TR>
+ <TD ALIGN="right">Void Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_pay->void_date %></B></TD>
+ </TR>
+
+%# <TR>
+%# <TD ALIGN="right">Void reason</TD>
+%# <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->reason %></B></TD>
+%# </TR>
+
+% }
+
<TR>
<TD ALIGN="right">Amount</TD>
<TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_pay->paid %></B></TD>
@@ -79,6 +93,15 @@
% }
+% if ( $conf->exists('pkg-balances') && $cust_pay->pkgnum ) {
+% my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_pay->pkgnum } );
+ <TR>
+ <TD ALIGN="right">For package</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pkg->pkg_label_long %></B></TD>
+ </TR>
+
+% }
+
</TABLE>
% if ( $link eq 'print' ) {
@@ -112,16 +135,20 @@ if ( $cgi->param('link') =~ /^(\w+)$/ ) {
$link = $1;
}
+my $void = $cgi->param('void') ? 1 : 0;
+my $thing = $void ? 'Voided Payment' : 'Payment';
+my $table = $void ? 'cust_pay_void' : 'cust_pay';
+
my $cust_pay = qsearchs({
- 'select' => 'cust_pay.*',
- 'table' => 'cust_pay',
+ 'select' => "$table.*",
+ 'table' => $table,
'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
'hashref' => { 'paynum' => $paynum },
'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
});
-die "Payment #$paynum not found!" unless $cust_pay;
+die "$thing #$paynum not found!" unless $cust_pay;
-my $pr_link = "${p}view/cust_pay.html?link=print;paynum=$paynum";
+my $pr_link = "${p}view/cust_pay.html?link=print;paynum=$paynum;void=$void";
my $custnum = $cust_pay->custnum;
my $display_custnum = $cust_pay->cust_main->display_custnum;
diff --git a/httemplate/view/cust_pay_void.html b/httemplate/view/cust_pay_void.html
new file mode 100644
index 0000000..8c22170
--- /dev/null
+++ b/httemplate/view/cust_pay_void.html
@@ -0,0 +1 @@
+<% include('cust_pay.html', @_, 'void' => 1 ) %>
diff --git a/httemplate/view/cust_statement-pdf.cgi b/httemplate/view/cust_statement-pdf.cgi
new file mode 100755
index 0000000..a1739e0
--- /dev/null
+++ b/httemplate/view/cust_statement-pdf.cgi
@@ -0,0 +1,28 @@
+<% $pdf %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint statementnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)(.pdf)?$/;
+my $templatename = $2 || 'statement'; #XXX configure... via event?? eh..
+my $statementnum = $3;
+
+my $cust_statement = qsearchs({
+ 'select' => 'cust_statement.*',
+ 'table' => 'cust_statement',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'statementnum' => $statementnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Statement #$statementnum not found!" unless $cust_statement;
+
+my $pdf = $cust_statement->print_pdf( '', $templatename);
+
+http_header('Content-Type' => 'application/pdf' );
+http_header('Content-Length' => length($pdf) );
+http_header('Cache-control' => 'max-age=60' );
+
+</%init>
diff --git a/httemplate/view/cust_statement.html b/httemplate/view/cust_statement.html
new file mode 100755
index 0000000..3e1345e
--- /dev/null
+++ b/httemplate/view/cust_statement.html
@@ -0,0 +1,79 @@
+<% include("/elements/header.html",'Statement View', menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+)) %>
+
+% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
+
+%# <A HREF="<% $p %>misc/send-statement.cgi?method=print;<% $link %>">Re-print this statement</A>
+
+% if ( grep { $_ ne 'POST' } $cust_statement->cust_main->invoicing_list ) {
+%# |
+ <A HREF="<% $p %>misc/send-statement.cgi?method=email;<% $link %>">Re-email this statement</A>
+% }
+
+% if ( 0 ) {
+% #if ( $conf->exists('hylafax') && length($cust_statement->cust_main->fax) ) {
+ | <A HREF="<% $p %>misc/send-statement.cgi?method=fax;<% $link %>">Re-fax this statement</A>
+% }
+
+ <BR><BR>
+
+% }
+
+
+% #if ( $conf->exists('invoice_latex') ) {
+% if ( 0 ) { #broken???
+
+ <A HREF="<% $p %>view/cust_statement-pdf.cgi?<% $link %>">View typeset statement</A>
+ <BR><BR>
+% }
+
+% #if ( $cust_statement->num_cust_event ) {
+% if ( 0 ) {
+<A HREF="<%$p%>search/cust_event.html?statementnum=<% $cust_statement->statementnum %>">(&nbsp;View statement events&nbsp;)</A><BR><BR>
+% }
+
+% if ( $conf->exists('invoice_html') ) {
+
+ <% join('', $cust_statement->print_html('', $templatename) ) %>
+% } else {
+
+ <PRE><% join('', $cust_statement->print_text('', $templatename) ) %></PRE>
+% }
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint statement
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $templatename = $2 || 'statement'; #XXX configure... via event?? eh..
+my $statementnum = $3;
+
+my $conf = new FS::Conf;
+
+my @payby = grep /\w/, $conf->config('payby');
+#@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
+@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
+ unless @payby;
+my %payby = map { $_=>1 } @payby;
+
+my $cust_statement = qsearchs({
+ 'select' => 'cust_statement.*',
+ 'table' => 'cust_statement',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'statementnum' => $statementnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Statement #$statementnum not found!" unless $cust_statement;
+
+my $custnum = $cust_statement->custnum;
+my $display_custnum = $cust_statement->cust_main->display_custnum;
+
+my $link = "statementnum=$statementnum";
+$link .= ';template='. uri_escape($templatename) if $templatename;
+
+</%init>
diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html
index a0b4e37..852640e 100644
--- a/httemplate/view/elements/svc_Common.html
+++ b/httemplate/view/elements/svc_Common.html
@@ -1,30 +1,40 @@
-% # options example...
-% #
-% # 'table' => 'svc_something'
-% #
-% # 'labels' => {
-% # 'column' => 'Label',
-% # },
-% #
-% # listref - each item is a literal column name (or method) or (notyet) coderef
-% # if not specified all columns (except for the primary key) will be viewable
-% # 'fields' => [
-% # ]
-% #
-% # # defaults to "edit/$table.cgi?", will have svcnum appended
-% # 'edit_url' =>
-%
-%
-% if ( $custnum ) {
+<%doc>
+
+#Example:
+
+ include( 'elements/svc_Common.html,
+
+ 'table' => 'svc_something'
+ 'labels' => {
+ 'column' => 'Label',
+ },
+
+ #listref - each item is a literal column name (or method) or
+ # (notyet) coderef. if not specified all columns (except for the
+ #primary key) will be viewable
+ 'fields' => [
+ ]
+
+ # defaults to "edit/$table.cgi?", will have svcnum appended
+ 'edit_url' =>
+ )
+
+</%doc>
+% if ( $custnum ) {
<% include("/elements/header.html","View $label: $value") %>
<% include( '/elements/small_custview.html', $custnum, '', 1,
"${p}view/cust_main.cgi") %>
<BR>
+
% } else {
+ <% include("/elements/header.html","View $label: $value", menubar(
+ "Cancel this (unaudited) $label" =>
+ "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')"
+ )) %>
<SCRIPT>
function areyousure(href) {
@@ -33,13 +43,8 @@
}
</SCRIPT>
- <% include("/elements/header.html","View $label: $value", menubar(
- "Cancel this (unaudited) $label" =>
- "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')"
- )) %>
% }
-
Service #<B><% $svcnum %></B>
% my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
| <A HREF="<%$url%><%$svcnum%>">Edit this <% $label %></A>
@@ -130,7 +135,9 @@ my $svc_x = qsearchs({
' LEFT JOIN cust_pkg USING ( pkgnum ) '.
' LEFT JOIN cust_main USING ( custnum ) ',
'hashref' => { 'svcnum' => $svcnum },
- 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ ),
}) or die "Unknown svcnum $svcnum in ". $opt{'table'}. " table\n";
my $cust_svc = $svc_x->cust_svc;
@@ -138,6 +145,14 @@ my($label, $value, $svcdb) = $cust_svc->label;
my $part_svc = $cust_svc->part_svc;
+ #false laziness w/edit/svc_Common.html
+ #override default labels with service-definition labels if applicable
+ my $labels = $opt{labels}; #not -> here
+ foreach my $field ( keys %$labels ) {
+ my $col = $part_svc->part_svc_column($field);
+ $labels->{$field} = $col->columnlabel if $col->columnlabel !~ /^\S*$/;
+ }
+
my $pkgnum = $cust_svc->pkgnum;
my($cust_pkg, $custnum);
diff --git a/httemplate/view/svc_Common.html b/httemplate/view/svc_Common.html
index bb3a6dd..defbee9 100644
--- a/httemplate/view/svc_Common.html
+++ b/httemplate/view/svc_Common.html
@@ -1,3 +1,9 @@
+<% include('elements/svc_Common.html',
+ 'table' => $table,
+ 'edit_url' => $p."edit/svc_Common.html?svcdb=$table;svcnum=",
+ %opt,
+ )
+%>
<%init>
# false laziness w/edit/svc_Common.html
@@ -21,9 +27,3 @@ if ( UNIVERSAL::can("FS::$table", 'table_info') ) {
}
</%init>
-<% include('elements/svc_Common.html',
- 'table' => $table,
- 'edit_url' => $p."edit/svc_Common.html?svcdb=$table;svcnum=",
- %opt,
- )
-%>
diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi
index e87a8ee..6a47ec7 100755
--- a/httemplate/view/svc_acct.cgi
+++ b/httemplate/view/svc_acct.cgi
@@ -214,7 +214,7 @@ Service #<B><% $svcnum %></B>
% if ($svc_acct->finger ne '') {
<TR>
- <TD ALIGN="right">GECOS</TD>
+ <TD ALIGN="right">Real Name</TD>
<TD BGCOLOR="#ffffff"><% $svc_acct->finger %></TD>
</TR>
% }
diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi
index 145d341..1463925 100644
--- a/httemplate/view/svc_broadband.cgi
+++ b/httemplate/view/svc_broadband.cgi
@@ -8,7 +8,9 @@
))
%>
-<A HREF="<%${p}%>edit/svc_broadband.cgi?<%$svcnum%>">Edit this information</A>
+<% include('/elements/init_overlib.html') %>
+
+<A HREF="<%$p%>edit/svc_broadband.cgi?<%$svcnum%>">Edit this information</A>
<BR>
<%ntable("#cccccc")%>
<TR>
@@ -22,10 +24,14 @@
<TD ALIGN="right">Description</TD>
<TD BGCOLOR="#ffffff"><%$description%></TD>
</TR>
- <TR>
- <TD ALIGN="right">Router</TD>
- <TD BGCOLOR="#ffffff"><%$routernum%>: <%$routername%></TD>
- </TR>
+
+% if ( $router ) {
+ <TR>
+ <TD ALIGN="right">Router</TD>
+ <TD BGCOLOR="#ffffff"><%$router->routernum%>: <%$router->routername%></TD>
+ </TR>
+% }
+
<TR>
<TD ALIGN="right">Download Speed</TD>
<TD BGCOLOR="#ffffff"><%$speed_down%></TD>
@@ -34,18 +40,25 @@
<TD ALIGN="right">Upload Speed</TD>
<TD BGCOLOR="#ffffff"><%$speed_up%></TD>
</TR>
- <TR>
- <TD ALIGN="right">IP Address</TD>
- <TD BGCOLOR="#ffffff"><%$ip_addr%></TD>
- </TR>
- <TR>
- <TD ALIGN="right">IP Netmask</TD>
- <TD BGCOLOR="#ffffff"><%$ip_netmask%></TD>
- </TR>
- <TR>
- <TD ALIGN="right">IP Gateway</TD>
- <TD BGCOLOR="#ffffff"><%$ip_gateway%></TD>
- </TR>
+
+% if ( $ip_addr ) {
+ <TR>
+ <TD ALIGN="right">IP Address</TD>
+ <TD BGCOLOR="#ffffff">
+ <%$ip_addr%>
+ (<% include('/elements/popup_link-ping.html', 'ip'=>$ip_addr ) %>)
+ </TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">IP Netmask</TD>
+ <TD BGCOLOR="#ffffff"><%$addr_block->NetAddr->mask%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">IP Gateway</TD>
+ <TD BGCOLOR="#ffffff"><%$addr_block->ip_gateway%></TD>
+ </TR>
+% }
+
<TR>
<TD ALIGN="right">MAC Address</TD>
<TD BGCOLOR="#ffffff"><%$mac_addr%></TD>
@@ -173,18 +186,14 @@ if ($pkgnum) {
#eofalse
my $addr_block = $svc_broadband->addr_block;
-my $router = $addr_block->router;
+my $router = $addr_block->router if $addr_block;
-if (not $router) { die "Could not lookup router for svc_broadband (svcnum $svcnum)" };
+#if (not $router) { die "Could not lookup router for svc_broadband (svcnum $svcnum)" };
my (
- $routername,
- $routernum,
$speed_down,
$speed_up,
$ip_addr,
- $ip_gateway,
- $ip_netmask,
$mac_addr,
$latitude,
$longitude,
@@ -193,13 +202,9 @@ my (
$auth_key,
$description,
) = (
- $router->getfield('routername'),
- $router->getfield('routernum'),
$svc_broadband->getfield('speed_down'),
$svc_broadband->getfield('speed_up'),
$svc_broadband->getfield('ip_addr'),
- $addr_block->ip_gateway,
- $addr_block->NetAddr->mask,
$svc_broadband->mac_addr,
$svc_broadband->latitude,
$svc_broadband->longitude,
diff --git a/httemplate/view/svc_domain.cgi b/httemplate/view/svc_domain.cgi
index 8c1f4ce..fc099d8 100755
--- a/httemplate/view/svc_domain.cgi
+++ b/httemplate/view/svc_domain.cgi
@@ -7,9 +7,29 @@
)
)) %>
+<% include('/elements/error.html') %>
+
Service #<% $svcnum %>
<BR>Service: <B><% $part_svc->svc %></B>
<BR>Domain name: <B><% $domain %></B>
+% if ($export) {
+<BR>Status: <B><% $status %></B>
+% if ( $FS::CurrentUser::CurrentUser->access_right('Manage domain registration') ) {
+% if ( defined($ops{'register'}) ) {
+ <A HREF="<% ${p} %>edit/process/domreg.cgi?op=register&svcnum=<% $svcnum %>">Register at <% $registrar->{'name'} %></A>&nbsp;
+% }
+% if ( defined($ops{'transfer'}) ) {
+ <A HREF="<% ${p} %>edit/process/domreg.cgi?op=transfer&svcnum=<% $svcnum %>">Transfer to <% $registrar->{'name'} %></A>&nbsp;
+% }
+% if ( defined($ops{'renew'}) ) {
+ <A HREF="<% ${p} %>edit/process/domreg.cgi?op=renew&svcnum=<% $svcnum %>&period=1">Renew at <% $registrar->{'name'} %></A>&nbsp;
+% }
+% if ( defined($ops{'revoke'}) ) {
+ <A HREF="<% ${p} %>edit/process/domreg.cgi?op=revoke&svcnum=<% $svcnum %>">Revoke</A>
+% }
+% }
+% }
+
% if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall') ) {
<BR>Catch all email <A HREF="<% ${p} %>misc/catchall.cgi?<% $svcnum %>">(change)</A>:
% } else {
@@ -138,9 +158,9 @@ my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
my $pkgnum = $cust_svc->getfield('pkgnum');
my($cust_pkg, $custnum, $display_custnum);
if ($pkgnum) {
- $cust_pkg =qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ $cust_pkg = qsearchs('cust_pkg', {'pkgnum'=>$pkgnum} );
$custnum = $cust_pkg->custnum;
- $custnum = $cust_pkg->cust_main->display_custnum;
+ $display_custnum = $cust_pkg->cust_main->display_custnum;
} else {
$cust_pkg = '';
$custnum = '';
@@ -158,4 +178,37 @@ if ($svc_domain->catchall) {
my $domain = $svc_domain->domain;
+my $status = 'Unknown';
+my %ops = ();
+
+my @exports = $part_svc->part_export();
+
+my $registrar;
+my $export;
+
+# Find the first export that does domain registration
+foreach (@exports) {
+ $export = $_ if $_->can('registrar');
+}
+# If we have a domain registration export, get the registrar object
+if ($export) {
+ $registrar = $export->registrar;
+ my $domstat = $export->get_status( $svc_domain );
+ if (defined($domstat->{'message'})) {
+ $status = $domstat->{'message'};
+ } elsif (defined($domstat->{'unregistered'})) {
+ $status = 'Not registered';
+ $ops{'register'} = "Register";
+ } elsif (defined($domstat->{'status'})) {
+ $status = $domstat->{'status'} . ' ' . $domstat->{'contact_email'} . ' ' . $domstat->{'last_update_time'};
+ } elsif (defined($domstat->{'expdate'})) {
+ $status = "Expires " . $domstat->{'expdate'};
+ $ops{'renew'} = "Renew";
+ $ops{'revoke'} = "Revoke";
+ } else {
+ $status = $domstat->{'reason'};
+ $ops{'transfer'} = "Transfer";
+ }
+}
+
</%init>
diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi
index f604daa..09d5be4 100644
--- a/httemplate/view/svc_phone.cgi
+++ b/httemplate/view/svc_phone.cgi
@@ -22,6 +22,74 @@
my $html_foot = sub {
my $svc_phone = shift;
+ ###
+ # Devices
+ ###
+
+ my $devices = '';
+
+ my $sth = dbh->prepare("SELECT COUNT(*) FROM part_device") #WHERE disabled = '' OR disabled IS NULL;");
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my $num_part_device = $sth->fetchrow_arrayref->[0];
+
+ my @phone_device = $svc_phone->phone_device;
+ if ( @phone_device || $num_part_device ) {
+ my $svcnum = $svc_phone->svcnum;
+ $devices .=
+ qq[Devices (<A HREF="${p}edit/phone_device.html?svcnum=$svcnum">Add device</A>)<BR>];
+ if ( @phone_device ) {
+
+ $devices .= qq!
+ <SCRIPT>
+ function areyousure(href) {
+ if (confirm("Are you sure you want to delete this device?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+ !;
+
+
+ $devices .=
+ include('/elements/table-grid.html').
+ '<TR>'.
+ '<TH CLASS="grid" BGCOLOR="#cccccc">Type</TH>'.
+ '<TH CLASS="grid" BGCOLOR="#cccccc">MAC Addr</TH>'.
+ '<TH CLASS="grid" BGCOLOR="#cccccc"></TH>'.
+ '</TR>';
+ my $bgcolor1 = '#eeeeee';
+ my $bgcolor2 = '#ffffff';
+ my $bgcolor = '';
+
+ foreach my $phone_device ( @phone_device ) {
+
+ if ( $bgcolor eq $bgcolor1 ) {
+ $bgcolor = $bgcolor2;
+ } else {
+ $bgcolor = $bgcolor1;
+ }
+ my $td = qq(<TD CLASS="grid" BGCOLOR="$bgcolor">);
+
+ my $devicenum = $phone_device->devicenum;
+
+ $devices .= '<TR>'.
+ $td. $phone_device->part_device->devicename. '</TD>'.
+ $td. $phone_device->mac_addr. '</TD>'.
+ "$td( ".
+ qq(<A HREF="${p}edit/phone_device.html?$devicenum">edit</A> | ).
+ qq(<A HREF="javascript:areyousure('${p}misc/delete-phone_device.html?$devicenum')">delete</A>).
+ ' )</TD>'.
+ '</TR>';
+ }
+ $devices .= '</TABLE><BR>';
+ }
+ $devices .= '<BR>';
+ }
+
+ ##
+ # CDR links
+ ##
+
tie my %what, 'Tie::IxHash',
'pending' => 'NULL',
'billed' => 'done',
@@ -43,9 +111,14 @@ my $html_foot = sub {
"View $_ CDRs</A>";
} keys(%what);
- my @ilinks = ( qq(<A HREF="${p}search/cdr.html?dst=$number">).
+ my @ilinks = ( qq(<A HREF="${p}search/cdr.html?cdrbatch=__ALL__;dst=$number">).
'View incoming CDRs</A>' );
+ ###
+ # concatenate & return
+ ###
+
+ $devices.
join(' | ', @links ). '<BR>'.
join(' | ', @ilinks). '<BR>';
diff --git a/init.d/freeside-init b/init.d/freeside-init
index c9bcebe..b4609d4 100644
--- a/init.d/freeside-init
+++ b/init.d/freeside-init
@@ -8,6 +8,8 @@ QUEUED_USER=%%%QUEUED_USER%%%
SELFSERVICE_USER=%%%SELFSERVICE_USER%%%
SELFSERVICE_MACHINES="%%%SELFSERVICE_MACHINES%%%"
+IF=eth0
+
#INSTALLSCRIPT/INSTALLSITEBIN from Makefile.PL
PATH="$PATH:/usr/local/bin"
export PATH
@@ -18,7 +20,10 @@ case "$1" in
start)
# Start daemons.
echo -n "Starting freeside-queued: "
+ #perl -MDBIx::Profile /usr/local/bin/freeside-queued $QUEUED_USER
freeside-queued $QUEUED_USER
+ #export NYTPROF="file=/usr/local/etc/freeside/nytprof.out"
+ #PERL5OPT="-d:NYTProf" freeside-queued $QUEUED_USER
echo "done."
echo -n "Starting freeside-sqlradius-radacctd: "
@@ -43,6 +48,10 @@ case "$1" in
echo "done."
done
+ #ip=`/sbin/ifconfig $IF | grep 'inet addr:' | cut -d: -f2- | cut -d' ' -f1`
+ #cp /opt/rt3/etc/RT_SiteConfig.pm.ORIG /opt/rt3/etc/RT_SiteConfig.pm
+ #perl -pi -e "s/localhost/$ip/" /opt/rt3/etc/RT_SiteConfig.pm
+
;;
stop)
# Stop daemons.
diff --git a/rpm/freeside.spec b/rpm/freeside.spec
index 77b5061..9312270 100644
--- a/rpm/freeside.spec
+++ b/rpm/freeside.spec
@@ -1,6 +1,6 @@
%{!?_initrddir:%define _initrddir /etc/rc.d/init.d}
-%{!?version:%define version 1.9}
-%{!?release:%define release 6}
+%{!?version:%define version 1.9.1}
+%{!?release:%define release 8}
Summary: Freeside ISP Billing System
Name: freeside
@@ -17,8 +17,10 @@ Requires: %{name}-frontend
Requires: %{name}-backend
%if "%{_vendor}" != "suse"
Requires: tetex-latex
+Requires: ghostscript
%else
Requires: te_latex
+Requires: ghostscript-library
%endif
Requires: perl-Fax-Hylafax-Client
@@ -48,11 +50,13 @@ Requires: perl-Fax-Hylafax-Client
%define fs_cron_user fs_daily
%define db_types Pg mysql
+%define texmflocal /usr/share/texmf
+
%define _rpmlibdir /usr/lib/rpm
%define rpmfiles rpm
%description
-Freeside is a flexible ISP billing system written by Ivan Kohler
+Freeside is a flexible ISP billing system
%package mason
Summary: HTML::Mason interface for %{name}
@@ -135,7 +139,7 @@ For security reasons, it is set to conflict with %{name} as you should not insta
%prep
%setup -q
-%{__rm} bin/pod2x # Only useful to Ivan Kohler now
+%{__rm} -f bin/pod2x # Only useful to Ivan Kohler now
perl -pi -e 's|/usr/local/bin|%{_bindir}|g' FS/Makefile.PL
# RPM handles changing file ownership, so Makefile shouldn't
perl -pi -e 's/\s+-o\s+(freeside|root)(\s+-g\s+\$\{\w+\})?\s+/ /g' Makefile
@@ -144,6 +148,7 @@ perl -ni -e 'print if !/\s+chown\s+/;' Makefile
# Fix-ups for self-service. Should merge this into Makefile
perl -pi -e 's|/usr/local/sbin|%{_sbindir}|g' FS/bin/freeside-selfservice-server
perl -pi -e 's|/usr/local/bin|%{_bindir}|g' fs_selfservice/FS-SelfService/Makefile.PL
+perl -pi -e 's|/usr/local/sbin|%{_sbindir}|g' fs_selfservice/FS-SelfService/Makefile.PL
perl -pi -e 's|/usr/local/freeside|%{freeside_socket}|g' fs_selfservice/FS-SelfService/*.pm
perl -pi -e 's|socket\s*=\s*"/usr/local/freeside|socket = "%{freeside_socket}|g' fs_selfservice/FS-SelfService/freeside-selfservice-*
perl -pi -e 's|log_file\s*=\s*"/usr/local/freeside|log_file = "%{freeside_log}|g' fs_selfservice/FS-SelfService/freeside-selfservice-*
@@ -161,6 +166,7 @@ cat << \EOF > %{name}-req
tee %{_tmppath}/filelist | %{_rpmlibdir}/rpmdeps --requires | grep -v -E '^perl\(the\)$' \
| grep -v -E '^perl\((lib|strict|vars|RT)\)$' \
| grep -v -E '^perl\(RT::' \
+| grep -v -E '^perl\(FS::' \
| sort -u
grep handler.pl %{_tmppath}/filelist | xargs %{_rpmlibdir}/perldeps.pl --requires \
| grep -v -E '^perl\((lib|strict|vars|RT)\)$' \
@@ -189,7 +195,7 @@ else
fi
%{__make} OPTIMIZE="$RPM_OPT_FLAGS"
cd ..
-%{__make} perl-modules VERSION='%{version}-%{release}' RT_ENABLED=%{rt_enabled} FREESIDE_CACHE=%{freeside_cache} FREESIDE_CONF=%{freeside_conf} FREESIDE_EXPORT=%{freeside_export} FREESIDE_LOCK=%{freeside_lock} FREESIDE_LOG=%{freeside_log}
+%{__make} perl-modules RT_ENABLED=%{rt_enabled} FREESIDE_CACHE=%{freeside_cache} FREESIDE_CONF=%{freeside_conf} FREESIDE_EXPORT=%{freeside_export} FREESIDE_LOCK=%{freeside_lock} FREESIDE_LOG=%{freeside_log}
touch perl-modules
cd fs_selfservice/FS-SelfService
@@ -209,17 +215,17 @@ cd ../..
touch install-perl-modules perl-modules
%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_cache}
%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_conf}
-#%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_export}
+%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_export}
%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_lock}
%{__mkdir_p} $RPM_BUILD_ROOT%{freeside_log}
for DBTYPE in %{db_types}; do
%{__mkdir_p} $RPM_BUILD_ROOT/tmp
[ -d $RPM_BUILD_ROOT%{freeside_conf}/default_conf ] && %{__rm} -rf $RPM_BUILD_ROOT%{freeside_conf}/default_conf
- %{__make} create-config DB_TYPE=$DBTYPE DATASOURCE=DBI:$DBTYPE:dbname=%{name} RT_ENABLED=%{rt_enabled} FREESIDE_CACHE=$RPM_BUILD_ROOT%{freeside_cache} FREESIDE_CONF=$RPM_BUILD_ROOT/tmp FREESIDE_EXPORT=$RPM_BUILD_ROOT%{freeside_export} FREESIDE_LOCK=$RPM_BUILD_ROOT%{freeside_lock} FREESIDE_LOG=$RPM_BUILD_ROOT%{freeside_log}
- %{__mv} $RPM_BUILD_ROOT/tmp/* $RPM_BUILD_ROOT%{freeside_conf}
- /bin/rmdir $RPM_BUILD_ROOT/tmp
+ %{__make} create-config DB_TYPE=$DBTYPE DATASOURCE=DBI:$DBTYPE:dbname=%{name} RT_ENABLED=%{rt_enabled} FREESIDE_CACHE=$RPM_BUILD_ROOT%{freeside_cache} FREESIDE_CONF=$RPM_BUILD_ROOT/tmp FREESIDE_EXPORT=$RPM_BUILD_ROOT%{freeside_export} FREESIDE_LOCK=$RPM_BUILD_ROOT%{freeside_lock} FREESIDE_LOG=$RPM_BUILD_ROOT%{freeside_log} DIST_CONF=$RPM_BUILD_ROOT%{freeside_conf}/default_conf
+ %{__mv} $RPM_BUILD_ROOT/tmp/secrets $RPM_BUILD_ROOT%{freeside_conf}
+ %{__rm} -rf $RPM_BUILD_ROOT/tmp
done
-%{__rm} install-perl-modules perl-modules $RPM_BUILD_ROOT%{freeside_conf}/conf*/ticket_system
+%{__rm} install-perl-modules perl-modules $RPM_BUILD_ROOT%{freeside_conf}/default_conf/ticket_system
touch docs
%{__perl} -pi -e "s|%%%%%%FREESIDE_DOCUMENT_ROOT%%%%%%|%{freeside_document_root}|g" htetc/handler.pl
@@ -327,29 +333,47 @@ cd ../..
%{__install} %{rpmfiles}/freeside-selfservice.conf $RPM_BUILD_ROOT%{apache_confdir}/%{name}-selfservice.conf
%{__perl} -pi -e "s|%%%%%%FREESIDE_SELFSERVICE_DOCUMENT_ROOT%%%%%%|%{freeside_selfservice_document_root}|g" $RPM_BUILD_ROOT%{apache_confdir}/%{name}-selfservice.conf
+# This is part of Makefile's install-texmf. The rest is in triggers. These files are not in the filelist
+%{__install} -D etc/fslongtable.sty $RPM_BUILD_ROOT%{texmflocal}/tex/generic/fslongtable.sty
+
%pre
if ! %{__id} freeside &>/dev/null; then
- /usr/sbin/useradd freeside
+%if "%{_vendor}" == "suse"
+ /usr/sbin/groupadd freeside
+%endif
+ /usr/sbin/useradd -m freeside
fi
%pre mason
if ! %{__id} freeside &>/dev/null; then
- /usr/sbin/useradd freeside
+%if "%{_vendor}" == "suse"
+ /usr/sbin/groupadd freeside
+%endif
+ /usr/sbin/useradd -m freeside
fi
%pre postgresql
if ! %{__id} freeside &>/dev/null; then
- /usr/sbin/useradd freeside
+%if "%{_vendor}" == "suse"
+ /usr/sbin/groupadd freeside
+%endif
+ /usr/sbin/useradd -m freeside
fi
%pre mysql
if ! %{__id} freeside &>/dev/null; then
- /usr/sbin/useradd freeside
+%if "%{_vendor}" == "suse"
+ /usr/sbin/groupadd freeside
+%endif
+ /usr/sbin/useradd -m freeside
fi
%pre selfservice-cgi
if ! %{__id} freeside &>/dev/null; then
- /usr/sbin/useradd freeside
+%if "%{_vendor}" == "suse"
+ /usr/sbin/groupadd freeside
+%endif
+ /usr/sbin/useradd -m freeside
fi
%post
@@ -389,6 +413,10 @@ if ! %{__grep} TEXINPUTS /etc/init.d/apache2 >/dev/null; then
fi
%endif
+%triggerin -- tetex
+#texhash `kpsewhich -expand-var \$TEXMFLOCAL`
+texhash %{texmflocal}
+
%clean
%{__rm} -rf %{buildroot}
@@ -400,7 +428,9 @@ fi
%attr(-,freeside,freeside) %dir %{freeside_conf}
%attr(-,freeside,freeside) %dir %{freeside_lock}
%attr(-,freeside,freeside) %dir %{freeside_log}
-%attr(0644,freeside,freeside) %config(noreplace) %{freeside_conf}/default_conf
+%attr(0711,freeside,freeside) %config(noreplace) %{freeside_conf}/default_conf
+%attr(0644,freeside,freeside) %config(noreplace) %{freeside_conf}/default_conf/*
+%attr(444,root,root) %{texmflocal}/tex/generic/fslongtable.sty
%files mason -f %{name}-%{version}-%{release}-mason-filelist
%defattr(-, freeside, freeside, 0755)
@@ -431,6 +461,9 @@ fi
%attr(0755,freeside,freeside) %{freeside_selfservice_document_root}/php
%changelog
+* Thu Jun 11 2009 Richard Siddall <richard.siddall@elirion.net> - 1.9-8
+- Since configuration is now kept in the RDBMS, don't install a configuration folder
+
* Mon Dec 22 2008 Richard Siddall <richard.siddall@elirion.net> - 1.9-5
- Modifications to make self-service work if you really insist on installing it on the same machine as Freeside
diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED
index 6691779..e820789 100644
--- a/rt/FREESIDE_MODIFIED
+++ b/rt/FREESIDE_MODIFIED
@@ -4,6 +4,7 @@ config.layout.in
etc/RT_SiteConfig.pm
lib/RT/Interface/Web_Vendor.pm
lib/RT/SearchBuilder.pm #need DBIx::SearchBuilder >= 1.36 for Pg 8.1+
+lib/RT/Transaction_Overlay.pm
lib/RT/URI/freeside.pm
lib/RT/URI/freeside/Internal.pm
lib/RT/URI/freeside/XMLRPC.pm
@@ -11,10 +12,13 @@ lib/RT/URI/freeside/XMLRPC.pm
html/Elements/Menu
html/Elements/PageLayout
html/Elements/QuickCreate
+ html/Elements/SelectDate
html/Elements/SimpleSearch
html/Elements/Tabs
html/Elements/Footer
html/Elements/CollectionAsTable/Row #backport from 3.3-TESTING
+ html/Ticket/Create.html
+ html/Ticket/Display.html
html/Ticket/Elements/AddCustomers
html/Ticket/Elements/EditCustomers
html/Ticket/Elements/ShowCustomers
@@ -23,6 +27,8 @@ html/Ticket/Elements/ShowCustomers
html/Ticket/ModifyCustomers.html
html/NoAuth/images/small-logo.png
html/NoAuth/css/3.5-default/main.css
+ html/NoAuth/css/3.5-default/misc.css
+ html/NoAuth/css/3.5-default/titlebox.css
html/NoAuth/css/3.5-default/freeside.css
html/Widgets/TitleBoxStart
@@ -31,4 +37,5 @@ html/Elements/FreesideNewCust
html/Elements/FreesideSearch
html/Elements/FreesideSvcSearch
-
+ html/User/Prefs.html
+ html/Prefs/SearchOptions.html
diff --git a/rt/Makefile b/rt/Makefile
index e6a5dde..7d510c8 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -60,7 +60,7 @@ SITE_CONFIG_FILE = $(CONFIG_FILE_PATH)/RT_SiteConfig.pm
RT_VERSION_MAJOR = 3
RT_VERSION_MINOR = 6
-RT_VERSION_PATCH = 4
+RT_VERSION_PATCH = 6
RT_VERSION = $(RT_VERSION_MAJOR).$(RT_VERSION_MINOR).$(RT_VERSION_PATCH)
TAG = rt-$(RT_VERSION_MAJOR)-$(RT_VERSION_MINOR)-$(RT_VERSION_PATCH)
@@ -83,7 +83,7 @@ WEB_USER = freeside
WEB_GROUP = freeside
-APACHECTL = /usr/sbin/apachectl
+APACHECTL =
# {{{ Files and directories
diff --git a/rt/etc/RT_SiteConfig.pm b/rt/etc/RT_SiteConfig.pm
index c3d6a66..7a6f407 100644
--- a/rt/etc/RT_SiteConfig.pm
+++ b/rt/etc/RT_SiteConfig.pm
@@ -49,4 +49,6 @@ $RT::QuickCreateLong = 0; #set to true to cause quick ticket creation to
#redirect to the "long" ticket creation screen
#instead of just creating a ticket with the subject.
+Set($MessageBoxWidth , 80);
+
1;
diff --git a/rt/html/Elements/Footer b/rt/html/Elements/Footer
index 0cb528f..6604bd2 100644
--- a/rt/html/Elements/Footer
+++ b/rt/html/Elements/Footer
@@ -52,26 +52,26 @@
<tr>
<td>
<& /Elements/Callback, %ARGS &>
-<div id="footer">
- <p id="time">
- <span><&|/l&>Time to display</&>: <%Time::HiRes::tv_interval( $m->{'rt_base_time'} )%></span>
- </p>
-<!--
- <p id="bpscredits">
- <span>
-<&|/l, '&#187;&#124;&#171;', $RT::VERSION, '2006', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
-</span>
-</p>
-% if (!$Menu) {
- <p id="legal">
-<&|/l&>Distributed under version 2 <a href="http://www.gnu.org/copyleft/gpl.html"> of the GNU GPL.</a></&><br />
-<&|/l, '<a href="mailto:sales@bestpractical.com">sales@bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br />
- </p>
-% }
+%# <div id="footer">
+%# <p id="time">
+%# <span><&|/l&>Time to display</&>: <%Time::HiRes::tv_interval( $m->{'rt_base_time'} )%></span>
+%# </p>
+
+%# <p id="bpscredits">
+%# <span>
+%# <&|/l, '&#187;&#124;&#171;', $RT::VERSION, '2006', '<a href="http://www.bestpractical.com?rt='.$RT::VERSION.'">Best Practical Solutions, LLC</a>', &>[_1] RT [_2] Copyright 1996-[_3] [_4].</&>
+%# </span>
+%# </p>
+%# % if (!$Menu) {
+%# <p id="legal">
+%# <&|/l&>Distributed under version 2 <a href="http://www.gnu.org/copyleft/gpl.html"> of the GNU GPL.</a></&><br />
+%# <&|/l, '<a href="mailto:sales@bestpractical.com">sales@bestpractical.com</a>' &>To inquire about support, training, custom development or licensing, please contact [_1].</&><br />
+%# </p>
+%# % }
+
+%# </div>
-</div>
--->
% if ($Debug >= 2 ) {
% require Data::Dumper;
% my $d = Data::Dumper->new([\%ARGS], [qw(%ARGS)]);
diff --git a/rt/html/Elements/FreesideSvcSearch b/rt/html/Elements/FreesideSvcSearch
index 4a59424..d68122d 100644
--- a/rt/html/Elements/FreesideSvcSearch
+++ b/rt/html/Elements/FreesideSvcSearch
@@ -1,3 +1,4 @@
+% if ( $FS::CurrentUser::CurrentUser->access_right('View customer services') ) {
<form action="<% $RT::URI::freeside::URL %>/search/cust_svc.html" STYLE="margin:0">
<SCRIPT TYPE="text/javascript">
function clearhint_search_svc (what) {
@@ -9,3 +10,4 @@
<A NOTYET="<% $RT::URI::freeside::URL %>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%; font-weight:normal">Advanced</A>
<input type="submit" value="<&|/l&>Search services</&>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
</form>
+% }
diff --git a/rt/html/Elements/Header b/rt/html/Elements/Header
index bf6fa46..a32784e 100644
--- a/rt/html/Elements/Header
+++ b/rt/html/Elements/Header
@@ -45,102 +45,17 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
-
-<title><%$Title%></title>
-
-% if ($Refresh && $Refresh > 0) {
- <meta http-equiv="refresh" content="<%$Refresh%>" />
-% }
-
-<link rel="shortcut icon" href="<%$RT::WebImagesURL%>/favicon.png" type="image/png" />
-<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/<% $RT::WebDefaultStylesheet %>/main-squished.css" type="text/css" media="all" />
-<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/print.css" type="text/css" media="print" />
-
-% if ( $RSSAutoDiscovery ) {
- <link rel="alternate" href="<%$RSSAutoDiscovery%>" type="application/rss+xml" title="RSS RT Search" />
-% }
-
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/util.js"></script>
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/ahah.js"></script>
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/titlebox-state.js"></script>
-<script type="text/javascript"><!--
- onLoadHook("loadTitleBoxStates()");
-% if ( $Focus ) {
- onLoadHook("focusElementById('<% $Focus %>')");
-% }
-% if ( $onload ) {
- onLoadHook("<% $onload |n %>");
-% }
---></script>
-
-<& /Elements/Callback, _CallbackName => 'Head', %ARGS &>
-
-</head>
- <body NOTBACKGROUND="<% $RT::URI::freeside::URL %>/images/background-cheat.png"
- STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0"
- <% $id && qq[ id="comp-$id"] |n %>
- >
-
-% if ($ShowBar) {
-
-<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF" STYLE="padding-left:0; padding-right:4">
- <tr>
- <td colspan=2 rowspan=2><img border=0 alt="freeside" src="<%$RT::WebImagesURL%>/small-logo.png" width="92" height="62"></td>
- <td align="left" rowspan=2><font size=6><% &RT::URI::freeside::FreesideGetConfig('company_name') || 'ExampleCo' %></font></td>
- <td align="right" valign="top">
-
-<div id="quickbar">
- <div id="quick-personal">
- <span class="hide"><a href="#skipnav"><&|/l&>Skip Menu</&></a> | </span>
-% if ($session{'CurrentUser'}->Name) {
- <&|/l, "<span>".$session{'CurrentUser'}->Name."</span>" &>Logged in as [_1]</&>
-% if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System )) {
- | <a href="<%$RT::WebPath%><%$Prefs%>"><&|/l&>Preferences</&></a>
-% }
-% } else {
- <&|/l&>Not logged in.</&>
-% }
- <& /Elements/Callback, %ARGS &>
-% unless (!$session{'CurrentUser'}->Name
-% or ($RT::WebExternalAuth and !$RT::WebFallbackToInternalAuth)) {
- | <a href="<%$RT::WebPath%>/NoAuth/Logout.html<%$URL ? "?URL=".$URL : ''%>"><&|/l&>Logout</&></a>
-% }
- </div>
-% }
-
- </td>
-
- </tr>
- <tr>
-
- <td align=right valign=bottom>
- <table>
- <tr>
- <td align=right>
- <FONT SIZE="-3">
- <A HREF="http://www.sisd.com/freeside">Freeside</A>&nbsp;v<% &RT::URI::freeside::FreesideVersion() %><BR>
- <A HREF="<% FS::Conf->new->config('support-key') ? "http://www.sisd.com/mediawiki/index.php/Supported:Documentation" : "http://www.sisd.com/mediawiki/index.php/Freeside:1.9:Documentation" %>">Documentation</A><BR>
- </FONT>
- </td>
- <td bgcolor=#000000></td>
- <td align=left>
- <FONT SIZE="-3">
- <A HREF="http://www.bestpractical.com/rt">RT</A>&nbsp;v<% $RT::VERSION %><BR>
- <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR>
- </FONT>
- </td>
-
- </tr>
- </table>
- </td>
-
- </tr>
-</table>
+<% include( '/elements/header.html', {
+ 'title' => $Title,
+ 'head' => $head,
+ 'nobr' => 1,
+ 'nocss' => 1,
+ }) |n
+%>
+
+%# if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System )) {
+%# | <a href="<%$RT::WebPath%><%$Prefs%>"><&|/l&>Preferences</&></a>
+%# }
<%INIT>
$r->headers_out->{'Pragma'} = 'no-cache';
@@ -155,6 +70,45 @@ $id =~ s|\.html$||g;
$id =~ s|index$||g
if $id ne 'index';
$id =~ s|-$||g;
+
+my $head = '';
+
+if ($Refresh && $Refresh > 0) {
+ $head .= '<meta http-equiv="refresh" content="$Refresh" />';
+}
+
+$head .= <<END;
+<link rel="shortcut icon" href="$RT::WebImagesURL/favicon.png" type="image/png" />
+<link rel="stylesheet" href="$RT::WebPath/NoAuth/css/$RT::WebDefaultStylesheet/main-squished.css" type="text/css" media="all" />
+<link rel="stylesheet" href="$RT::WebPath/NoAuth/css/print.css" type="text/css" media="print" />
+END
+
+if ( $RSSAutoDiscovery ) {
+ $head .= qq(<link rel="alternate" href="$RSSAutoDiscovery" type="application/rss+xml" title="RSS RT Search" />);
+}
+
+$head .= <<END;
+<script type="text/javascript" src="$RT::WebPath/NoAuth/js/util.js"></script>
+<script type="text/javascript" src="$RT::WebPath/NoAuth/js/ahah.js"></script>
+<script type="text/javascript" src="$RT::WebPath/NoAuth/js/titlebox-state.js"></script>
+<script type="text/javascript"><!--
+ onLoadHook("loadTitleBoxStates()");
+END
+
+if ( $Focus ) {
+ $head .= qq{ onLoadHook("focusElementById('$Focus')");\n};
+}
+if ( $onload ) {
+ $head .= qq{ onLoadHook("$onload");\n};
+}
+
+$head .= '--></script>';
+
+$head .= $m->scomp( '/Elements/Callback', _CallbackName => 'Head', %ARGS );
+
+my $etc = '';
+$etc .= qq[ id="comp-$id"] if $id;
+
</%INIT>
<%ARGS>
diff --git a/rt/html/Elements/PageLayout b/rt/html/Elements/PageLayout
index b9fd31f..b9d15e9 100644
--- a/rt/html/Elements/PageLayout
+++ b/rt/html/Elements/PageLayout
@@ -45,53 +45,116 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+% #false laziness w/menubar.html... shouldn't these just go in freeside.css?
+<style type="text/css">
+a.fsblackbutton {
+ background-color:#333333;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ font-size:16px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
+}
-<table class="black" border=0 cellspacing=0 cellpadding=0 width="100%">
-<tr>
- <TD colspan=5 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD>
-</tr>
-<tr>
-
- <div id="topactions">
-% my $notfirst = 0; foreach my $action (sort keys %{$topactions}) {
- <span class="topaction">
- <td class="blackright" ALIGN="right" VALIGN="center">
-% $m->out($topactions->{"$action"}->{'html'});
- </td>
- </span>
-% }
- </div>
-
-</tr>
-</table>
+a.fsblackbuttonselected,
+a:link:hover.fsblackbutton,
+a:visited:hover.fsblackbutton {
+ background-color:#7e0079;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ font-size:16px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
+}
-%# End of div#quickbar from /Elements/Header
-</div>
+a.fsdarkbutton {
+ background-color:#555555;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ font-size:16px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff555555',EndColorStr='#ff666666')
+}
+a.fsdarkbuttonselected,
+a:link:hover.fsdarkbutton,
+a:visited:hover.fsdarkbutton {
+ background-color:#7e0079;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ /*font-weight:bold;*/
+ /*padding-left:12px;
+ padding-right:12px;*/
+ padding-left:4px;
+ padding-right:4px;
+ font-size:16px;
+ text-decoration:none;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
+}
+</style>
+<% include('/elements/init_calendar.html') |n %>
<table border=0 cellspacing=0 cellpadding=0 width="100%" height="100%">
- <TR>
- <TD STYLE="padding:0" WIDTH="100%"><IMG BORDER=0 ALT="" SRC="<% $RT::URI::freeside::URL %>/images/black-gray-top.png" HEIGHT="13" WIDTH="100%"></TD>
- </TR>
<TR HEIGHT="100%">
- <TD>
+ <TD valign="top">
-% if ( $show_menu ) {
+% if (0) { ##FREESIDE MENUS INSTEAD## if ( $show_menu ) {
+%# if ( $show_menu ) {
<div id="nav">
<& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &>
</div>
% }
-<div id="header">
- <h1><%$title%></h1>
+%#already shown <h1><%$title%></h1>
% my $sep = 0;
% my $postsep = 0;
% my $count = 0;
% my $class = { };
%
- <ul id="page-menu"<% (($actions && %$actions) || ($subactions && %$subactions)) && q[ class="actions-present"] | n %>>
- <div><div><div>
+
+ <TABLE BGCOLOR="#000000" BORDER=0 CELLSPACING=0 CELLPADDING=0>
+ <TR>
+
+%# <ul id="page-menu"<% (($actions && %$actions) || ($subactions && %$subactions)) && q[ class="actions-present"] | n %>>
+
% if ($page_tabs) {
+ <TD><IMG SRC="<%$fsurl%>images/gray-black-side.png" WIDTH=13 HEIGHT=25></TD>
+ <TD>
% foreach my $tab (sort keys %{$page_tabs}) {
% next if $tab =~ /^(?:current_toptab|this)$/;
% $count++;
@@ -119,22 +182,24 @@
% $class->{li} = join ' ', @li;
%
%
- <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && "&#183; "|n%><a href="<%$RT::WebPath%>/<%$page_tabs->{$tab}->{'path'}%>"<%$class->{a}|n%><% $class->{a} ? ' name="focus"' : ''|n %>><% $page_tabs->{$tab}->{'title'} %></a></li>
-%
-% if ($sep) {
- <li class="separator">&#183;&#183;&#183;</li>
-% }
-% $postsep = $sep;
+
+%# <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && "&#183; "|n%><a href="<%$RT::WebPath%>/<%$page_tabs->{$tab}->{'path'}%>"<%$class->{a}|n%><% $class->{a} ? ' name="focus"' : ''|n %>><% $page_tabs->{$tab}->{'title'} %></a></li>
+
+% $class->{a} = $path eq $current ? ' class="fsblackbuttonselected"' : ' class="fsblackbutton"';
+ <a href="<%$RT::WebPath%>/<%$page_tabs->{$tab}->{'path'}%>"<%$class->{a}|n%><% $class->{a} =~ 'selected' ? ' name="focus"' : ''|n %>><% $page_tabs->{$tab}->{'title'} %></a>
+
% }
-% } else {
-&nbsp;
+ </TD>
+%# } else {
+%#&nbsp;
% }
- </div></div></div>
- </ul>
% if (($actions && %$actions) || ($subactions && %$subactions)) {
- <ul id="actions-menu">
- <div><div><div>
+ <TD><IMG SRC="<%$fsurl%>images/<% $page_tabs ? 'black-gray' : 'gray-black' %>-side.png" WIDTH=13 HEIGHT=25></TD>
+% if ( $page_tabs ) {
+ <TD BGCOLOR="#333333">&nbsp;&nbsp;</TD>
+% }
+ <TD BGCOLOR="#333333">
% $sep = 0;
% $postsep = 0;
% $count = 0;
@@ -160,24 +225,30 @@
%
% $class->{li} = join ' ', @li;
%
- <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%>
+
+%# <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%>
+
+% #$class->{a} = $path eq $current ? ' class="fsblackbuttonselected"' : ' class="fsblackbutton"';
+% $type->{$action}->{class} ||= 'fsdarkbutton';
+
% if ($type->{"$action"}->{'html'}) {
<% $type->{"$action"}->{'html'} | n %>
% } else {
<a href="<%$RT::WebPath%>/<%$type->{$action}->{'path'}%>"<% $type->{$action}->{class} && ' class="'.$type->{$action}->{class}.'"' |n %><% $type->{$action}->{id} && ' id="'.$type->{$action}->{id}.'"' |n %>><%$type->{$action}->{'title'}%></a>
% }
- </li>
-% if ($sep) {
- <li class="separator">&#183;&#183;&#183;</li>
-% }
-% $postsep = $sep;
+
% }
% }
% }
- </div></div></div>
- </ul>
+
+ </TD>
+
% }
-</div>
+
+ <TD><IMG SRC="<%$fsurl%>images/black-gray-side.png" WIDTH=13 HEIGHT=25></TD>
+ </TR>
+</TABLE>
+
<div id="body">
<& /Elements/Callback, _CallbackName => 'BeforeBody', %ARGS &>
diff --git a/rt/html/Elements/SelectDate b/rt/html/Elements/SelectDate
index b43f324..23df246 100644
--- a/rt/html/Elements/SelectDate
+++ b/rt/html/Elements/SelectDate
@@ -45,10 +45,21 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
+%# in PageLayout instead, once <% include('/elements/init_calendar.html') |n %>
+<input type="text" id="<% $Name %>" name="<% $Name %>" value="<% $Default %>" size="<% $Size %>" />
+<IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $Name %>_date_button" STYLE="cursor: pointer" TITLE="Select date">
<script type="text/javascript"><!--
- onLoadHook('createCalendarLink("<% $Name %>");');
+Calendar.setup({
+ inputField: "<%$Name%>",
+% if ( defined($ShowTime) && $ShowTime ) {
+ ifFormat: "%Y-%m-%d %H:%M",
+ showsTime: true,
+% } else {
+ ifFormat: "%Y-%m-%d",
+% }
+ button: "<%$Name%>_date_button",
+});
--></script>
-<input type="text" id="<% $Name %>" name="<% $Name %>" value="<% $Default %>" size="<% $Size %>" />
<%init>
unless ((defined $Default) or
($current <= 0)) {
diff --git a/rt/html/Elements/Tabs b/rt/html/Elements/Tabs
index 9d1eea6..36ecfa5 100644
--- a/rt/html/Elements/Tabs
+++ b/rt/html/Elements/Tabs
@@ -59,20 +59,6 @@
<a name="skipnav" id="skipnav" accesskey="8"></a>
<%INIT>
my $action;
-my $basetopactions = {
-# A => { html => $m->scomp('/Elements/CreateTicket')
-# },
- A => { html => $m->scomp('/Elements/FreesideNewCust')
- },
- B => { html => $m->scomp('/Elements/FreesideSearch')
- },
- C => { html => $m->scomp('/Elements/FreesideInvoiceSearch')
- },
- D => { html => $m->scomp('/Elements/FreesideSvcSearch')
- },
- E => { html => $m->scomp('/Elements/SimpleSearch')
- }
- };
my $basetabs = {
' A'=> { title => 'Billing Main',
path => &RT::URI::freeside::FreesideURL(),
@@ -112,9 +98,6 @@ if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf',
if (!defined $toptabs) {
$toptabs = $basetabs;
}
-if (!defined $topactions) {
- $topactions = $basetopactions;
-}
require RT::URI::freeside;
diff --git a/rt/html/NoAuth/css/3.5-default/freeside.css b/rt/html/NoAuth/css/3.5-default/freeside.css
index a595061..5e7e0a0 100644
--- a/rt/html/NoAuth/css/3.5-default/freeside.css
+++ b/rt/html/NoAuth/css/3.5-default/freeside.css
@@ -1,77 +1,3 @@
-.black {
- background-color: #000000;
- color: #ffffff;
- background-position: left top;
- vertical-align: top;
- text-align: left;
-}
-
-.blackright {
- background-color: #000000;
- color: #ffffff;
- background-position: left top;
- vertical-align: center;
- text-align: right;
- font-size:16px;
- padding-right:4px
-}
-
-input.fsblackbutton {
- background-color:#333333;
- color: #ffffff;
- border:1px solid;
- border-top-color:#cccccc;
- border-left-color:#cccccc;
- border-right-color:#aaaaaa;
- border-bottom-color:#aaaaaa;
- font-family: Arial, Verdana, Helvetica, sans-serif;
- font-weight:bold;
- padding-left:12px;
- padding-right:12px;
- overflow:visible;
- filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
-}
-
-input.fsblackbuttonselected {
- background-color:#7e0079;
- color: #ffffff;
- border:1px solid;
- border-top-color:#cccccc;
- border-left-color:#cccccc;
- border-right-color:#aaaaaa;
- border-bottom-color:#aaaaaa;
- font-family: Arial, Verdana, Helvetica, sans-serif;
- font-weight:bold;
- padding-left:12px;
- padding-right:12px;
- overflow:visible;
- filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
-}
-
-.darkmediumgray {
- background-color: #aaaaaa;
- background-position: left top;
- vertical-align: top;
- text-align: left;
-}
-.darkmediumgrayright {
- background-color: #aaaaaa;
- background-position: left top;
- vertical-align: top;
- text-align: right;
-}
-.bggray {
- background-color: #e8e8e8;
- background-position: left top;
- vertical-align: top;
- text-align: left;
-}
-.bggrayright {
- background-color: #e8e8e8;
- background-position: left top;
- vertical-align: top;
- text-align: right;
-}
div.titlebox {
background: #d4d4d4;
@@ -80,3 +6,4 @@ div.titlebox {
div.titlebox-title {
background: #e8e8e8;
}
+
diff --git a/rt/html/NoAuth/css/3.5-default/misc.css b/rt/html/NoAuth/css/3.5-default/misc.css
index ddb2e68..cf7068a 100755
--- a/rt/html/NoAuth/css/3.5-default/misc.css
+++ b/rt/html/NoAuth/css/3.5-default/misc.css
@@ -46,7 +46,8 @@
%#
%# END BPS TAGGED BLOCK }}}
body {
- font-family: Verdana, sans-serif;
+ /* font-family: Verdana, sans-serif; */
+ font-family: Arial, Verdana, Helvetica, sans-serif;
font-size: 76%;
margin: 0;
/* background-color: white; */
@@ -74,9 +75,11 @@ body {
.evenline { background-color: white; }
.oddline { background-color: #ddd; }
+/*
td {
padding: 0.1em 0.5em 0.1em 0.5em;
}
+*/
.clear { clear: both; }
diff --git a/rt/html/NoAuth/css/3.5-default/titlebox.css b/rt/html/NoAuth/css/3.5-default/titlebox.css
index 79d8040..1e3f7c4 100644
--- a/rt/html/NoAuth/css/3.5-default/titlebox.css
+++ b/rt/html/NoAuth/css/3.5-default/titlebox.css
@@ -51,7 +51,8 @@
.titlebox .titlebox-content {
margin-top: -1px;
- padding: 1em 2em 0.5em 2em;
+ padding: 0.25em .50em 0.125em .50em;
+ /*padding: 1em 2em 0.5em 2em;*/
margin: 0;
/*margin: 1em 2em 0.5em 2em;*/
}
diff --git a/rt/html/Prefs/SearchOptions.html b/rt/html/Prefs/SearchOptions.html
index 7cc71b0..fd292d8 100644
--- a/rt/html/Prefs/SearchOptions.html
+++ b/rt/html/Prefs/SearchOptions.html
@@ -46,7 +46,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title => loc("Search Preferences") &>
+<& /Elements/Header, Title => loc("Ticketing Search Preferences") &>
<& /User/Elements/Tabs,
current_tab => "Prefs/SearchOptions.html",
Title => loc("Search Preferences")
diff --git a/rt/html/Ticket/Create.html b/rt/html/Ticket/Create.html
index 2061b3b..b22a675 100644
--- a/rt/html/Ticket/Create.html
+++ b/rt/html/Ticket/Create.html
@@ -387,10 +387,10 @@ if ((!exists $ARGS{'AddMoreAttach'}) and ($ARGS{'id'} eq 'new')) { # new ticket?
my $actions = {
A => {
- html => q[<a href="#basics" onclick="return switchVisibility('Ticket-Create-basics','Ticket-Create-details');">] . loc('Show basics') . q[</a>],
+ html => q[<a href="#basics" onclick="return switchVisibility('Ticket-Create-basics','Ticket-Create-details');" CLASS="fsblackbutton">] . loc('Show basics') . q[</a>],
},
B => {
- html => q[<a href="#details" onclick="return switchVisibility('Ticket-Create-details','Ticket-Create-basics');">] . loc('Show details') . q[</a>],
+ html => q[<a href="#details" onclick="return switchVisibility('Ticket-Create-details','Ticket-Create-basics');" CLASS="fsblackbutton">] . loc('Show details') . q[</a>],
},
};
</%INIT>
diff --git a/rt/html/Ticket/Display.html b/rt/html/Ticket/Display.html
index 17d00a0..ca69398 100644
--- a/rt/html/Ticket/Display.html
+++ b/rt/html/Ticket/Display.html
@@ -46,11 +46,11 @@
%#
%# END BPS TAGGED BLOCK }}}
<& /Elements/Header,
- Title => loc("#[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
+ Title => loc("Ticket #[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
<& /Ticket/Elements/Tabs,
Ticket => $TicketObj,
current_tab => 'Ticket/Display.html?id='.$TicketObj->id,
- Title => loc("#[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
+ Title => loc("Ticket #[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
<& /Elements/ListActions, actions => \@Actions &>
<& /Elements/Callback, _CallbackName => 'BeforeShowSummary', Ticket => $TicketObj, %ARGS &>
diff --git a/rt/html/User/Prefs.html b/rt/html/User/Prefs.html
index 8c6d5f1..bb38760 100644
--- a/rt/html/User/Prefs.html
+++ b/rt/html/User/Prefs.html
@@ -45,7 +45,7 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title=>loc("Preferences") &>
+<& /Elements/Header, Title=>loc("Ticketing Preferences") &>
<& /User/Elements/Tabs,
current_tab => 'User/Prefs.html',
Title=>loc("Preferences") &>
diff --git a/rt/lib/RT.pm b/rt/lib/RT.pm
index 0d0c0f5..22fb9a1 100644
--- a/rt/lib/RT.pm
+++ b/rt/lib/RT.pm
@@ -68,7 +68,7 @@ use vars qw($VERSION $System $SystemUser $Nobody $Handle $Logger
$MasonSessionDir
);
-$VERSION = '3.6.4';
+$VERSION = '3.6.6';
$CORE_CONFIG_FILE = "/opt/rt3/etc/RT_Config.pm";
$SITE_CONFIG_FILE = "/opt/rt3/etc/RT_SiteConfig.pm";
@@ -161,12 +161,12 @@ EOF
}
eval { require $CORE_CONFIG_FILE };
if ($@) {
- my ($fileuid,$filegid) = (stat($SITE_CONFIG_FILE))[4,5];
+ my ($fileuid,$filegid) = (stat($CORE_CONFIG_FILE))[4,5];
my $fileusername = getpwuid($fileuid);
my $filegroup = getgrgid($filegid);
- my $errormessage = sprintf($message, $SITE_CONFIG_FILE,
+ my $errormessage = sprintf($message, $CORE_CONFIG_FILE,
$fileusername, $filegroup, $filegroup);
- die ("$errormessage '$CORE_CONFIG_FILE'\n$@")
+ die ("$errormessage\n$@")
}
# RT::Essentials mistakenly recommends that WebPath be set to '/'.
@@ -459,6 +459,8 @@ ok ($RT::SystemUser->Name() ne 'noname', "The system user isn't noname");
=cut
+eval "require RT_Vendor";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT_Vendor.pm});
eval "require RT_Local";
die $@ if ($@ && $@ !~ qr{^Can't locate RT_Local.pm});
diff --git a/rt/lib/RT/Transaction_Overlay.pm b/rt/lib/RT/Transaction_Overlay.pm
index 451f9d7..dd1887e 100644
--- a/rt/lib/RT/Transaction_Overlay.pm
+++ b/rt/lib/RT/Transaction_Overlay.pm
@@ -276,7 +276,7 @@ textual part (as defined in RT::I18N::IsTextualContentType). Otherwise,
returns undef.
Takes a paramhash. If the $args{'Quote'} parameter is set, wraps this message
-at $args{'Wrap'}. $args{'Wrap'} defaults to 70.
+at $args{'Wrap'}. $args{'Wrap'} defaults to $RT::MessageBoxWidth - 2 or 70.
If $args{'Type'} is set to C<text/html>, plain texts are upgraded to HTML.
Otherwise, HTML texts are downgraded to plain text. If $args{'Type'} is
@@ -290,6 +290,7 @@ sub Content {
Type => $PreferredContentType,
Quote => 0,
Wrap => 70,
+ Wrap => ( $RT::MessageBoxWidth || 72 ) - 2,
@_
);
@@ -335,7 +336,7 @@ sub Content {
$max = length if ( length > $max );
}
- if ( $max > 76 ) {
+ if ( $max > $args{'Wrap'}+6 ) { # 76 ) {
require Text::Wrapper;
my $wrapper = new Text::Wrapper(
columns => $args{'Wrap'},